Vue が配列またはオブジェクトの変更を検出できない問題を解決するにはどうすればよいですか?

亚连
リリース: 2018-06-04 16:32:15
オリジナル
2179 人が閲覧しました

以下に、Vue が配列またはオブジェクトの変更を検出できない問題を解決する記事を共有します。これは優れた参考値なので、皆さんのお役に立てれば幸いです。

例を見てみましょう:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
 <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script>
 <style>
 li:hover {
  cursor: pointer;
 }
 </style>
</head>
<body>
 <p class="wrap">
 <ul>
  <li v-for="item,index in items" v-on:click="handle(index)">
  <span>{{item.name}}</span>
  <span>{{numbers[index]}}</span>
  </li>
 </ul>
 </p>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  numbers: [],
  items: [
   {name: &#39;jjj&#39;},
   {name: &#39;kkk&#39;},
   {name: &#39;lll&#39;},
  ]
  },
  methods: {
  handle: function (index) {
   // WHY: 更新数据,view层未渲染,但通过console这个数组可以发现数据确实更新了
   if (typeof(this.numbers[index]) === "undefined" ) {
   // 注:下面这么设置是可以的。例如 
   // var arr = [];
   // arr[3]=3;
   // console.log(arr) //[empty × 3, 3]
    this.numbers[index] = 1; 
   // this.numbers.splice(index,0,1) //用splice方法能同步显示,但得不到想要的效果
   } else {
    this.numbers[index]++;
   // this.numbers.splice(index,1,this.numbers[index]++)
   }
  // console.log(this.numbers)
  }
  }
 });
 
 </script>
</body>
</html>
ログイン後にコピー

実現したい効果は、li をクリックして vm.nymbers[index] が存在するかどうかを確認することです。存在しない場合は 1 に設定します。 、1を追加します。

クリック後、ビューレイヤーでは数値が更新されませんでしたが、コンソールの印刷により、データが更新されたことがわかりましたが、ビューレイヤーではそれを検出できませんでした。

別の変更を見てください:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
 <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script>
 <style>
 li:hover {
  cursor: pointer;
 }
 </style>
</head>
<body>
 <p class="wrap">
 <ul>
  <li v-for="item,index in items" v-on:click="handle(index)">
  <span>{{item.name}}</span>
  <!--<span>{{numbers[index]}}</span>-->
  </li>
 </ul>
 </p>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  // numbers: [],
  items: [
   {name: &#39;jjj&#39;},
   {name: &#39;kkk&#39;},
   {name: &#39;lll&#39;},
  ]
  },
  methods: {
  handle: function (index) {
   // 不是数组,这里更新数据就可以直接在view层渲染
   this.items[index].name += " success";
  // console.log(this.numbers)
  }
  }
 });
 </script>
</body>
</html>
ログイン後にコピー

ここのビューレイヤーは時間内に更新できることがわかりますが、配列に関してはなぜ更新できないのでしょうか?

Vue2.0 の公式ドキュメントを参照してください:

JavaScript の制限により、Vue は次の変更された配列を検出できません:

インデックスを使用して項目を直接設定する場合 (例: vm.items) [indexOfItem ] = newValue

配列の長さを変更する場合、たとえば: vm.items.length = newLength

最初のタイプの問題を解決するには、次の 2 つの方法で vm と同じ効果を達成できます。 items[indexOfItem] = newValue 、ステータス更新もトリガーします:

// Vue.set 
Vue.set(example1.items, indexOfItem, newValue)
ログイン後にコピー
// Array.prototype.splice 
example1.items.splice(indexOfItem, 1, newValue)
ログイン後にコピー

また、グローバル Vue.set のエイリアスである vm.$set インスタンス メソッドを使用することもできます。

または、JavaScript の制限により、Vue はオブジェクト プロパティの追加または削除を検出できません:

var vm = new Vue({
 data: {
 a: 1
 }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
ログイン後にコピー

すでに作成されたインスタンスの場合、Vue はルートレベルの応答プロパティを動的に追加できません。ただし、Vue.set(object, key, value) メソッドを使用して、ネストされたオブジェクトにリアクティブ プロパティを追加できます。例:

var vm = new Vue({ 
 data: { 
 userProfile: { 
  name: &#39;Anika&#39; 
 } 
 } 
})
ログイン後にコピー

場合によっては、Object.assign() や _.extend() を使用するなど、複数の新しいプロパティを既存のオブジェクトに割り当てる必要があります。この場合、両方のオブジェクトのプロパティを使用して新しいオブジェクトを作成する必要があります。したがって、新しい応答属性を追加したい場合は、次のようにするのではなく:

Object.assign(this.userProfile, { 
 age: 27, 
 favoriteColor: &#39;Vue Green&#39; 
})
ログイン後にコピー

次のようにする必要があります:

this.userProfile = Object.assign({}, this.userProfile, { 
 age: 27, 
 favoriteColor: &#39;Vue Green&#39; 
})
ログイン後にコピー

したがって、上記の例は次のように変更する必要があります:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>vue</title>
 <script src="https://unpkg.com/vue@2.3.3/dist/vue.js"></script>
 <style>
 li:hover {
  cursor: pointer;
 }
 </style>
</head>
<body>
 <p class="wrap">
 <ul>
  <li v-for="item,index in items" v-on:click="handle(index)">
  <span>{{item.name}}</span>
  <span>{{numbers[index]}}</span>
  </li>
 </ul>
 </p>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  numbers: [],
  items: [
   {name: &#39;jjj&#39;},
   {name: &#39;kkk&#39;},
   {name: &#39;lll&#39;},
  ]
  },
  methods: {
  handle: function (index) {
   if (typeof(this.numbers[index]) === "undefined" ) {
    this.$set(this.numbers, index, 1);  //(arr,index,newvalue)
   } else {
    this.$set(this.numbers, index, ++this.numbers[index]);
   }
  }
  }
 });
 </script>
</body>
</html>
ログイン後にコピー

完了!

1.17補足---------------------------------

「ある人にとって」の理解方法インスタンスが作成されているため、Vue はルートレベルのリアクティブ プロパティを動的に追加できません。」

例:

var vm=new Vue({ 
 el:&#39;#test&#39;, 
 data:{ 
  //data中已经存在info根属性 
  info:{ 
   name:&#39;小明&#39; 
  } 
 } 
}); 
//给info添加一个性别属性 
Vue.set(vm.info,&#39;sex&#39;,&#39;男&#39;);
ログイン後にコピー

上記は正しいアプローチですが、次のことを実行するとエラーが報告されます:

Vue.set(vm.data,&#39;sex&#39;,&#39;男&#39;)
ログイン後にコピー

実際には、データに属性を直接追加することはできませんが、属性を追加することはできますデータ内のオブジェクトに。

実際には vm.data は未定義です。

上記は私があなたのためにまとめたものです。

関連記事:

NodeJSの親プロセスと子プロセスのリソース共有原理と実装方法

Vueの携帯電話番号、メール定期認証、60秒送信認証コードの例

Vueがアクティブクリック切り替え方式を実装

以上がVue が配列またはオブジェクトの変更を検出できない問題を解決するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート