浅谈vuejs实现数据驱动视图原理

什么是数据驱动

数据驱动是vuejs最大的特点。在vuejs中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom。

比如说我们点击一个button,需要元素的文本进行是和否的切换。在jquery刀耕火种的年代中,对于页面的修改我们一般是这样的一个流程,我们对button绑定事件,然后获取文案对应的元素dom对象,然后根据切换修改该dom对象的文案值。

而对于vuejs实现这个功能的流程,只需要在button元素上指明事件,同时声明对应文案的属性,点击事件的时候改变属性的值,对应元素的文本就能够自动的进行切换,我们不需要像以前那样手动的操作dom。

简而言之,就是vuejs帮我们封装了数据和dom对象操作的映射,我们只需要关心数据的逻辑处理,数据的变化就能够自然的通知页面进行页面的重新渲染。

这样做的确实给我们带来的好处,我们不需要再在代码中频繁地去操作dom了,在实际项目中,我们有很大部分代码都是在数据修改以后,手动操作重新渲染页面元素,当页面越来越复杂的时候,页面代码组织会越来难以维护。同时,js对dom的频繁操作,会使得页面代码的出错概率高,页面的视图展示会融合在js代码中,对于页面视图显示的升级也不友好。

那么vuejs是如何实现这种数据驱动的呢?

MVVM框架

Vuejs的数据驱动是通过MVVM这种框架来实现的。MVVM框架主要包含3个部分:model、view和 viewmodel。

Model:指的是数据部分,对应到前端就是javascript对象

View:指的是视图部分,对应前端就是dom

Viewmodel:就是连接视图与数据的中间件

数据(Model)和视图(View)是不能直接通讯的,而是需要通过ViewModel来实现双方的通讯。当数据变化的时候,viewModel能够监听到这种变化,并及时的通知view做出修改。同样的,当页面有事件触发时,viewMOdel也能够监听到事件,并通知model进行响应。Viewmodel就相当于一个观察者,监控着双方的动作,并及时通知对方进行相应的操作。

Vuejs的数据驱动实现

对于数据驱动的实现,我们可以简单的通过定时器来实现这个功能,定时器定时监控对象数据,定时器监控数据变化,确定是否更新界面

a = 1;
  function renderDom(){
    document.getElementById('app').innerHTML = '数据是' + a;
  }

  function watcher(method){
    var b = a;
    method.apply();
     return setInterval(function(){
      if(b != a){
        method.apply();
        b = a;
      }
    }, 1000)
  }
  watcher(renderDom);

当然vuejs不可能是这样简单暴力的实现方式,vuejs是通过在实现一个观察者来实现的数据驱动。

首先,vuejs在实例化的过程中,会对遍历传给实例化对象选项中的data 选项,遍历其所有属性并使用 Object.defineProperty把这些属性全部转为 getter/setter。

同时每一个实例对象都有一个watcher实例对象,他会在模板编译的过程中,用getter去访问data的属性,watcher此时就会把用到的data属性记为依赖,这样就建立了视图与数据之间的联系。当之后我们渲染视图的数据依赖发生改变(即数据的setter被调用)的时候,watcher会对比前后两个的数值是否发生变化,然后确定是否通知视图进行重新渲染。

这样就实现了所谓的数据对于视图的驱动。

关于代码的实现,可以参考一下这篇文章 实现vue2.0响应式的基本思路

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

您可能感兴趣的文章:

  • 详解VueJS 数据驱动和依赖追踪分析
  • Vue数据驱动模拟实现5
  • Vue数据驱动模拟实现4
  • Vue数据驱动模拟实现2
  • Vue数据驱动模拟实现1
  • Vue数据驱动模拟实现3
(0)

相关推荐

  • Vue数据驱动模拟实现2

    一.前言 在随笔"模拟Vue之数据驱动1"结尾处,我们说到如果监听的属性是个对象呢?那么这个对象中的其他属性岂不就是监听不了了吗? 如下: 倘若user中的name.age属性变化,如何知道它们变化了呢? 今儿,就来解决这一问题. 通过走读Vue源码,发现他是利用Observer构造函数为每个对象创建一个Observer对象,来监听数据的,如果数据中的属性又是一个对象,那么就又通过Observer来监听嘛. 其实,核心思想就是树的先序遍历(关于树,可参考here).如我们将上述Demo

  • Vue数据驱动模拟实现3

    一.前言 在"模拟Vue之数据驱动2"中,我们实现了个Observer构造函数,通过它可以达到监听已有数据data中的所有属性. 但,倘若我们想在某个对象中,新增某个属性呢? 如下: 那么岂不是,新增的infor属性,以及它的对象属性,没有得到监听. 此时,应该怎么处理呢? 通过走读Vue源码,发现他是采用另增属性方法$set实现的. 就是说,如果我们采用常规方法为对象增加属性(如上),我们没法得知并监控它,所以,我们为每个对象扩展一个$set方法,用于另增属性使用,即可,如下: da

  • Vue数据驱动模拟实现5

    一.前言 在"模拟Vue之数据驱动4"中,我们实现了push.pop等数组变异方法. 但是,在随笔末尾我们提到,当pop.sort这些方法触发后,该怎么办呢?因为其实,它们并没有往数组中新增属性呢. 而且,当数据改动后,如果我们在变动数据处,就立即更改数据也未免性能不够,此时,走读Vue源码,发现他用了一个很巧妙的方法,就是职责链模式.当某个数据有所变动时,它会向上传递,通俗点就是冒泡至根结点,这样我们也可以在自己代码中使用事件代理咯,哇卡哇卡. 示意图如下所示: 好了,说了这么多,我

  • 详解VueJS 数据驱动和依赖追踪分析

    之前关于 Vue 数据绑定原理的一点分析,最近需要回顾,就顺便发到随笔上了 在之前实现一个自己的Mvvm中,用 setter 来观测model,将界面上所有的 viewModel 绑定到 model 上. 当model改变,更新所有的viewModel,将新值渲染到界面上 .同时监听界面上通过v-model 绑定的所有 input,并通过 addEventListener事件将新值更新到 model 上,以此来完成双向绑定 . 但是那段程序除了用来理解 defineProperty,其它一文不值

  • Vue数据驱动模拟实现4

    一.前言 在"模拟Vue之数据驱动3"中,我们实现了为每个对象扩展一个$set方法,用于新增属性使用,这样就可以监听新增的属性了. 当然,数组也是对象,也可以通过$set方法实现新增属性. 但是,对于数组而言,通常我们是通过push之类的方法吧. PS:Vue中明确指出push.pop.shift.unshift.splice.sort.reverse方法为变异方法,可以通过它们监听属性变化,触发视图更新(详情见here) 下面,我们就一起来实现这些Array的变异方法吧. 注:我们将

  • Vue数据驱动模拟实现1

    一.前言 Vue有一核心就是数据驱动(Data Driven),允许我们采用简洁的模板语法来声明式的将数据渲染进DOM,且数据与DOM是绑定在一起的,这样当我们改变Vue实例的数据时,对应的DOM元素也就会改变了. 如下: <!DOCTYPE html> <head> <meta charset="utf-8"> </head> <body> <div id="test"> {{name}} &

  • 浅谈vuejs实现数据驱动视图原理

    什么是数据驱动 数据驱动是vuejs最大的特点.在vuejs中,所谓的数据驱动就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom. 比如说我们点击一个button,需要元素的文本进行是和否的切换.在jquery刀耕火种的年代中,对于页面的修改我们一般是这样的一个流程,我们对button绑定事件,然后获取文案对应的元素dom对象,然后根据切换修改该dom对象的文案值. 而对于vuejs实现这个功能的流程,只需要在button元素上指明事件,同时声明对应文案的属性,点击

  • 浅谈laravel aliases别名的原理

    在laravel发现有些类可以直接use 类名,就能使用了,例如use DB;就可以使用DB类了,问题是DB这个类并不在根命名空间,这里面实际就是用到了别名. 先通过如下例子来分析基本原理 建立如下文件upload.php,内容为 <?php namespace test\test2; class upload{ public function test(){ return 123; } } 2 建立文件index.php,内容为 <?php namespace b; require('upl

  • 浅谈Maven包冲突的原理及解决方法

    1.概述 Apache Maven ,是一个软件(特别是Java软件)项目管理及自动构建工具.在没有Maven的上古年代,项目中引入jar包需要手动下载一个个的去下载,但是随着代码数量的增加,引入的jar包数量自然会增加,随之而来的就是jar包冲突的问题了. 2.产生jar包冲突的原因 众所周知,一个项目中不能存在两个全限定类名一致的Class类,并且jar包的本质就是打包好的Class类文件,例如: 将 junit-jupiter-api-5.6.2.jar 文件解压后, 可以得到多个Clas

  • 浅谈Mybatis #和$区别以及原理

    总结: 1.#可以防止Sql 注入,它会将所有传入的参数作为一个字符串来处理. 2.$ 则将传入的参数拼接到Sql上去执行,一般用于表名和字段名参数,$ 所对应的参数应该由服务器端提供,前端可以用参数进行选择,避免 Sql 注入的风险 为什么? 为什么# 和 $ 的作用不同,Mybatis 对他们做了哪些惨无人道的处理,我们看一下下面的例子,并追踪一下源码总结. 示例代码: 创建一个 tb_class 表(具体字段不做解释). 创建一个 ClassDao.java 并使用注解的方式 ,table

  • 浅谈swoole的作用与原理

    PHP 中的 Node ?Swoole 到底是什么? 我先从官方文档中引用下 Swoole 的定义: Swoole:面向生产环境的 PHP 异步网络通信引擎. 使 PHP 开发人员可以编写高性能.可拓展的异步并发 TCP.UDP.Unix Socket.HTTP,WebSocket 服务,而无需深入了解非阻塞 I/O 编程和初级 Linux 内核. Swoole 使用 C 语言编写,作为 PHP 的基本扩展存在.听起来可还行,是吧?用 PHP 来运行 HTTP 服务?用 PHP 实现 Webso

  • 浅谈Redis主从复制以及主从复制原理

    面临问题 1. 机器故障.我们部署到一台 Redis 服务器,当发生机器故障时,需要迁移到另外一台服务器并且要保证数据是同步的.而数据是最重要的,如果你不在乎,基本上也就不会使用 Redis 了. 2. 容量瓶颈.当我们有需求需要扩容 Redis 内存时,从 16G 的内存升到 64G,单机肯定是满足不了.当然,你可以重新买个 128G 的新机器. 解决办法 要实现分布式数据库的更大的存储容量和承受高并发访问量,我们会将原来集中式数据库的数据分别存储到其他多个网络节点上.Redis 为了解决这个

  • 浅谈Android串口通讯SerialPort原理

    目录 前言 一.名词解释 二.SerialPort的函数分析 三.SerialPort打开串口的流程 四.疑惑 五.总结 前言 通过前面这篇文章Android串口通讯SerialPort的使用详情已经基本掌握了串口的使用,那么不经想问自己,到底什么才是串口通讯呢?串口通讯(Serial Communication),设备与设备之间,通过输入线(RXD),输出线(TXD),地线(GND),按位进行传输数据的一种通讯方式.CPU 和串行设备间的编码转换器(转换器(converter)是指将一种信号转

  • 浅谈一下mysql数据库底层原理

    1.数据库事务的基本特性. 原子性: 事务中的所有操作要么全部提交成功,要么全部失败回滚. 场景:UPDATE cs_user SET age = 18 , gender = '女' WHERE id = 4.要么全部更新要么更新失败,不会出现age更新成功,gender更新失败. 一致性: 据库总是从给一个一致性的状态转换到另一个一致性的状态. 场景:比如规定某个表的字段age大于等于12小于18时,字段type为青少年,而数据库中存在age=16的时候,type='儿童'. 隔离性: 一个事

  • 浅谈:什么是数据驱动编程的详解

    前言:最近在学习<Unix编程艺术>.以前粗略的翻过,以为是介绍unix工具的.现在认真的看了下,原来是介绍设计原则的.它的核心就是第一章介绍的unix的哲学以及17个设计原则,而后面的内容就是围绕它来展开的.以前说过,要学习适合自己的资料,而判断是否适合的一个方法就是看你是否能够读得下去.我对这本书有一种相见恨晚的感觉.推荐有4~6年工作经验的朋友可以读一下.正题:作者在介绍Unix设计原则时,其中有一条为"表示原则:把知识叠入数据以求逻辑质朴而健壮".结合之前自己的一些

  • 浅谈Vuejs中nextTick()异步更新队列源码解析

    vue官网关于此解释说明如下: vue2.0里面的深入响应式原理的异步更新队列 官网说明如下: 只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变.如果同一个 watcher 被多次触发,只会一次推入到队列中.这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要.然后,在下一个的事件循环"tick"中,Vue 刷新队列并执行实际(已去重的)工作.Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MutationOb

随机推荐