$refsで子コンポーネントのメソッドにアクセスしたい


#1

以下のようなファイルを作成し、子コンポーネントのメソッドを実行したいのですが、未定義エラーが発生します。
色々試してみたのですが、原因がわからずここにたどり着きました。

[child-a]の中に[child-b]のコンポーネントを作成し、
[child-a]のボタンをクリックに[child-b]の[action_b()]を実行させたい。というのがやりたいことになります。

ご教授、解決策のほど、よろしくお願いします。

エラーメッセージ

Uncaught TypeError: Cannot read property ‘action_b’ of undefined

index.html

<!DOCTYPE html>
<html>
<head>
...
</head>
<body>
  <div id="app">
        <child-a></child-a>
  </div>
  
</body>
</html>

<script>
const app = new Vue
({
 el : "#app"
 ,components: {
    "child-a" : child_a
  }
})

const child_a =
{ 
  template: 
  `
  <div>
    <button @ckick="action_a">click</button>
    <child-b ref="child"></child-b>
  </div>
  `
  ,data()
  {
  }
  ,methods: 
  {
    action_a()
    {
       this.$refs.child.action_b();
    } 
  }
  ,components: {
    "child-b" : child_b
  }
}

const child_b =
{ 
  template: 
  `
  <div>
    <p>BBBBBBB</p>
  </div>
  `
  ,data()
  {
  }
  ,methods: 
  {
    action_b()
    {
       console.log("action_b","start!");
    } 
  }
}


</script>

記載した内容は、

app
└ child-a
└ child-b
というコンポーネントの配置後の実行時を記載していますが、

app
┝ child-a
└ child-b
という配置でも試した(タグやコンポーネントの記述位置を変更)のですが、同じエラーメッセージが出力されます。

よろしくお願いします。


#2

こんにちは!
なるべくそのままの形で動作するようにしてみました。

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.22/dist/vue.js"></script>
</head>
<body>
  <div id="app">
    <child-a></child-a>
  </div>
</body>
</html>

<script>
  const child_b = { 
    template: `
      <div>
        <p>BBBBBBB</p>
      </div>
    `,
    data: function() {
      return {
      }
    },
    methods: {
      action_b: function() {
       console.log("action_b","start!");
      } 
    }
  }

  const child_a = { 
    template: `
      <div>
        <button @click="action_a">click</button>
        <child-b ref="child"></child-b>
      </div>
    `,
    data: function() {
      return {
      }
    },
    methods: {
      action_a: function() {
       this.$refs.child.action_b();
      } 
    },
    components: {
      "child-b" : child_b
    }
  }

  const app = new Vue({
    el : "#app",
    components: {
      "child-a" : child_a
    }
  })
</script>

修正内容としては以下の通りです。

  • @ckickのtypoを@clickに修正

  • 変数定義の順序を変更
    constはソースコードの上から順番に実行されるため、今回のようにappでchild-aを参照, child-aでchild-bを参照としている場合は、参照時に該当の変数がすでに存在しているようにする必要があります。
    ですが、今回のように複数コンポーネントに切り分けているような場合は、1コンポーネントごとにsfc化し、script文の先頭で必要なコンポーネントを適宜importする方がスマートかと思います。
    詳しくは公式ドキュメントのこちらをご一読ください。