Object.defineproperty()和proxy

数据绑定

“数据绑定”的关键在于监听数据的变化,可是对于这样一个对象:var obj = {value: 1},我们该怎么知道 obj 发生了改变呢?

Object.defineProperty
  • ES5 提供了 Object.defineProperty 方法,该方法可以在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。
  • 语法:Object.defineProperty(obj, prop, descriptor)
  • 参数
    • obj: 要在其上定义属性的对象
    • prop: 要定义或修改的属性的名称
    • descriptor: 将被定义或修改的属性的描述符
Proxy
  • ES6提供了 Proxy,可以重定义更多的行为,比如 in、delete、函数调用等更多行为。
  • Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
  • 语法:var proxy = new Proxy(target, handler)
  • 复制代码proxy 对象的所有用法,都是上面这种形式,不同的只是handler参数的写法。
    • new Proxy()表示生成一个Proxy实例
    • target参数表示所要拦截的目标对象
    • handler参数也是一个对象,用来定制拦截行为
区别

使用Object.defineProperty的时候,我们遇到的问题有:

  • 一次只能对一个属性进行监听,需要遍历来对所有属性监听
  • 在遇到一个对象的属性还是一个对象的情况下,需要递归监听
  • 对于对象的新增属性,需要手动监听
  • 对于数组通过push、unshift方法增加的元素,也无法监听
Object.defineProperty简单实现
<body>
    <input id="input" type="text" />
	<div id="text"></div>
</body>
// 简单粗暴的说明双向绑定的原理
const input = document.getElementById("input");
const text = document.getElementById("text");
const data = { value: "" };
Object.defineProperty(data, value, {
    get: function(){
        return input.value;
    },
    set: function(newVal){
        text.innerHTML = newVal;
        input.value = newVal;
    }
});
input.onkeyup = function(e){
    data.value = e.target.value;
}
实现mvvm的双向绑定

是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。就必须要实现以下几点:

  • 实现一个数据监听器Observer,能够对数据对象的所有属性进行监听,如有变动可拿到最新值并通知订阅者
  • 实现一个指令解析器Compile,对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数
  • 实现一个Watcher,作为连接Observer和Compile的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图
  • mvvm入口函数,整合以上三者
具体实现
function defineReactive(obj, key, val){
    let dep = new Dep(); // 为属性添加订阅者
    Object.defineProperty(obj, key, {
        get: function () { 
            if(Dep.target){
                dep.addSub(Dep.target); // 添加订阅者到dep实例对象
            }
            return val; // 返回监听到的值
         },
        set: function (newVal) {
            if(newVal === val) return;
            val = newVal; // 写入新的val值
            dep.notify(); // 作为发布者发布通知
        }
    });
}
function observe(obj, vm) { 
    Object.keys(obj).forEach((key) => {
        defineReactive(vm, key, obj[key]);
    })
 }
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力不熬夜的小喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值