web-dev-qa-db-ja.com

[警告]:プロパティまたはメソッドはインスタンスで定義されていませんが、レンダリング中に参照されます。

var MainTable = Vue.extend({
  template: "<ul>" +
    "<li v-for='(set,index) in settings'>" +
    "{{index}}) " +
    "{{set.title}}" +
    "<button @click='changeSetting(index)'> Info </button>" +
    "</li>" +
    "</ul>",
  data: function() {
    return data;
  }
});

Vue.component("main-table", MainTable);

data.settingsSelected = {};
var app = new Vue({
  el: "#settings",
  data: data,
  methods: {
    changeSetting: function(index) {
      data.settingsSelected = data.settings[index];
    }
  }
});

上記のコードでは、ボタンをクリックしたときに以下のエラーが発生します。

[警告]:プロパティまたはメソッド "changeSetting"はインスタンスに定義されていませんが、レンダリング中に参照されます。 dataオプションでは必ずリアクティブデータプロパティを宣言してください。 (<MainTable>にあります)

56

問題

[Vue warn]: Property or method "changeSetting" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in <MainTable>)

changeSettingメソッドがMainTableコンポーネントで参照されているため、エラーが発生しています。

    "<button @click='changeSetting(index)'> Info </button>" +

ただし、changeSettingメソッドはMainTableコンポーネントでは定義されていません。ここではルートコンポーネントで定義されています:

var app = new Vue({
  el: "#settings",
  data: data,
  methods: {
    changeSetting: function(index) {
      data.settingsSelected = data.settings[index];
    }
  }
});

覚えておく必要があるのは、プロパティとメソッドはそれらが定義されている範囲内でしか参照できないということです。

親テンプレート内のすべてのものは親スコープでコンパイルされます。子テンプレート内のすべてのものが子スコープ内でコンパイルされます

Vueの ドキュメント でコンポーネントのコンパイル範囲についてもっと読むことができます。

私はそれについて何ができますか?

これまでのところ、正しいスコープで物事を定義することについては多くの話がありましたので、修正は単にchangeSetting定義をMainTableコンポーネントに移動することですか?

それはそれほど単純に思えますが、ここに私が推薦するものがあります。

あなたはおそらくあなたのMainTableコンポーネントをダム/プレゼンテーションコンポーネントにしたいと思うでしょう。 ( ここで はあなたがそれが何であるかわからない場合に読むべきものですがtl; drはコンポーネントがただ何かをレンダリングする責任があるということです - いいえ論理)。 smart/container要素がロジックを担当します - あなたの質問で与えられた例では、ルートコンポーネントはsmart/containerコンポーネントになります。このアーキテクチャでは、コンポーネントが対話するためにVueの親子通信方法を使用できます。 小道具 を介してMainTableのデータを渡し、 イベントを介してMainTableからその親にユーザーアクションを送信します これは次のようになります。

Vue.component('main-table', {
  template: "<ul>" +
    "<li v-for='(set, index) in settings'>" +
    "{{index}}) " +
    "{{set.title}}" +
    "<button @click='changeSetting(index)'> Info </button>" +
    "</li>" +
    "</ul>",
  props: ['settings'],
  methods: {
    changeSetting(value) {
      this.$emit('change', value);
    },
  },
});


var app = new Vue({
  el: '#settings',
  template: '<main-table :settings="data.settings" @change="changeSetting"></main-table>',
  data: data,
  methods: {
    changeSetting(value) {
      // Handle changeSetting
    },
  },
}),

上記は、あなたに何をすべきかについての良い考えを与え、あなたの問題を解決するためにキックスタートするのに十分であるべきです。

71
Wing