扫码关注官方订阅号
在vuejs官方文档中看到:
因为 JavaScript 的限制,Vue.js 不能检测到下面数组变化:
直接用索引设置元素,如 vm.items[0] = {};
vm.items[0] = {};
修改数据的长度,如 vm.items.length = 0
vm.items.length = 0
据说vuejs是遍历对象的所有属性和方法加上钩子,为什么无法检测到上面这两种变化。
小伙看你根骨奇佳,潜力无限,来学PHP伐。
是这样的,你console.log一下跟vue绑在一起的data里面属性,你会发现那些打印出来多了两个东西:
setter
getter
没错,vue检测数组变动靠的就是这两个属性而这两个属性,根据vue文档的说法,它是使用了js原生的Object.defineProperty()(其实准确来讲应该是es的东西)简单地讲,就是js属性的属性。。。怎么那么别扭。。。就是描述Array或者Json等Object类型里面的值的属性,比如一个arr=[1,2,3,4],属性的属性就是里面的1具有的属性。。。而且还有两个:数据属性和访问器属性。比如数据属性中的 Enumberable,如果它为false,那么即使它描述的那个属性存在于json里面,也不会被for-in遍历到。
Object.defineProperty()
arr=[1,2,3,4]
好,回到正题,也就是vue对数组的检测方法它使用是Object类型底层的访问器属性来检测数组变动的。访问器属性存在两个方法(姑且叫做方法吧,原文是叫attribute,但翻译成属性的话感觉太乱了。。而它们的作用又如同面向对象里面的方法一样)
Get :在读取时调用的函数。默认值为undefined
Set :在写入时调用的函数,默认值为undefined
Vue的数组检测变动就基于上面这两个方法。然而,都说了是es底层定义的东西,js是不可能直接就修改访问上面的Get和Set,必须通过Object.defineProperty这个方法进行修改:
var json={ a:1 }; /*当json.a变动时打印修改信息*/ Object.defineProperty(json,'a',{ set:function(newValue){ console.log(this.value+'->'+newValue) }, get:function(){ console.log(this.value) } })
据说,第一个实现Object.defineProperty方法的浏览器是IE8,想不到吧,渣渣IE居然是第一个实现的。。。这也是为什么vuejs不支持ie8以下的垃圾ie了的原因了。
而且,vue为了检测push这些操作造成的数组变动,都是将这些Api重新封装了一遍的。。。所以当你直接 vm.items[0]={}这样的时候,vue根本没法给你做一个Object.defineProperty处理,自然也搞不出setter和getter,自然无法检测数组变动。。。
vm.items[0]={}
=========2016年9月19日15:51:17 补充==========首先更正我的一个错误,就是之前我说console.log跟vue绑定的数组,但是我自己试了一下发现是json才存在getter和setter,数组里面没有setter和getter。只有一个__ob__,看了一下1.026的源码,vue封装的数组方法都在里面。那这个setter和getter是什么时候生成的,文档里说了,是在实例初始化的时候。当然你使用vue数组方法进行数组修改的时候,也会触发这个Object.defineProperty的访问器属性。所以按照文档说的,用$set这个方法代替索引赋值,$remove方法清空数组
Object.defineProperty
$set
$remove
vue不能直接检测数组变化,要用vue封装好的数组方法
移步:https://vuejs.org.cn/guide/li...
微信扫码关注PHP中文网服务号
QQ扫码加入技术交流群
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
PHP学习
技术支持
返回顶部
是这样的,你console.log一下跟vue绑在一起的data里面属性,你会发现那些打印出来多了两个东西:
setter
getter
没错,vue检测数组变动靠的就是这两个属性
而这两个属性,根据vue文档的说法,它是使用了js原生的
Object.defineProperty()(其实准确来讲应该是es的东西)简单地讲,就是js属性的属性。。。怎么那么别扭。。。就是描述Array或者Json等Object类型里面的值的属性,比如一个
arr=[1,2,3,4],属性的属性就是里面的1具有的属性。。。而且还有两个:数据属性和访问器属性。比如数据属性中的 Enumberable,如果它为false,那么即使它描述的那个属性存在于json里面,也不会被for-in遍历到。
好,回到正题,也就是vue对数组的检测方法
它使用是Object类型底层的访问器属性来检测数组变动的。
访问器属性存在两个方法(姑且叫做方法吧,原文是叫attribute,但翻译成属性的话感觉太乱了。。而它们的作用又如同面向对象里面的方法一样)
Get :在读取时调用的函数。默认值为undefined
Set :在写入时调用的函数,默认值为undefined
Vue的数组检测变动就基于上面这两个方法。
然而,都说了是es底层定义的东西,js是不可能直接就修改访问上面的Get和Set,必须通过Object.defineProperty这个方法进行修改:
据说,第一个实现Object.defineProperty方法的浏览器是IE8,想不到吧,渣渣IE居然是第一个实现的。。。这也是为什么vuejs不支持ie8以下的垃圾ie了的原因了。
而且,vue为了检测push这些操作造成的数组变动,都是将这些Api重新封装了一遍的。。。
所以当你直接
vm.items[0]={}这样的时候,vue根本没法给你做一个Object.defineProperty处理,自然也搞不出setter和getter,自然无法检测数组变动。。。=========2016年9月19日15:51:17 补充==========
首先更正我的一个错误,就是之前我说console.log跟vue绑定的数组,但是我自己试了一下发现是json才存在getter和setter,数组里面没有setter和getter。只有一个__ob__,看了一下1.026的源码,vue封装的数组方法都在里面。
那这个setter和getter是什么时候生成的,文档里说了,是在实例初始化的时候。当然你使用vue数组方法进行数组修改的时候,也会触发这个
Object.defineProperty的访问器属性。所以按照文档说的,用
$set这个方法代替索引赋值,$remove方法清空数组vue不能直接检测数组变化,要用vue封装好的数组方法
移步:https://vuejs.org.cn/guide/li...