用vue的双向绑定简单实现一个todo - list的示例代码

  

<强>前言
  

  

最近在学习vue框架的基本原理,看了一些技术博客以及一些对vue源码的简单实现,对数据代理,数据劫持,模板解析,变异数组方法,双向绑定有了更深的理解。于是乎,尝试着去实践自己学到的知识,用vue的一些基本原理实现一个简单的todo - list,完成对深度复杂对象的双向绑定以及对数组的监听,加深了对vue基本原理的印象。

  

github地址:todo - list

  

<强>学习链接
  

  

前排感谢以下文章,对我理解vue的基本原理有很大的帮助!

  

剖析vue实现原理,自己动手实现mvvm DMQ 

  

对vue早期源码的理解,梁少峰
  

  

<>强实现效果

  

用vue的双向绑定简单实现一个todo - list的示例代码

  

<强>数据代理
  

  

1。简单介绍数据代理

  

正常情况下,我们都会把数据写在数据里面,如下面所示

        var vm=new Vue ({   埃尔:“#应用”,   数据:{   标题:“hello world”   }   方法:{   changeTitle:函数(){   这一点。title=澳愫胿ue”   }   }   })   console.log (vm.title)//癶ello world”或“你好vue”   之前      

如果没有数据代理,而我们又要修改数据里面的标题的话,方法里面的changeTitle只能这样修改成<代码> this.data。title=澳愫胿ue”> console.log (vm.data.title) 数据代理就是这样的功能。

  

<强> 2。实现原理

  

通过遍历数据里面的属性,将每个属性通过object.defineProperty()设置getter和setter,将数据里面的每个属性都复制到与数据同级的对象里。

  

(对应上面的示例代码)

  

, 用vue的双向绑定简单实现一个todo - list的示例代码

  

触发这里的getter将会触发数据里面对应属性的getter,触发这里的setter将会触发数据里面对应属性的setter,从而实现代理。实现代码如下:

        var自我=;//这个vue实为例,即vm   种(this.data) .forEach(函数(关键){   Object.defineProperty(关键,{//1晏?即vm.title   可列举的:假的,   可配置:没错,   得到:getter函数(){   返回self.data(例子);//触发对应的数据(关键)的getter   },   设置:setter函数(newVal) {   自我。数据(关键)=newVal;//触发对应的数据(关键)的setter   }   });   }   之前      

对object.defineProperty不熟悉的小伙伴可以在MDN的文档(链接)学习一下
  

  

<强>双向绑定
  

  
      <李>数据变动——→李视图更新   <李>视图更新(输入、textarea)——比;数据变动
      李   
  

<代码>视图更新——比;数据变动> 数据变动——→视图更新这个方向的绑定。

  

<强> 1。数据劫持

  

不妨让我们自己思考一下,如何实现数据变动,对应绑定数据的视图就更新呢?
  

  

答案还是object.defineProperty,通过object.defineProperty遍历设置this.data里面所有属性,在每个属性的setter里面去通知对应的回调函数,这里的回调函数包括dom视图重新渲染的函数,使用美元看添加的回调函数等,这样我们就通过object.defineProperty劫持了数据,当我们对数据重新赋值时,如<代码> this.title='你好vue '>   

<强> 2。发布-订阅模式

  

那么问题来了,我们如何在setter里面触发所有绑定该数据的回调函数呢?
  

  

既然绑定该数据的回调函数不止一个,我们就把所有的回调函数放在一个数组里面,一旦触发该数据的setter,就遍历数组触发里面所有的回调函数,我们把这些回调函数称为订阅者。数组最好就定义在setter函数的最近的上级作用域中,如下面实例代码所示。

        种(this.data) .forEach(函数(关键){   var潜艇=[];//在这里放置添加所有订阅者的数组   Object.defineProperty (this.data键,{//this.data.title   可列举的:假的,   可配置:没错,   得到:getter函数(){   console.log(“访问数据啦啦啦”)   返回this.data(例子);//返回对应数据的值   },   设置:setter函数(newVal) {   如果(newVal===this.data[主要]){   返回;//如果数据没有变动,函数结束,不执行下面的代码   }   这一点。数据(关键)=newVal;//数据重新赋值      潜艇。forEach(函数(){//通知潜艇里面的所有的订阅者   })   }   });   }   

用vue的双向绑定简单实现一个todo - list的示例代码