如何实现双向绑定?底层原理是什么?
1、如何实现双向绑定?
以用户提交表单为例,其原理是我们对input进行value的属性绑定(v-bind:value="…"),将Model中的变量绑定到View上(Model -> View),以及当用户对input进行操作时,进行事件监听(v-on: input =" … "),从而实现双向数据绑定。v-model实际上是语法糖,结合了上述两个操作。
2、底层原理是什么?
参考:Vue的MVVM是如何实现的
如何追踪数据变化?
Vue将遍历传入Vue实例data选项中的js对象的所有property,并使用Object.defineProperty
把这些 property 全部转为getter/setter
。这些getter/setter
可使property在被访问和修改时通知变更。每个组件实例都对应一个watcher实例,它会在组件渲染的过程中把“接触”过的数据property记为依赖,之后当依赖项的setter触发时,会通知watcher,从而使它关联的组件重新渲染。
vue实现数据双向绑定主要是采用数据劫持,配合发布-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter和getter,在数据变动时发布消息给订阅者,触发响应监听回调。
vue数据双向绑定整合Observer Compile 和 Watcher三者,
(1) 通过Observer来监听自己Model的数据变化: Obeject.defineProperty()来监听属性变动,将需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter和getter,同时创建一个消息订阅器Dep用来收集订阅者,数据变动之后触发notify,再调用订阅者的update方法
(2) 通过Complie来解析编译模板指令: 对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定相应的更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。(每次找到一个数据替换,都要重新渲染一遍,可能会造成页面的回流和重绘,那么我们最好的办法就是把以上的元素放在内存中,在内存中操作完成之后,再替换掉.)
(3) **通过Watcher搭起Observer 和Compile 之间的通信桥梁:**能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数,从而更新视图,达到 数据变化 -> 视图更新,视图交互变化 -> 数据model变更。什么时候添加绑定watcher? 当订阅数据变化时,来绑定更新函数,从而让watcher更新视图
(1)观察者模式和发布订阅者模式的区别
**观察者模式:**在观察者模式里,被观察者subject只需要维护一套观察者observer的集合,这些observer实现相同的接口,subject只需要知道,通知observer时,需要调用哪个方法就好了。观察者模式是由具体目标调度的,其订阅者与发布者之间存在依赖。
发布订阅者模式: :发布订阅模式里,不仅仅只有发布者和订阅者两个角色,还存在一个调度中心,当事件触发时,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者注册到调度中心的处理代码。发布/订阅模式是统一由调度中心调的,其订阅者与发布者之间不存在依赖。
(2)Object.defineProperty可以对数组对象数据进行劫持吗?数组对象如何实现数据的响应更新?
参考:深入理解 Object.defineProperty 及实现数据双向绑定
Object.defineProperty(obj, prop, descriptor);
descriptor
由两部分组成:数据描述符(configurable,enumerable,value 及 writable 配置项)和访问器描述符(configurable,enumerable,get以及set),即使用访问器描述符中 getter或 setter方法的话,不允许使用 writable 和 value 这两个配置项。
ans:
- 当我们使用 Object.defineProperty 对数组赋值有一个新对象的时候,会执行set方法,但是当我们改变数组中的某一项值的时候,或者使用数组中的push等其他的方法,或者改变数组的长度,都不会执行set方法
- 通过重写 Array.property.push方法,并且生成一个新的数组赋值给数据,这样数据双向绑定就触发了
重新编写数组的方法:
const arrPush = {};// 如下是 数组的常用方法
const arrayMethods = ['push','pop','shift','unshift','splice','sort','reverse'
];
// 对数组的方法进行重写
arrayMethods.forEach((method) => {const original = Array.prototype[method]; arrPush[method] = function() {console.log(this);return original.apply(this, arguments);}
});const testPush = [];
// 对 testPush 的原型 指向 arrPush,因此testPush也有重写后的方法
testPush.__proto__ = arrPush;testPush.push(1); // 打印 [], this指向了 testPushtestPush.push(2); // 打印 [1], this指向了 testPush
(3)Object.defineProperty和Proxy的区别
Object.definePropery是对对象的属性的劫持,而Proxy是对对象的劫持,因此对于新增的属性不用重新定义getter,setter特性,Proxy也可以实现劫持,同时对于复杂对象也不必进行深度遍历。Vue3中将使用Proxy来实现数据劫持.
参考:Object.defineProperty与Proxy理解整理
let p = new Proxy(target, handler)
- Object.defineProperty()的主要问题
- 不能监听数组的变化
- 必须遍历对象的每个属性
- 必须深层遍历嵌套的对象
- Proxy
- 针对对象:针对整个对象,而不是对象的某个属性。相比于Object.defineProperty(),省了一个 Object.keys() 的遍历
- 支持数组:不需要对数组的方法进行重载
- 嵌套支持:和 Object.defineProperty() 是一样的,也需要通过逐层遍历来解决。Proxy 的写法是在 get 里面递归调用 Proxy 并返回
- Proxy的优劣势
- 优势:Proxy 的第二个参数可以有 13 种拦截方法,比 Object.defineProperty() 要更加丰富
- 劣势:Proxy 的兼容性不如 Object.defineProperty(), 不能使用 polyfill 来处理兼容性
如何实现双向绑定?底层原理是什么?相关推荐
- [vue] 什么是双向绑定?原理是什么?
[vue] 什么是双向绑定?原理是什么? 双向数据绑定个人理解就是存在data→view,view→data两条数据流的模式.其实可以简单的理解为change和bind的结合.目前双向数据绑定都是基于 ...
- vue数据双向绑定的原理
vue数据双向绑定的原理 一 复习闭包 1 闭包含义: 当函数嵌套时,内部函数使用了外部函数的变量,就会产生闭包 当函数可以记住并访问自己的作用域时,就会产生闭包 2 闭包注意点 ① 队列里的代码执行 ...
- Vue双向绑定:原理篇(详细)
文章目录 前言 什么是响应式 数据劫持 发布者-订阅者模式 模式简介 发布者 Observer 订阅器 dep 订阅者 Watcher 整体流程 初始化data data变为响应式数据 解析模板 收集 ...
- vue双向绑定的原理
之前我有个学生在面试的时候,面试官问vue的双向绑定如何实现?学生说用v-module实现.又问那么双向绑定的原理是什么?就回答不上来了,这个offer工资在18k左右,其他问题都回答上来了,如果这个 ...
- VUE双向绑定的原理(简单版)+虚拟DOM 节点的创建和更新
手动敲敲代码,就很容易理解了,供参考 1.以下是VUE双向绑定的原理(简单版) 主要是监听和defineProperty实现简单的双向绑定 <html><head></h ...
- 浅谈vue双向绑定的原理
一.什么是双向绑定 我们先从单向绑定切入 单向绑定非常简单,就是把Model绑定到View,当我们用JavaScript代码更新Model时,View就会自动更新 双向绑定就很容易联想到了,在单向绑定 ...
- DataBinding的双向绑定实现原理
" 悄悄咪咪告诉你,DataBinding是怎么实现双向绑定的" 在讲DataBinding之前,有必要讲讲ViewBinding 1.ViewBinding 1) 配置 要使用V ...
- Vue学习笔记--Vue双向绑定实现原理
我们知道Vue可以实现数据双向绑定,Angular和Vue都是采用的MVVM 模式,意思就是当M(模型层)层数据进行修改时,VM层会监测到变化,并且通知V(视图层)层进行相应的修改,反之修改V层则会通 ...
- vue2数据双向绑定的原理
vue2的数据双向绑定原理使用的是es5的数据劫持object.defineProperty,如果读取数据就会触发get,修改数据就会触发set,达到数据和视图的响应和更新,但是因为js固有的特性,不 ...
- php 双向绑定的原理,【原】数据双向绑定和虚拟dom探究
自各个mvvm框架出现和流行以来,他们都实现了两个新的概念及功能:数据双向绑定和虚拟dom.网上对于这两个概念的阐述很多很全面,这里仅对它们的原理和应用场景进行探究和记录,希望更接地气的理解和应用这两 ...
最新文章
- Activity(3、启动模式)
- python语言入门电子版-python从入门到精通pdf
- 黑马lavarel教程---13、分页
- Kafka解惑之Old Producer(3)——Async Analysis
- linux yum自动挂载_LINUX6安装YUM仓库和实现开机自动挂载
- ajax表单提交post(错误400) 序列化表单(post表单转换json(序列化))
- DB2中修改表字段类型或者长度
- 2019年数据库系统工程师上午真题及答案解析
- verilog学习笔记——8位数码管驱动设计与验证
- 解决 fxp/composer-asset-plugin 包报错问题
- 服务器系统 与win7系统,服务器系统win7
- MySQL 修改报错 You can't specify target table 'tb_trade' for update in FROM clause
- 联想服务器能够上固态硬盘吗,联想Y400能不能装固态硬盘 需要什么接口的
- Android实现语音识别成中文
- 防近视护眼台灯哪个牌子好?无蓝光无频闪的护眼台灯推荐
- 云服务器与虚拟主机有什么区别,我们应该如何选择?
- 数学之美读书感悟03
- Apple App Store 音乐App 美国畅销榜单前30名使用记录
- [SDIO]Read Wait 读等待机制
- Google Voice 保留号码