专栏首页web秀vue响应式原理(数据双向绑定的原理)

vue响应式原理(数据双向绑定的原理)

概念

渐进式框架

每个框架都不可避免会有自己的一些特点,从而会对使用者有一定的要求,这些要求就是主张,主张有强有弱,它的强势程度会影响在业务开发中的使用方式。

比如说,Angular,它两个版本都是强主张的,如果你用它,必须接受以下东西: - 必须使用它的模块机制 - 必须使用它的依赖注入 - 必须使用它的特殊形式定义组件(这一点每个视图框架都有,难以避免)

所以Angular是带有比较强的排它性的,如果你的应用不是从头开始,而是要不断考虑是否跟其他东西集成,这些主张会带来一些困扰。

比如React,它也有一定程度的主张,它的主张主要是函数式编程的理念,比如说,你需要知道什么是副作用,什么是纯函数,如何隔离副作用。它的侵入性看似没有Angular那么强,主要因为它是软性侵入。

Vue可能有些方面是不如React,不如Angular,但它是渐进的,没有强主张,你可以在原有大系统的上面,把一两个组件改用它实现,当jQuery用;也可以整个用它全家桶开发,当Angular用;还可以用它的视图,搭配你自己设计的整个下层用。你可以在底层数据逻辑的地方用OO和设计模式的那套理念,也可以函数式,都可以,它只是个轻量视图而已,只做了自己该做的事,没有做不该做的事,仅此而已。

渐进式的含义,我的理解是:没有多做职责之外的事。

MVC模式

MVC的全称是Model-View-Controller,模型-视图-控制器,整个结构分成三层: 1. 最上面一层,视图层(View):用户界面(UI) 2. 最底层,是核心的“数据层”:保存数据 3. 中间层,控制层(Controller):处理业务逻辑,负责根据用户从“视图层”输入的指令,选取“数据层”的数据,然后对其进行相应的操作,产生最终的结果

各部分的通信方式如下: - View传送指令到Controller - Controller完成业务逻辑后,要求Model改变状态 - Model将新的数据发送到View,用户得到反馈

所有通信都是单向的。

MVP

MVP模式将Controller更名为Presenter,同时改变了通信方向 1. 各部分的通信都是双向的 2. View与Model不发生联系,都通过Presenter传递 3. View不部署任何业务逻辑,成为“被动视图”,而所有业务逻辑都部署在Presenter

4、MVVM模式 MVVM模式将Presenter更名为ViewModel(对应MVC中的C-controller),基本上与MVP模式一致。唯一区别MVVM采用双向数据绑定,View的变动自动反应在ViewModel上。 - M(model):模型---javascript object,代表真实情况的内容(一个面向对象的方法)、或表示内容(以数据为中心的方法)的数据访问层 - V(view):视图---用户界面(UI) - Viewmodel:在vue中指vue实例对象,是一个公开公共属性和命令的抽象的view;是一个转值器,负责转换Model中的数据对象,来让对象变得更容易管理和使用。

View的变化会自动更新到ViewModel,ViewModel的变化也会自动同步到View上显示。这种自动同步是因为ViewModel中的属性实现了Observer,当属性变更时都能触发对应的操作。

数据双向绑定

所谓的双向绑定,就是view的变化能反映到ViewModel上,ViewModel的变化能同步到view上

vue的定义: 1. vue是一套用于构建用户界面的渐进式框架 2. vue是一款基于MVVM方式的轻量级的框架 3. vue是一款基于数据驱动、组件化思想的框架 4. vue被设计为可以自底向上、逐层应用的框架 5. vue的核心库只关注视图层,易于上手,还便于与第三方库或既有项目整合 6. 当与现代化的工具链以及各种支持类库结合使用时,vue也完全能够为复杂的单页应用提供驱动

数据驱动:Vue.js 一个核心思想是数据驱动。所谓数据驱动是指视图是由数据驱动生成的,对视图的修改,不会直接操作 DOM,而是通过修改数据。相比传统的前端开发,如使用 jQuery 等前端库直接修改 DOM,大大简化了代码量,特别是当交互复杂的时候,只关心数据的修改会让代码的逻辑变的非常清晰,因为 DOM 变成了数据的映射,我们所有的逻辑都是对数据的修改,而不用碰触 DOM,这样的代码非常利于维护

在MVVM中,M(model)---代表JavaScript Objects,V(view)---DOM也就是UI,VM(ViewModel)----代表Vue实例对象(在该对象中有Directives和DOM Listeners)

在vue.js里面只需要改变数据,Vue.js通过Directives指令去对DOM做封装,当数据发生变化,会通知指令去修改对应的DOM,数据驱动DOM的变化,DOM是数据的一种自然的映射。vue.js还会对View操作做一些监听(DOM Listener),当我们修改视图的时候,vue.js监听到这些变化,从而改变数据。这样就形成了数据的双向绑定。

Vue实现数据双向绑定的原理:

如new Vue一个实例对象a,其中有一个属性a.b,那么在实例化的过程中,通过Object.defineProperty()会对a.b添加getter和setter,同时Vue.js会对模板做编译,解析生成一个指令对象(这里是v-text指令),每个指令对象都会关联一个Watcher,当对a.b求值的时候,就会触发它的getter,当修改a.b的值的时候,就会触发它的setter,同时会通知被关联的Watcher,然后Watcher就会再次对a.b求值,计算对比新旧值,当值改变了,Watcher就会通知到指令,调用指令的update()方法,由于指令是对DOM的封装,所以就会调用DOM的原生方法去更新视图,这样就完成了数据改变到视图更新的一个自动过程

实现数据双向绑定的方法:

发布者-订阅者模式(backbone.js)

思路:使用自定义的data属性,在HTML代码中指明绑定。所有绑定起来的javascript对象以及DOM元素都将订阅一个发布者对象。任何时候如果javascript对象或者一个HTML输入字段被侦测到发生变化,将代理事件变成发布者-订阅者模式,这会反过来变化广播,并传播到所有绑定的javascript对象以及DOM元素上。

脏值检查(angular.js)

angular.js是通过脏值检测的方式,对比数据是否有变更,从而决定是否更新视图。最简单的方式就是通过setInterval()定时轮询检测数据变动。angular.js只有在指定的事件触发时,进入脏值检测,大致如下: - DOM事件,譬如用户输入文本,点击按钮等(ng-click) - XHR响应事件($http) - 浏览器location变更事件($location) - Timer事件($timeout,$interval) - 执行$digest()或$apply()

数据劫持结合发布者-订阅者模式(vue.js)

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

具体的来讲,Vue.js通过Directives指令去对DOM做封装,当数据发生变化,会通知指令去修改对应的DOM,数据驱动DOM的变化。vue.js还会对操作做一些监听(DOM Listener),当我们修改视图的时候,vue.js监听到这些变化,从而改变数据。这样就形成了数据的双向绑定。

具体步骤如下: 1. 首先,需要对observe的数据对象进行递归遍历,包括子属性对象的属性,都加上setter getter。这样的话,给这个对象的某个属性赋值,就会触发setter,那么就能监听到数据变化。(其实是通过Object.defineProperty()实现监听数据变化的) 2. 然后,需要compile解析模板指令,将模板中的变量替换成数据,接着初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者。一旦数据有变动,订阅者收到通知,就会更新视图 3. 接着,Watcher订阅者是Observer和Compile之间通信的桥梁,主要负责: 1)在自身实例化时,往属性订阅器(Dep)里面添加自己 2)自身必须有一个update()方法 3)待属性变动,dep.notice()通知时,就调用自身的update()方法,并触发Compile中绑定的回调 4. 最后,viewmodel(vue实例对象)作为数据绑定的入口,整合Observer、Compile、Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 (ViewModel)-》视图更新(view);视图变化(view)-》数据(ViewModel)变更的双向绑定效果。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Webpack4 教程:入口、输入和ES6模块(第一章)

    你好!今天我们会开始一个 Webpack 4的入门教程。我们会以Webpack的基本概念开始,随着教程逐渐深入。这一次,我们将学习用ES6 modules进行模...

    Javanx
  • CSS3 calc()详细介绍及使用

    calc()对很多同学来说,或许很陌生。看其外表像个函数,既然是函数为什么又出现在CSS中呢?这一点也让我百思不得其解。

    Javanx
  • vue多语言插件vue-i18n使用介绍

    多语言,一听很高大上,象征着与国际接轨,中文版(简体、繁体)、英文版、日文版等等。感觉6b的不要不要的,下面来看看vue怎么来实现这个操作了?(其实很简单)

    Javanx
  • 实验2 基本图元光栅化

    (1) 阅读学习所给的直线光栅化的DDA算法示范代码,将其彻底弄懂,根据实验思考题找出其中的错误;同时能在计算机上编译运行,输出正确结果,指出错误并截图保存为图...

    步行者08
  • 疑似30万玖融网用户数据被挂暗网,仅售1个比特币

    日前,一本财经记者发现,在暗网中有黑客称盗取了汽车金融平台玖融网的后台权限,可以入侵所有的服务器。黑客称,他已获得该平台上30万的用户数据,并以一个比特币(现价...

    FB客服
  • 请不要将Alpha Go胜出联系到机械生命,谢谢!

    Alpha Go人工智能系统与世界围棋冠军李世石的“世纪对决”第一幕结束,李世石输了第一局。在这场比赛开始之前,我就在朋友圈说,机器胜出,毫无悬念。我坚信,Al...

    罗超频道
  • Qcon北京2017总结:测试角度看泛智能和大数据

    本来这个文章应该在很早之前就写的,可惜一直没时间,写的时候断断续续。关键是这次leader 拓展又见晓生,每次见到他都会提醒我,这总结居然还没有写。下面就由小V...

    serena
  • 大数据项目测试<二>项目的测试工作

     后端的测试重点,主要集中在数据的采集处理、标签计算效率、异常数据排查(功能),测试脚本编写(HiveQL)、自动化脚本编写(造数据、数据字段检查等)

    互联网金融打杂
  • 14亿邮箱泄露密码明文信息查询网站惊现网络

    经查询统计,该14亿邮箱密码库涉及Gamil、Hotmail、Yahoo、Sina、qq、163、Sohu、Live、Aol等知名电邮厂商注册用户,另外,还涉及...

    FB客服
  • 震撼可视化,4分钟看完世界5500年版图演变(视频)

    导读:人类历史进展?国家版图如何变化?5500年厚重的历史如何被压缩到4分钟内?请观看视频,感受可视化的魅力。 ? 超震撼 | 地学最前沿的16幅动图 ? ...

    小莹莹

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动