解决Vue不能检测数组或对象变动的问题


Posted in Javascript onFebruary 24, 2018

来看一个实例:

<!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>
 <div 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>
 </div>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  numbers: [],
  items: [
   {name: 'jjj'},
   {name: 'kkk'},
   {name: 'lll'},
  ]
  },
  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。

点击之后数字并没有在view层更新,而通过console打印发现数据更新了,只是view层没有及时的检测到。

再看一个改动之后的:

<!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>
 <div 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>
 </div>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  // numbers: [],
  items: [
   {name: 'jjj'},
   {name: 'kkk'},
   {name: 'lll'},
  ]
  },
  methods: {
  handle: function (index) {
   // 不是数组,这里更新数据就可以直接在view层渲染
   this.items[index].name += " success";
  // console.log(this.numbers)
  }
  }
 });
 </script>
</body>
</html>

可以看到这里的view层能及时得到更新,但是到了数组哪里为什么就不可以了呢?

来看Vue2.0官方的文档说明:

由于 JavaScript 的限制,Vue 不能检测以下变动的数组:

当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue

当你修改数组的长度时,例如:vm.items.length = newLength

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新:

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

你还可以使用 vm.$set 实例方法,它只是全局 Vue.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: 'Anika' 
 } 
 } 
})

有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

Object.assign(this.userProfile, { 
 age: 27, 
 favoriteColor: 'Vue Green' 
})

应该这样做:

this.userProfile = Object.assign({}, this.userProfile, { 
 age: 27, 
 favoriteColor: 'Vue Green' 
})

因此,上面例子应该改为:

<!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>
 <div 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>
 </div>
 <script>
 var vm = new Vue({
  el: ".wrap",
  data: {
  numbers: [],
  items: [
   {name: 'jjj'},
   {name: 'kkk'},
   {name: 'lll'},
  ]
  },
  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:'#test', 
 data:{ 
  //data中已经存在info根属性 
  info:{ 
   name:'小明' 
  } 
 } 
}); 
//给info添加一个性别属性 
Vue.set(vm.info,'sex','男');

上面是正确做法,下面的做法的话就会报错了:

Vue.set(vm.data,'sex','男')

实际上,不能直接在data上增加属性,但可以在data里的对象上增加属性。

实际上vm.data是undefined。

以上这篇解决Vue不能检测数组或对象变动的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript之锁定表格栏位
Jun 29 Javascript
使用jQuery fancybox插件打造一个实用的数据传输模态弹出窗体
Jan 15 Javascript
顶部缓冲下拉菜单导航特效的JS代码
Aug 27 Javascript
超链接的禁用属性Disabled使用示例
Jul 31 Javascript
使用Node.js实现HTTP 206内容分片的教程
Jun 23 Javascript
bootstrap实现弹窗和拖动效果
Jan 03 Javascript
JavaScript中ES6 Babel正确安装过程
Jul 18 Javascript
打通前后端构建一个Vue+Express的开发环境
Jul 17 Javascript
Vue动态路由缓存不相互影响的解决办法
Feb 19 Javascript
在element-ui的select下拉框加上滚动加载
Apr 18 Javascript
关于element-ui的隐藏组件el-scrollbar的使用
May 29 Javascript
全网小程序接口请求封装实例代码
Nov 06 Javascript
vue将对象新增的属性添加到检测序列的方法
Feb 24 #Javascript
jQuery实现碰到边缘反弹的动画效果
Feb 24 #jQuery
vue cli webpack中使用sass的方法
Feb 24 #Javascript
vue-cli常用设置总结
Feb 24 #Javascript
JS处理一些简单计算题
Feb 24 #Javascript
jQuery 改变P标签文本值方法
Feb 24 #jQuery
jQuery实现标签子元素的添加和赋值方法
Feb 24 #jQuery
You might like
深入理解PHP中的Streams工具
2015/07/03 PHP
PHP实现事件机制的方法
2015/07/10 PHP
判断、添加和删除WordPress置顶文章的相关PHP函数小结
2015/12/10 PHP
jQuery+ajax中getJSON() 用法实例
2014/12/22 Javascript
在Python中使用glob模块查找文件路径的方法
2015/06/17 Javascript
浅谈javascript中replace()方法
2015/11/10 Javascript
设计模式中的facade外观模式在JavaScript开发中的运用
2016/05/18 Javascript
Jquery针对tr td的一些实用操作方法(必看篇)
2016/10/05 Javascript
解决bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题
2017/06/05 Javascript
MUI实现上拉加载和下拉刷新效果
2017/06/30 Javascript
JavaScript自执行函数和jQuery扩展方法详解
2017/10/27 jQuery
layer弹窗在键盘按回车将反复刷新的实现方法
2019/09/25 Javascript
使用 JavaScript 创建并下载文件(模拟点击)
2019/10/25 Javascript
Vue+elementUI实现多图片上传与回显功能(含回显后继续上传或删除)
2020/03/23 Javascript
Bootstrap简单实用的表单验证插件BootstrapValidator用法实例详解
2020/03/29 Javascript
vue实现打地鼠小游戏
2020/08/21 Javascript
python使用xmlrpc实例讲解
2013/12/17 Python
举例详解Python中循环语句的嵌套使用
2015/05/14 Python
用python找出那些被“标记”的照片
2017/04/20 Python
python flask实现分页效果
2017/06/27 Python
Python解析json之ValueError: Expecting property name enclosed in double quotes: line 1 column 2(char 1)
2017/07/06 Python
Python实现比较扑克牌大小程序代码示例
2017/12/06 Python
python矩阵/字典实现最短路径算法
2019/01/17 Python
解决Django生产环境无法加载静态文件问题的解决
2019/04/23 Python
如何利用Pyecharts可视化微信好友
2019/07/04 Python
Python爬虫之爬取淘女郎照片示例详解
2020/07/28 Python
python批量合成bilibili的m4s缓存文件为MP4格式 ver2.5
2020/12/01 Python
美国女孩洋娃娃店:American Girl
2017/10/24 全球购物
意大利婴儿产品网上商店:Mukako
2018/10/14 全球购物
北京SQL新华信咨询
2016/09/30 面试题
数控专业毕业生自荐信范文
2014/03/04 职场文书
学校联谊协议书
2014/09/16 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
合同范本之电脑出租
2019/08/13 职场文书
python实现大文本文件分割成多个小文件
2021/04/20 Python
Java实现多线程聊天室
2021/06/26 Java/Android