Home > Web Front-end > JS Tutorial > How to solve the problem that Vue cannot detect changes in arrays or objects?

How to solve the problem that Vue cannot detect changes in arrays or objects?

亚连
Release: 2018-06-04 16:32:15
Original
2215 people have browsed it

Below I will share with you an article that solves the problem that Vue cannot detect changes in arrays or objects. It has a good reference value and I hope it will be helpful to everyone.

Let’s look at an example:

<!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>
Copy after login

The effect you want to achieve is to click li to see if vm.nymbers[index] exists, and there is no setting. is 1, plus 1 if present.

After clicking, the number was not updated in the view layer. However, it was found through console printing that the data was updated, but the view layer did not detect it in time.

Look at another change:

<!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>
Copy after login

You can see that the view layer here can be updated in time, but why can't it be done when it comes to the array?

Let’s take a look at the official documentation of Vue2.0:

Due to JavaScript limitations, Vue cannot detect the following changed arrays:

When you use the index to directly set an item, for example: vm.items[indexOfItem] = newValue

When you modify the length of the array, for example: vm.items.length = newLength

In order to solve the first type of problem, the following two methods can achieve the same effect as vm.items[indexOfItem] = newValue, and will also trigger status updates:

// Vue.set 
Vue.set(example1.items, indexOfItem, newValue)
Copy after login
// Array.prototype.splice 
example1.items.splice(indexOfItem, 1, newValue)
Copy after login

You can also use vm.$ set instance method, which is just an alias for the global Vue.set.

Or due to JavaScript limitations, Vue cannot detect the addition or deletion of object properties:

var vm = new Vue({
 data: {
 a: 1
 }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
Copy after login

For already created instances, Vue cannot dynamically add root-level responsive properties. However, you can add reactive properties to nested objects using the Vue.set(object, key, value) method. For example, for:

var vm = new Vue({ 
 data: { 
 userProfile: { 
  name: &#39;Anika&#39; 
 } 
 } 
})
Copy after login

Sometimes you may need to assign multiple new properties to an existing object, such as using Object.assign() or _.extend(). In this case, you should create a new object with the properties of both objects. So, if you want to add a new reactive attribute, instead of doing it like this:

Object.assign(this.userProfile, { 
 age: 27, 
 favoriteColor: &#39;Vue Green&#39; 
})
Copy after login

you should do this:

this.userProfile = Object.assign({}, this.userProfile, { 
 age: 27, 
 favoriteColor: &#39;Vue Green&#39; 
})
Copy after login

Therefore, the above example should be changed to :

<!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>
Copy after login

Done!

1.17 Supplement----------------------------------

How to understand "Vue cannot dynamically add root-level responsive properties to already created instances"?

For example:

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;);
Copy after login

The above is the correct approach, but if you do the following, an error will be reported:

Vue.set(vm.data,&#39;sex&#39;,&#39;男&#39;)
Copy after login

Actually , you cannot directly add attributes to data, but you can add attributes to objects in data.

Actually vm.data is undefined.

The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.

Related articles:

NodeJS parent process and child process resource sharing principles and implementation methods

Vue mobile phone number, email regular verification And an example of sending verification code in 60s

Vue implements active click switching method

The above is the detailed content of How to solve the problem that Vue cannot detect changes in arrays or objects?. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template