解决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 相关文章推荐
用一段js程序来实现动画功能
Mar 06 Javascript
让ie运行js时提示允许阻止内容运行的解决方法
Oct 24 Javascript
checkbox使用示例
Aug 23 Javascript
jquery处理json数据实例分析
Jun 03 Javascript
JavaScript使用Max函数返回两个数字中较大数的方法
Apr 06 Javascript
jQuery图片轮播插件——前端开发必看
May 31 Javascript
详解RequireJS按需加载样式文件
Apr 12 Javascript
AngularJS 实现购物车全选反选功能
Oct 24 Javascript
详解create-react-app 2.0版本如何启用装饰器语法
Oct 23 Javascript
Vue之beforeEach非登录不能访问的实现(代码亲测)
Jul 18 Javascript
VUE实现强制渲染,强制更新
Oct 29 Javascript
微信小程序scroll-view点击项自动居中效果的实现
Mar 25 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 判断是否是中文/英文/数字示例代码
2013/09/30 PHP
php读取文件内容的方法汇总
2015/01/24 PHP
php单元测试phpunit入门实例教程
2017/11/17 PHP
jQuery版Tab标签切换
2011/03/16 Javascript
无缝滚动改进版支持上下左右滚动(封装成函数)
2012/12/04 Javascript
Js参数值中含有单引号或双引号问题的解决方法
2013/11/06 Javascript
raphael.js绘制中国地图 地图绘制方法
2014/02/12 Javascript
jQuery中nextUntil()方法用法实例
2015/01/07 Javascript
简介JavaScript中Boolean.toSource()方法的使用
2015/06/05 Javascript
JavaScript中0和&quot;&quot;比较引发的问题
2016/05/26 Javascript
JavaScript遍历Json串浏览器输出的结果不统一问题
2016/11/03 Javascript
jQuery中get方法用法分析
2016/12/07 Javascript
利用Console来Debug的10个高级技巧汇总
2018/03/26 Javascript
详解Vue中的scoped及穿透方法
2019/04/18 Javascript
Vue+Express实现登录状态权限验证的示例代码
2019/05/05 Javascript
关于vue利用postcss-pxtorem进行移动端适配的问题
2019/11/20 Javascript
Vue中import from的来源及省略后缀与加载文件夹问题
2020/02/09 Javascript
Vue+Java 通过websocket实现服务器与客户端双向通信操作
2020/09/22 Javascript
vue中解决chrome浏览器自动播放音频和MP3语音打包到线上的实现方法
2020/10/09 Javascript
[06:35]2014DOTA2国际邀请赛 老男孩梦圆西雅图中国军团世界最强
2014/07/22 DOTA
利用python3随机生成中文字符的实现方法
2017/11/24 Python
Flask框架URL管理操作示例【基于@app.route】
2018/07/23 Python
使用python进行拆分大文件的方法
2018/12/10 Python
Python Numpy中数据的常用保存与读取方法
2020/04/01 Python
TensorFlow2.1.0最新版本安装详细教程
2020/04/08 Python
Python Opencv实现单目标检测的示例代码
2020/09/08 Python
详解tensorflow之过拟合问题实战
2020/11/01 Python
运动会开幕式邀请函
2014/02/03 职场文书
《天安门广场》教学反思
2014/04/23 职场文书
党的群众路线教育实践活动对照检查剖析材料
2014/10/09 职场文书
2015年企业新年寄语
2014/12/08 职场文书
环保建议书作文400字
2015/09/14 职场文书
学习商务礼仪心得体会
2016/01/22 职场文书
MySQL命令无法输入中文问题的解决方式
2021/08/30 MySQL
Spring事务管理下synchronized锁失效问题的解决方法
2022/03/31 Java/Android
Win11局域网共享权限在哪里设置? Win11高级共享的设置技巧
2022/04/05 数码科技