前言:本系列学习笔记从以下几个点展开

  • 什么是双向数据绑定
  • 双向数据绑定的好处
  • 怎么实现双向数据绑定
    • 实现双向数据数据绑定需要哪些知识点

      • 数据劫持
      • 发布订阅模式

先看看我们要实现的目标是什么,如下动图:

0、什么是双向数据绑定

  单向数据绑定:把Model 绑定到View上,当我们用js修改模型 Model 时候,视图View上对应的内容也会改动,这就是 数据动,页面动 。

  双向数据绑定:简言之 数据动 页面动,页面动,数据动, 典型的应用就是在做表单时候,输入框的内容改动后,跟该输入框的value 的值改动。

  

看vue 官网上的这个V-model  的演示案例:

1、双向数据绑定的好处

  要说出这个好处的时候,也只有在实际场景中才能对应的显示出来。比如我们需要实时显示数据,我们一边说话,一边实时显示我们说的话的文字内容,等等。这让我想起了去年参加云栖大会,台上的大佬一边说话,下面的字幕实时更新。(当然实现这个技术有很多技术点,我们不讨论这个内容,小编也才疏学浅,搞不懂)

以上的都是废话,我们直接看看怎么实现这个双向数据绑定。

一、实现原理

  Vue实现双向数据绑定的原理:数据劫持 + 发布订阅模式(有的也称为观察者模式)

  数据劫持的核心技术: Object.defineProperty()

  **vue 3.0 已经用的不是这个技术了,采用是 原生的 Proxy,据说速度能够提升100%,截张尤大的ppt,** 2018-11-21 修改本篇笔记

(香菇,刚研究会一点,就立马变了,这就是前端世界),Proxy 的方式将会在本系列笔记结束后,再记录这个技术点的使用

二、数据劫持的方法 Object.defineProperty()

  先上一个参照代码,它长这个样子:

var book = {_year: 2004,edition: 1
};
Object.defineProperty(book, "year", {get: function(){   console.log('访问year了,返回_year')return this._year;},set: function(newValue){if (newValue > 2004) {this._year = newValue;     console.log('重新设置_year了,并返回edition')this.edition += newValue - 2004;}}
});
book.year = 2005;
alert(book.edition); //2 

---摘自 JavaScript高级程序设计

  Object.defineProperty() 的具体介绍,我们本文不做具体展开,查看我这里的一篇文章,Object.defineProperty。 我们这里先要知道这么一个事情。这个方法要传入三个参数,传入的数据对象data,属性key,描述符对象。其中,描述符(descriptor)对象的属 性必须是:configurable、enumerable、writable 和 value。设置其中的一或多个值,可以修改 对应的特性值。我们需要用的是这访问器属性。当我们在读取访问器属性时,会调用 getter 函数,这个函数负责返回有效的值;在写入访问器属性时,会调用 setter 函数并传入新值,这个函数负责决定如何处理数据。上文代码上的 get 方法,在读取属性时调用的函数,set方法,在写入属性时调用的函数。

三、发布订阅者模式

  我画了一个图,来理解这个模式,如下图:

  

代码解释:

//下面封装一个单例模式,内容是发布订阅模式
let event = {eventList: [],listener: function (key, fn) {if (!this.eventList[key]) { //没有订阅过此类消息,创建一个缓存列表this.eventList[key] = [];}this.eventList[key].push(fn)},trigger: function () {let key = Array.prototype.shift.call(arguments); // marrylet fns = this.eventList[key];if (!fns || fns.length == 0) { //没有订阅 则返回return false;}for (let i = 0, fn; fn = fns[i++];) {fn.apply(this, arguments)// 调用 event.listen 里面的 fn 方法,通过apply将当前执行的对象指向当前的this,arguments 传进 fn 函数
        }},remove: function (key, fn) { // 取消订阅let fns = this.eventList[key];if (!fns) {return false;}if(!fn) {fns && (fns.length = 0)} else {for (let l = fns.length-1; l>=0; l--) {let _fn = fns[l];if( _fn === fn) {fns.splice(l, 1)}}}},install: function (obj) {for (let i in this) {if (i === 'install') {return false}obj[i] = this[i];}}
}let testMsg = {}
event.install(testMsg)// 上面方法 就会将event的方法 浅拷贝给 testMsg, 这样testMsg就有 event的方法和属性
testMsg.listener('rich', fn1 = (name) => {console.log(`${name}知道你有钱了`)
})
testMsg.listener('borrowMoney', fn2 =  (name) => {console.log(`${name}想问你借钱`)
})// listen方法将事件 放进队列
// testMsg.remove('rich', fn1) // 取消订阅// trigger方法,处理事件队列的方法,调用listen的函数的里面的回调函数 fn
testMsg.trigger('rich', '张三')
testMsg.trigger('rich', '张三2')
testMsg.trigger('borrowMoney', '李四')
testMsg.trigger('borrowMoney', '李四2')// 代码总结:
// 订阅的事件具有对应的key// 通过listener方法,将具体的事件队列保存到 eventList ,可以理解为缓存列表也可以是事件队列;// 执行trigger 方法,将事件队列拿出来执行调用// remove 方法根据对应的key值,删除对应的订阅事件
// 模式总结:封装一个单例event, 执行installEvent方法,将想要event对象拷贝到某个对象中去,
// 发布者trigger方法,监听者listen方法 ,trigger 发布一个东西,listen立马知道你要发布的东西

View Code

四、实现分解

  • 主函数入口

    •   

      function Myvue (options) {this.$options = optionsthis.$el = document.querySelector(options.el);this.$data = options.data;Object.keys(this.$data).forEach(key => {this.$prop = key;})this.init()
      }
      Myvue.prototype.init = function () {// 监听数据变化observer(this.$data);// 获得值// let value = this.$data[this.$prop];// 不经过模板编译直接 通知订阅者更新dom// new Watcher(this,this.$prop,value => {//     console.log(`watcher ${this.$prop}的改动,要有动静了`)//     this.$el.textContent = value// }) //通知模板编译来执行页面上模板变量替换new Compile(this)
      }

  • 主函数调用
    •   

      <script>const vm = new Myvue({el: "#app",data: {name: "vue 双向数据绑定test1"}});
      </script>

  • 监听器
  • 订阅者
  • 模板编译器

未完待续,错误之处,敬请指出,共同进步!

下一篇 vue 双向数据绑定的实现学习(二)-监听器的实现

文章参考:

  https://www.cnblogs.com/beevesnoodles/p/9844854.html

  https://github.com/youngwind/blog/issues/87

  https://juejin.im/post/5a9108b6f265da4e7527b1a4

后记:代码只做基本实现,不做代码健壮性处理,一些错误处理已经忽略

转载于:https://www.cnblogs.com/adouwt/p/9928278.html

vue 双向数据绑定的实现学习(一)相关推荐

  1. vue双向数据绑定原理分析--Mr.Ember

    vue双向数据绑定原理分析 摘要 vue常用,但原理常常不理解,下面我们来具体分析下vue的双向数据绑定原理. (1)创建一个vue对象,实现一个数据监听器observer,对所有数据对象属性进行监听 ...

  2. [Vue源码分析]谷歌翻译后,Vue双向数据绑定失效了?

    前言: 最近运营反馈了一个问题:谷歌浏览器打开第三方储值平台,使用谷歌浏览器自带的翻译功能后,选择商品没有计算总额. 首先可以肯定的是这不是bug,这个平台已经兼容了13种语言,只是运营没有通过语言栏 ...

  3. vue双向数据绑定的简单实现

    vue双向数据绑定的简单实现 参考教程:链接 <!DOCTYPE html> <html lang="en"> <head><meta c ...

  4. “别具一格”的vue双向数据绑定原理

    背景和一点点看法 见网上许多文章讲vue双向数据绑定一开口就大谈 Object.defineProperty 和 proxy.其实不然.这是vue中响应式的"基石". vue 中有 ...

  5. vue双向数据绑定原理 1

    1. 原理 1.1 vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布订阅模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化 ...

  6. Vue 双向数据绑定原理

    原理 1.vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布者订阅者模式的方式来实现的,通过Object.defineProperty()来劫持各个属性的 ...

  7. 理解VUE双向数据绑定原理和实现

    一.原理: 1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变: 2.核心:关于VUE双向数 ...

  8. 分析Vue双向数据绑定原理以及简单实现MVVM

    前言 随着Vue的火热发展,越来越多的程序员并不满足于对框架的使用,更多地追求其内在的原理,就像不能沉沦于美丽的外表,更应该追求灵魂的高度. 正文 好了,废话不多说,接下来我们将通过俩方面开展我们对外 ...

  9. vue双向数据绑定原理学习

    vue源码 1.双向数据绑定 学习数组的reduce函数 var arr = [2,4,5,67,78,5,1] // arr.reduce(函数,初始值) // arr.reduce((上次的初始值 ...

最新文章

  1. NMAP输出结果中CPE的含义
  2. Linux(四)——redis服务
  3. SQL注入-SQL注入的WAF绕过(十六)
  4. html选中后当前变色,JS代码实现表格选中后变色操作有哪些代码?
  5. Monkey随机性能压测初探(一)
  6. 作为研发工程师,不可不知的运维技能武器库,这些你知道吗
  7. pandas 增删改
  8. 解决python2.7.9以下版本requests访问https的问题
  9. #大数加减乘除#校赛D题solve
  10. java编程练习题四
  11. C语言程序设计(第四版)谭浩强 清华 【2000】
  12. 电信机顶盒怎么连接鸿蒙系统电视,移动电信机顶盒怎么投屏?怎么连接手机
  13. U8记账凭证修改方法汇总
  14. android qq 邮箱格式,QQ邮箱格式怎么写
  15. python unpack函数_Lua UnPack函数用法实例
  16. 2020最新版前端学习路线图--Javascript网页编程重点知识
  17. Connection could not be established with host smtp.163.com 阿星小栈
  18. 如何解决html文档无法复制,教你如何解决网页不能复制粘贴的问题
  19. 苹果开发者账户创建流程
  20. 雅加达(印度尼西亚)出差小记

热门文章

  1. Java小结(三)——打印完美杨辉三角
  2. c 获取数据库数据计算机,使用c从单板计算机写入mysql数据库使用c
  3. 机器学习 + 深度学习 + 计算机视觉 + 自然语言处理: 原理, 实践以及应用 --- 干货分享(持续更新…)
  4. redis的lrange_Redis Lrange 命令
  5. JZOJ 5263. 【NOIP2017模拟8.12A组】分手是祝愿
  6. mysql执行查询出来的数据_F#连接到在线MySQL数据库执行查询
  7. mysql事务服务_MySQL (事务篇)
  8. 查询 oracle_关于oracle和mysql数据库的查询问题
  9. 如何发表顶级期刊论文
  10. 正则表达式删除文件中某些列