vue数据双向绑定原理,即 MVVM 原理

一、结论

  • vue2.0,通过ES5中的 defineProperty 实现数据双向绑定
  • vue3.0,通过ES6中的 Proxy 实现数据双向绑定

二、vue2.0原理

2-1、实现步骤

第一步:声明一个对象,并克隆该对象
let obj={
     name:""
};
let newObj=JSON.parse(JSON.stringify(obj))
第二步:通过 Object.defineProperty 劫持 setget
 Object.defineProperty(obj,"name",{
      get(){
          return newObj.name;
      },
     set(val){
         newObj.name=val;
         observer();//调用第三步中封装的方法,数据变化时修改视图内容
     }
})
第三步:封装一个方法,数据变化时修改视图内容。同时监听页面变化,并修改数据。
function observer(){ //(奥博惹窝)观察者
        divName.innerHTML= obj.name;
        inpName.value = obj.name;
 }

inpName.oninput=function(){
         obj.name=this.value;//this指向input输入框
}

2-2、完整代码示例

<body>
    姓名: <div id="divName"></div>
    <br>
    <input id="inpName" type="text">
    
    <script>
        let obj={
            name:""
        };

        let newObj=JSON.parse(JSON.stringify(obj));//克隆对象
        // defineProperty,给对象定义属性
        Object.defineProperty(obj,"name",{
            // 获取obj.name时会触发get
            get(){
                return newObj.name;//必须有一个返回值,否则通过obj.name获取到的值就是underfind
                // return obj.name;//错误用法。如果使用obj.name,会陷入死循环,因为obj.name就是获取值,会触发get
            },
            // 给obj.name赋值时会触发set
            set(val){
                if(val===newObj.name) return;
                newObj.name=val;//当obj.name值修改时,同步修改newObj
                observer()
            }
        })

		// 修改数据
        setTimeout(()=>{
         obj.name="张三"
        },1000)

        // 数据的更改,影响视图的变化。相当于vue中的双大括号插值法{{}}
        function observer(){ //奥博惹窝,观察者
            divName.innerHTML= obj.name;
            inpName.value= obj.name;
        }

        // 视图的变化,影响数据的更改。相当于vue中的v-model
        inpName.oninput=function(){
            obj.name=this.value;//this指向input输入框
        }
    </script>
</body>

2-3、vue2.0通过defineProperty实现数据双向绑定的问题

    1. 需要对原始数据克隆。
    1. 需要分别给对象中的每一个属性设置监听。
      • Vue文档有这么一句话:如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。
      • 所以在vue中有一个问题是,data中的对象,如果刚开始没有定义某个属性,后来通过 “对象.属性” 这种方法给对象添加了这个属性,那么vue是没有对这个属性进行监听的。
      • 解决方法是通过$set方法给对象添加属性,this.$set(this.obj,'sex', '男')Vue.set(this.obj,'sex', '男')

二、vue3.0原理

3-1、原理: 通过Proxy劫持getset

let obj={};
 obj = new Proxy(obj,{ //Proxy(泼可谁)
      get(target,prop){
           return target[prop];
     },
      set(target,prop,value){
          target[prop]=value;
          observer();//修改数据时,修改视图内容
      }
 })

其他步骤和vue2.0类似。

3-2、完整代码示例

<body>
   姓名: <div id="divName"></div>
   <br>
   <input id="inpName" type="text">
   
   <script>
       let obj={};
       obj  = new Proxy(obj,{
           get(target,prop){
               return target[prop];
           },
           set(target,prop,value){
               target[prop]=value;
               observer();//修改数据时,修改视图内容
           }
       })

       // 修改数据
       setTimeout(()=>{
        obj.name="张三"
       },1000)

        // 数据的更改,影响视图的变化。相当于vue中的双大括号插值法{{}}
        function observer(){ 
           divName.innerHTML= obj.name;
           inpName.value= obj.name;
       }

       // 视图的变化,影响数据的更改。相当于vue中的v-model
       inpName.oninput=function(){
           obj.name=this.value;//this指向input输入框
       }
   </script>
</body>
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值