解决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 相关文章推荐
Save a File Using a File Save Dialog Box
Jun 18 Javascript
js实现的日期操作类DateTime函数代码
Mar 16 Javascript
jquery 可拖拽的窗体控件实现代码
Mar 21 Javascript
JS中的this变量的使用介绍
Oct 21 Javascript
js正则表达式replace替换变量方法
May 21 Javascript
从零开始做一个pagination分页组件
Mar 15 Javascript
ES6中的箭头函数实例详解
Apr 06 Javascript
详解Angular2组件之间如何通信
Jun 22 Javascript
jQuery绑定事件方法及区别(bind,click,on,live,one)
Aug 14 jQuery
vue文件树组件使用详解
Mar 29 Javascript
webpack项目轻松混用css module的方法
Jun 12 Javascript
JS/HTML5游戏常用算法之碰撞检测 像素检测算法实例详解
Dec 12 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数组函数序列之array_push() 数组尾部添加一个或多个元素(入栈),返回新长度。
2011/11/07 PHP
php/js获取客户端mac地址的实现代码
2013/07/08 PHP
php导出csv数据在浏览器中输出提供下载或保存到文件的示例
2014/04/24 PHP
php禁止直接从浏览器输入地址访问.php文件的方法
2014/11/04 PHP
Thinkphp关闭缓存的方法
2015/06/26 PHP
php通过两层过滤获取留言内容的方法
2016/07/11 PHP
关于php几种字符串连接的效率比较(详解)
2017/02/22 PHP
phpQuery采集网页实现代码实例
2020/04/02 PHP
JavaScript-世界上误解最深的语言分析
2007/08/12 Javascript
加载jQuery后$冲突的解决办法
2010/07/09 Javascript
ASP.NET jQuery 实例12 通过使用jQuery validation插件简单实现用户注册页面验证功能
2012/02/03 Javascript
event.currentTarget与event.target的区别介绍
2012/12/31 Javascript
Javascript拓展String方法小结
2013/07/08 Javascript
JQuery实现鼠标移动图片显示描述层的方法
2015/06/25 Javascript
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
js中substr,substring,indexOf,lastIndexOf,split,replace的用法详解
2015/11/09 Javascript
基于BootstrapValidator的Form表单验证(24)
2016/12/12 Javascript
JS实现的添加弹出层并完成锁屏操作示例
2017/04/07 Javascript
关于jquery form表单序列化的注意事项详解
2017/08/01 jQuery
详解vue-cli构建项目反向代理配置
2017/09/07 Javascript
BootStrap Validator 根据条件在JS中添加或移除校验操作
2017/10/12 Javascript
Vue使用localStorage存储数据的方法
2019/05/27 Javascript
基于vue实现简易打地鼠游戏
2020/08/21 Javascript
Python 记录日志的灵活性和可配置性介绍
2018/02/27 Python
浅谈python函数调用返回两个或多个变量的方法
2019/01/23 Python
python 绘制拟合曲线并加指定点标识的实现
2019/07/10 Python
python文件路径操作方法总结
2020/12/21 Python
HTML5 CSS3给网站设计带来出色效果
2009/07/16 HTML / CSS
中国酒类在线零售网站:酒仙网
2016/08/20 全球购物
俄罗斯三星品牌商店:GalaxyStore
2020/11/04 全球购物
优秀志愿者事迹材料
2014/02/03 职场文书
《金孔雀轻轻跳》教学反思
2014/04/20 职场文书
经济国贸专业求职信
2014/06/18 职场文书
2015年教师节活动总结
2015/03/20 职场文书
使用vue-element-admin框架从后端动态获取菜单功能的实现
2021/04/29 Vue.js
python 学习GCN图卷积神经网络
2022/05/11 Python