引言
都知道Vue可以通过 v-model 实现双向数据绑定、响应式跟更新;例如:
双向数据绑定: <input type="text" v-model:value="name">
或者简写形式: <input type="text" v-model="name">
原理
(1)MVVM模型
(2) Vue数据代理
1.data中的属性出现在vm上并能可通过vm调用,便是Object.defineProperty()
方法会通过一个对象(vm)直接在另一个对象(data)上定义新属性,或者修改一个对象的现有属性(读/写),并返回此对象。
2.方便Vue操作data中的数据。
(3)Vue数据劫持
(4) Vue数据监视
这个这是Vue实现数据改变驱动页面更新的关键所在,并不是说以任意方式修改data中的数据都会引起页面视图的改变,比如:
模拟问题
不奏效的原因在于:该行虽然修改了persons数组,但是vue没有监测到!
为啥没有监测到数组的数据?
简而言之,对于直接修改persons数组的第0项的值,不会经过Vue数据代理添加 geter/seter方法,也没有后面这俩方法对相应属性的数据劫持监测变化。
解决办法:1.用数组能够改变原数组的七个API;
为啥用这七个API就可以,因为这是被vue重新包装后的,包装的作用就是使其重新解析模版生产虚拟dom等等
2.如果要用其他的API如 filter 等,需用新数组替换旧数组。
对比:
而能奏效的方法,均可通过Vue实现下图的流程。
列表渲染
参考链接:列表渲染 — Vue.js
补充
通过重写数组的Array.prototype对应的方法,具体来说就是重新指定要操作数组的prototype,并重新该prototype中对应上面的7个数组方法,通过下面代码简单了解下实现原理:
const methods = ['pop','shift','unshift','sort','reverse','splice', 'push'];
// 复制Array.prototype,并将其prototype指向Array.prototype
let proto = Object.create(Array.prototype);
methods.forEach(method => {
proto[method] = function () { // 重写proto中的数组方法
Array.prototype[method].call(this, ...arguments);
viewRender() // 视图更新
function observe(obj) {
if (Array.isArray(obj)) { // 数组实现响应式
obj.__proto__ = proto; // 改变传入数组的prototype
return;
}
if (typeof obj === 'object') {
... // 对象的响应式实现
}
}
}
})
活动地址:毕业季·进击的技术er