1. ホーム
  2. javascript

[解決済み] [Vue警告]: プロパティまたはメソッドがインスタンスで定義されておらず、レンダリング中に参照される

2022-05-05 14:55:15

質問

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];
    }
  }
});

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

[Vue warn]: プロパティまたはメソッド "changeSetting" はインスタンスで定義されていませんが、レンダリング中に参照されます。必ずdataオプションでreactive dataプロパティを宣言してください。(以下の場所で見つかります <MainTable> )

解決方法は?

問題点

<ブロッククオート

[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 コンポーネントは、ダム/プレゼン テーション・コンポーネントにします。( ここで が何かわからない場合は、これを読んでみてください。) スマート/コンテナ要素はロジックを担当します。質問にある例では、ルートコンポーネントはスマート/コンテナ要素になります。このアーキテクチャでは、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
    },
  },
}),

上記は、何をすべきかの良いアイデアを与え、問題解決を始めるのに十分であるべきです。