Vue.js 是一个提供了 MVVM(Model-View-ViewModel ) 风格的双向数据绑定、数据层和视图层通过DOM监听和Data绑定的方式,实现View 和 Model的一致性。
view层和model层之间通过 ViewModel也就是Vue实例绑定在一起实现数据驱动,免去了频繁更新Dom的操作。MVVM实现的原理是用defineProperty方法进行数据劫持(拦截处理数据),即拦截目标属性定义给目标对象(要操作的对象,为这个对象定义属性),并给目标属性一定的特性。再通过发布订阅的方式对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者,执行更新DOM的操作。
<body>
<div id="app">
<h2>{
{msg}}</h2>
</div>
<script>
const data = {
msg: "hello world"
}
let vm = {} //模拟Vue实例对象
Object.defineProperty(vm, 'msg', {
get() {
console.log('get', data.msg);
},
set(newValue) {
console.log('set', newValue);
if (newValue == data.msg) {
return
}
data.msg = newValue
}
})
console.log(vm.msg);//get方法获取数据
vm.msg = 'hello vue'; //set方法设置数据
</script>
</body>
但是这个方法不完善,因为当data中包含多属性是就无法进行获取或者设置,所以当data中还有对象的时候就应该遍历data
const data ={
name: "zhangsan",
age: 18,
}
//模拟vue对象
let vm = {}
function handleData(data) {
//遍历data中的属性
Object.keys(data).forEach((key) => {
//对每个属性进行数据劫持
// 参数:对象 属性 对象增加的描述
Object.defineProperty(vm, key,// key就是data里的动态属性
{
get() {
console.log('get', data[key]);
},
set(newValue) {
console.log('set', newValue);
if (newValue === data[key]) {
return
}
data[key] = newValue
document.querySelector('#app').textContent = data[key]
}
})
})
}
handleData(data);
如果data中包含多属性,对象中还有多属性就要循环递归遍历,实现起来就很麻烦。 Vue3引入proxy代理监听变化之后就可以简单高效的拦截数据。
<script>
const data = {
name: "zhangsi",