zoukankan      html  css  js  c++  java
  • Vue数据双向绑定(面试必备) 极简版

      我又来吹牛逼了,这次我们简单说一下vue的数据双向绑定,我们这次不背题,而是要你理解这个流程,保证读完就懂,逢人能讲,面试必过,如果没做到,请再来看一遍,走起:

      

      介绍双向数据之前,我们先解释几个名词:

     

      1、什么是setter、getter ?

      答:首先,别误以为他们就是一会要说的get、set,我们先看一句定义:

        对象有两种属性:(1)数据属性,就是我们经常使用的属性(2)访问器属性,也称存取器属性(存取器属性就是一组获取和设置值的函数

       

      再看一行代码:

      

      log打印出来的如下:

      

      数据属性就是a和b;

      get和set就是关键字 它们后面各自对应一个函数,这个函数就是上面红字部分所讲的,存储器属性。

      get对应的方法称为getter,负责获取值,它不带任何参数。set对应的方法为setter,负责设置值,在它的函数体中,一切的return都是无效的。

     

      2、什么是Object.defineProperty() ?

      答:老规矩走起,我们先看一句定义:

      对象是由多个名/值对组成的无序的集合。对象中每个属性对应任意类型的值。

      

      定义对象可以使用构造函数或字面量的形式:

      

      

      除了以上添加属性的方式,当然还可以使用Object.defineProperty定义新属性或修改原有的属性;

      语法:

      Object.defineProperty(obj, prop, descriptor)

      参数:

      obj:必需。目标对象;
      prop:必需。需定义或修改的属性的名字;
      descriptor:必需。目标属性所拥有的特性;

      返回值:

      传入函数的对象,即第一个参数obj;

     

      OK,定义介绍完了,我们现在说一下一会关于双向绑定我们要用到的知识点:存取器描述;(诶?你是不是发现和上面好像有点关系)

      

      对头,它是这样使用的:

      

     

      现在无论是你获取还是设置我们都可以接到通知,是不是有一点双向数据绑定的影子了,别急下面还有;

      

      OK,我终于叨叨完没用的了,现在开始说正题,如何理解Vue的双向数据绑定,哈哈,先来一个定义:

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

     

      我们来看一个很粗暴的栗子,low版双向绑定:

      

     

      是不是有点明白了呢,当然这也不是全部,我们刚刚说的大概就是下面Observer的部分,对每个vue中的data中定义的属性循环用Object.defineProperty()实现数据劫持,以便利用其中的setter和getter,然后通知订阅者,订阅者会触发它的update方法,对视图进行更新。

     

      

     

      别急,下面也很简单:

      Dep,它就像一个依赖管理一样,小伙伴又问啥是依赖管理倪? 上图!

      

      我用一个例子来解释一下上面这张图 下面高能预警:

      在vue中v-model,v-name,{{}}等都可以对数据进行展示,也就是说假如一个属性都通过这三个指令了,那么每当这个属性改变的时候,相应的这个三个指令的html视图也必须改变;

      于是vue中就是每当有这样的可能用到双向绑定的指令,就在一个Dep中增加一个订阅者(addSub),其订阅者只是更新自己的指令对应的数据,也就是v-model='name'和{{name}}有两个对应的订阅者,各自管理自己的地方;

      每当属性的set方法触发,就循环更新Dep中的订阅者(notify);

     

      OK,Dep是不是很明白了呢

      集合上面的那张图来看,就是Observer一旦有了set触发,就会通知到Dep,那Dep接到通知之后呢?从图上来看,下面所讲的就应该是Compile了,也很简单:

      首先,先要知道它负责干什么?

      compile主要做的事情是解析模板指令,将模板中的变量替换成数据

      其次知道它什么时候要工作,只有两种情况,先上图:

      

      

      1)初始化,init的时候 初始化渲染页面视图;

      2)将每个指令对应的节点绑定更新函数,添加监听数据的订阅者

      Dep负责维护依赖,而订阅者则来自于compile,一旦有数据变动,则会绑定更新函数,此时也就是产生了订阅者,这个时候Dep内就增加了一个订阅者,而一旦数据变动,则会收到通知,更新视图;

      好了,你是不是觉得上面这行说不通,或是读不通,当然,因为上面的这个流程了缺少了,我们最后要说的Watcher我把上面这句话补全,就是Watcher的工作了;

      Dep负责维护依赖,而订阅者则来自于compile,一旦有数据变动,则会通过Watcher绑定更新函数,此时Watcher也向Dep中添加了订阅者,一旦Dep接到Observer的通知,它就会再去通知WatcherWatcher则会调用自身的update()方法,并触发Compile中绑定的回调,更新视图;

      

      最后敲黑板:

      首先我们为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;

      然后在编译的时候在该属性的数组dep中添加订阅者,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会;

      接着为input会添加监听事件,修改值就等于为该属性赋值,则会触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。

      参考干货:

      https://www.cnblogs.com/zhenfei-jiang/p/7542900.html

      https://segmentfault.com/a/1190000006599500

      感谢巨人的肩膀

      

      

      

      

     

     

     

     

     

     

      

     

     

         

        

  • 相关阅读:
    RE
    【LeetCode】198. House Robber
    【LeetCode】053. Maximum Subarray
    【LeetCode】152. Maximum Product Subarray
    【LeetCode】238.Product of Array Except Self
    【LeetCode】042 Trapping Rain Water
    【LeetCode】011 Container With Most Water
    【LeetCode】004. Median of Two Sorted Arrays
    【LeetCode】454 4Sum II
    【LeetCode】259 3Sum Smaller
  • 原文地址:https://www.cnblogs.com/webcabana/p/11077628.html
Copyright © 2011-2022 走看看