首页系统综合问题什么是双向数据绑定?如何去实现?Observer,Compile,Watcher

什么是双向数据绑定?如何去实现?Observer,Compile,Watcher

时间2023-02-25 18:12:26发布分享专员分类系统综合问题浏览62

今天小编给各位分享compile的知识,文中也会对其通过什么是双向数据绑定?如何去实现?Observer,Compile,Watcher和vue原理相关总结等多篇文章进行知识讲解,如果文章内容对您有帮助,别忘了关注本站,现在进入正文!

内容导航:

  • 什么是双向数据绑定?如何去实现?Observer,Compile,Watcher
  • vue原理相关总结
  • vue双向绑定原理
  • vue数据双向绑定原理
  • 一、什么是双向数据绑定?如何去实现?Observer,Compile,Watcher

    根据流程图来理一下实现一个MVVM:

    如上图所示,我们可以看到,整体实现分为四步:

    1、实现一个Compile,对指令进行解析,初始化视图,并且订阅数据的变更,绑定好更新函数

    2、实现一个Observer,对数据进行劫持通知数据的变化

    3、实现一个Watcher,将其作为以上两者的一个中介点,在接收数据变更的同时,让Dep添加当前Watcher,并及时通知视图进行update

    4、实现MVVM,整合以上三者,作为一个入口函数

    流程解读

    第一步:创建MVVM、Compile类,并且利用createDocumentFragment将<div id="app"></div>下的标签放到JS文档碎片中去。

    第二步:对 标签 进行编译,将带有 v- 指令的标签和{{ }}的标签解析出来

    第三步:创建Observer类进行数据劫持、深度递归劫持,当data中设置值或者修改值的时候,利用Object.defineProperty对值进行监控。

    第四步:创建Watch类观察者,用新值和老值进行比对,如果发生变化,就调用更新方法,进行视图更新。

    第五步:将输入框v-model和视图绑定起来,输入框的值变化,同时页面中通过{{}}绑定的值也变化,实现双向数据绑定。

    代码比较粗糙,核心就是这些了。应该来说一定要掌握的,因为Vue,Watcher,Dep等都是大家非常熟悉的构造函数了,创造实例只是前面多了一个关键字 new。其他的平常都很熟悉了。

    一、vue原理相关总结

    一、vue2.0的双向绑定是怎么实现的

    2、observer,compile,watcher

    (1)observe是一个数据监听器,核心方法是Object.defineProperty

    (3)compile是一个指令解析器,对需要监听的节点和属性进行扫描和解析。

    3、此模式的优点:不需要显式调用,可以直接通知变化,更新视图;劫持了属性setter,不需要额外的diff操作

    4、Object.defineProperty缺点

    (1)不能监听数组

    (2)不能监听整个对象,只能监听属性

    (3)不能监听属性的增删,只能监听变化

    5、3.0版本使用Proxy

    (1)可以监听数组

    (2)可直接监听整个对象,不用层层递归属性

    (3)get和set时候直接有参数,不需要单独存储变量

    (4)new Proxy()会返回一个新对象,不会污染源对象。

    二、数据不更新的问题

    1、更新的原理:在数据读取时收集依赖,在赋值时通知依赖更新。

    2、object有defineProperty方法,通过getter,setter只监听了属性的读取和赋值,但是新增属性和删除属性没有检测,所以专门提供了$set和$delete来实现

    3、array,没有defineProperty方法,没有setter,通过get和新建数组方法拦截器修改原生方法push,pop,shift,unshift,splice,sort,reserve来实现监听,而通过修改数组下标操作数组的不会被检测,所以专门提供了$set和$delete来实现

    4、$set(target, key, value)和$delete(target, propertyName/index)方法原理

    (1)判断target是否是undefined,null,或者原始类型,或者vue实例,或者vue实例的跟数据对象

    (2)target为数组,则还是通过调用splice操作索引更新数据

    (3)target为对象,且为响应式,则调用defineReactive操作数据

    (4)更新完数据后通知依赖更新

    三、computed和watch和methods

    1、computed

    (1)设计初衷:为了使模板中的逻辑运算更简单

    (2)适用于数据被重复使用或者计算复杂费时的场景;依赖其他数据的场景

    (3)读取缓存,依赖不变,则不需重新计算。(根据dirty标志判断)

    2、watch是对数据的监听回调

    3、computed和watch的区别

    相同点:都会观察页面的数据变化

    不同点:(1)computed是读取缓存,watch每次都要重新执行;

    (2)watch更适合数据变化时的异步操作和开销较大的操作。

    4、computed和methods的区别

    computed依赖缓存,可以定义getter和setter,但是methods不行

    四、vue-router的模式区别

    1、abstract:非浏览器环境下使用

    2、hash:

    (1)默认。监听hashchange实现。

    (2)有点,兼容性好,ie8支持

    (3)缺点:看起来奇怪

    3、history:

    (1)h5新增的。允许开发者直接修改前端路由而不重新触发请求页面

    (2)实现原理:监听popstate事件。能监听到用户点击浏览器的前进后退事件或者手动调用go,back,forward事件;不能监听到pushState和replaceState事件。

    (3)为了避免浏览器刷新出现的404页面,需要在服务端配置兼容。

    (4)如果浏览器不支持,会降级到hash模式

    * 通过vue.use插件机制和vue.mixin将store在beforeCreate和destroyed生命周期进行混入。

    五、vuex解决了什么问题

    1、vuex解决了vue项目中的数据状态管理问题

    2、是组件通信的一种方式。

    3、原理:创建了单一的状态树,包含state,mutation,action,getter,module。

    4、view(dispatch)action(commit)mutation(mutate)state(render)view

    5、通过vue的data和computed,让state变成响应式,

    6、通过vue.use插件机制和vue.mixin将store在beforeCreate生命周期进行混入。

    六、nextTick是怎么是实现的

    1、作用:将回调延迟到下次DOM更新循环之后执行

    2、原因:VUE在更新DOM时是异步的,vue检测到数据变化后,不会立即更新DOM,而是会开启一个事件队列,并缓冲同一时间循环中的所有数据变更,在下一次tick中,执行更新DOM。

    3、js的运行机制:js是单线程的,基于事件循环,有宏任务和微任务。

    4、内部原理:

    (1)能力检测:Promise.then(微), MutationObserve(微),setImmediate(微),setTimeout(宏)

    (2)将回调函数推入回调队列,锁上易步锁,执行回调。

    七、keep-alive内置组件和LRU算法(队列)

    1、自身不会渲染成DOM,没有常规的 标签,是个函数组件,被他包裹的组件,切换时会被缓存在内存中,而不是销毁。

    (1)可以有条件的缓存:include(匹配到的缓存),exclude(匹配到的不缓存),max(最多可以缓存多少组件实例)

    2、原理:内部维护了this.cache(缓存的组件对象)和this.keys(this.cache中的key),运用LRU策略。

    (1)命中了缓存的组件要调整组件key的顺序。

    (2)缓存的组件数量如果超过this.max时,要删除第一个缓存组件。

    (3)LRU(Least recently used,最近最少使用):根据数据的 历史 访问记录来进行淘汰数据。“如果数据最近被访问过,那么将来被访问的几率也更高。”

    3、生命周期钩子:activated和deactivated,被keep-alive包括的组件激活和停用时调用。先停用组件的deactivated,再激活组件的activated

    二、vue双向绑定原理


    具体步骤:

    第一步: 需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter

    这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化

    2、自身必须有一个update()方法

    3、待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。

    第四步: MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。


    1、v-model是什么?怎么使用? vue中标签怎么绑定事件?

    答:可以实现双向绑定,指令(v-class、v-for、v-if、v-show、v-on)。vue的model层的data属性。绑定事件:

    三、vue数据双向绑定原理

    vue.js 采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

    首先我们为每个vue属性用Object.defineProperty()实现数据劫持,在监听数据的过程中,为每个属性分配一个订阅者集合的管理数组dep;然后在编译的时候在该属性的数组dep中添加订阅者 watcher,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会,接着为input会添加监听事件,修改值就会为该属性赋值,触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。

    实现步骤:修改输入框内容 => 在事件回调函数中修改属性值 => 触发属性的 set 方法=>发出通知 dep.notify() => 触发订阅者的 update 方法 => 更新视图。

    流程图

    在实例化一个Vue对象的时候,会传进去一个data对象,之后分成两个进程,一个进程是对挂载目标元素模板里的v-model和{{ }};两个指令进行编译。另一个进程是对传进去的data对象里面的数据进行监听。

    上图中,observe是利用Object.defineProperty()对传入的data对象进行数据监听,在数据改变的时候触发该属性的set方法,更新该属性的值,并发布消息,我(该属性)的值变了。

    compile是编译器,找到vue的指令v-model所在的元素,将data中该属性的值赋给元素的value,并给这个元素添加二级监听器,在元素的值改变的时候,将新值赋给data里面同名属性,这个时候就完成了单向数据绑定,视图 >> 模型。

    那么最终的由模型到视图的更新,依赖于dep和watcher,dep会收集订阅者,就是绑定了data里面属性的元素,在数据更新的时候,会触发该属性的set方法,在set里触发该属性的消息发布通知函数。而Watcher根据收到的数据变化通知,更新相应的数据。

    dep这个东东给大家解释一下,就是data里的每个属性都有一个dep对象,dep对象里可以有很多订阅者(watcher),但是只有一个添加订阅者的方法和一个发布变化通知的方法,就是模板上可以有多处元素绑定data里的同一个属性值,所以dep是依赖于data里面的属性的。

    而Watcher是每个{{ }}有一个,初次编译的时候,会在new的时候自动更新一下模板的数据,等到下次数据改变的时候,由dep通知数据更新,直接调用watcher的update方法,更新模板的绑定数据。

    observer 模块共分为这几个部分:

    示意图如下:

    Observer的构造函数

    value是需要被观察的数据对象,在构造函数中,会给value增加 ob 属性,作为数据已经被Observer观察的标志。如果value是数组,就使用observeArray遍历value,对value中每一个元素调用observe分别进行观察。如果value是对象,则使用walk遍历value上每个key,对每个key调用defineReactive来获得该key的set/get控制权。

    Dep是Observer与Watcher之间的纽带,也可以认为Dep是服务于Observer的订阅系统。Watcher订阅某个Observer的Dep,当Observer观察的数据发生变化时,通过Dep通知各个已经订阅的Watcher。

    Watcher是用来订阅数据的变化的并执行相应操作(例如更新视图)的。Watcher的构造器函数定义如下:

    参数中,vm表示组件实例,expOrFn表示要订阅的数据字段(字符串表示,例如a.b.c)或是一个要执行的函数,cb表示watcher运行后的回调函数,options是选项对象,包含deep、user、lazy等配置。

    Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义属性的对象) prop (要定义或修改的属性的名称或 Symbol ) descriptor (要定义或修改的属性描述符=>具体的改变方法)

    简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;

    主要解释第三个参数 {
    value: 设置属性的值
    writable: 值是否可以重写。true | false
    enumerable: 目标属性是否可以被枚举。true | false (就是能不能被遍历出来)
    configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
    set: 目标属性设置值的方法
    get:目标属性获取值的方法
    }

    set 是一个函数,接收一个新值,会在值被重写或修改的时候触发这个函数
    get 是一个函数,返回一个值,会在属性被调用的时候触发。


    Object.defineProperty()详解
    Object.defineProperty()官方文档

    已经了解到vue是通过数据劫持的方式来做数据绑定的,其中最核心的方法便是通过Object.defineProperty()来实现对属性的劫持,那么在设置或者获取的时候我们就可以在get或者set方法里假如其他的触发函数,达到监听数据变动的目的。

    我们知道通过Object.defineProperty()可以实现数据劫持,它的属性在赋值的时候触发set方法,

    当然要是这么粗暴,肯定不行,性能会出很多的问题。

    observer用来实现对每个vue中的data中定义的属性循环用Object.defineProperty()实现数据劫持,以便利用其中的setter和getter,然后通知订阅者,订阅者会触发它的update方法,对视图进行更新。

    为什么要订阅者 :在vue中v-model,v-name,{{}}等都可以对数据进行显示,也就是说假如一个属性都通过这三个指令了,那么每当这个属性改变的时候,相应的这个三个指令的html视图也必须改变,于是vue中就是每当有这样的可能用到双向绑定的指令,就在一个Dep中增加一个订阅者,其订阅者只是更新自己的指令对应的数据,也就是v-model='name'和{{name}}有两个对应的订阅者,各自管理自己的地方。每当属性的set方法触发,就循环更新Dep中的订阅者。

    订阅发布模式(又称观察者模式)定义了一种一对多的关系,让多个观察者同时监听某一个主题对象,这个主题对象的状态发生改变时就会通知所有观察者对象。

    发布者发出通知 => 主题对象收到通知并推送给订阅者 => 订阅者执行相应操作
    举个例子:

    2.实现compile: compile的目的就是解析各种指令称真正的html。

    这样一来就实现了vue的数据双向绑定。

    参考链接:
    理解VUE双向数据绑定原理和实现---赵佳乐
    Vue的双向数据绑定原理
    vue双向绑定原理分析
    Vue原理解析之observer模块
    深入响应式原理

    关于compile的问题,通过《vue双向绑定原理》、《vue数据双向绑定原理》等文章的解答希望已经帮助到您了!如您想了解更多关于compile的相关信息,请到本站进行查找!

    爱资源吧版权声明:以上文中内容来自网络,如有侵权请联系删除,谢谢。

    compile
    企业微信超级管理员有哪些权限? Windows 字体优化,这几个办法能帮你解决