浅谈vue双向绑定的原理
一、什么是双向绑定
我们先从单向绑定切入
单向绑定非常简单,就是把Model
绑定到View
,当我们用JavaScript
代码更新Model
时,View
就会自动更新
双向绑定就很容易联想到了,在单向绑定的基础上,用户更新了View
,Model
的数据也自动被更新了,这种情况就是双向绑定
举个栗子
当用户填写表单时,View
的状态就被更新了,如果此时可以自动更新Model
的状态,那就相当于我们把Model
和View
做了双向绑定
关系图如下
二、双向绑定的原理是什么
我们都知道 Vue
是数据双向绑定的框架,双向绑定由三个重要部分构成
数据层(Model):应用的数据及业务逻辑
视图层(View):应用的展示效果,各类UI组件
业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来
而上面的这个分层的架构方案,可以用一个专业术语进行称呼:MVVM
这里的控制层的核心功能便是 “数据双向绑定” 。自然,我们只需弄懂它是什么,便可以进一步了解数据绑定的原理
理解ViewModel
它的主要职责就是:
数据变化后更新视图
视图变化后更新数据
当然,它还有两个主要部分组成
监听器(Observer):对所有数据的属性进行监听
解析器(Compiler):对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数
三、实现双向绑定
我们还是以
Vue
为例,先来看看Vue
中的双向绑定流程是什么的new Vue()
首先执行初始化,对data
执行响应化处理,这个过程发生Observe
中同时对模板执行编译,找到其中动态绑定的数据,从
data
中获取并初始化视图,这个过程发生在Compile
中同时定义⼀个更新函数和
Watcher
,将来对应数据变化时Watcher
会调用更新函数由于
data
的某个key
在⼀个视图中可能出现多次,所以每个key
都需要⼀个管家Dep
来管理多个Watcher
将来data中数据⼀旦发生变化,会首先找到对应的
Dep
,通知所有Watcher
执行更新函数
流程图如下:
实现
先来一个构造函数:执行初始化,对
data
执行响应化处理class Vue {constructor(options) {this.$options = options;this.$data = options.data;// 对data选项做响应式处理observe(this.$data);// 代理data到vm上proxy(this);// 执行编译new Compile(options.el, this);} }
对
data
选项执行响应化具体操作function observe(obj) {if (typeof obj !== "object" || obj == null) {return;}new Observer(obj); } class Observer {constructor(value) {this.value = value;this.walk(value);}walk(obj) {Object.keys(obj).forEach((key) => {defineReactive(obj, key, obj[key]);});} }
编译
Compile
对每个元素节点的指令进行扫描跟解析,根据指令模板替换数据,以及绑定相应的更新函数
class Compile {constructor(el, vm) {this.$vm = vm;this.$el = document.querySelector(el); // 获取domif (this.$el) {this.compile(this.$el);}}compile(el) {const childNodes = el.childNodes; Array.from(childNodes).forEach((node) => { // 遍历子元素if (this.isElement(node)) { // 判断是否为节点console.log("编译元素" + node.nodeName);} else if (this.isInterpolation(node)) {console.log("编译插值⽂本" + node.textContent); // 判断是否为插值文本 {{}}}if (node.childNodes && node.childNodes.length > 0) { // 判断是否有子元素this.compile(node); // 对子元素进行递归遍历}});}isElement(node) {return node.nodeType == 1;}isInterpolation(node) {return node.nodeType == 3 && /\{\{(.*)\}\}/.test(node.textContent);} }
依赖收集
视图中会用到
data
中某key
,这称为依赖。同⼀个key
可能出现多次,每次都需要收集出来用⼀个Watcher
来维护它们,此过程称为依赖收集多个
Watcher
需要⼀个Dep
来管理,需要更新时由Dep
统⼀通知实现思路
defineReactive
时为每⼀个key
创建⼀个Dep
实例初始化视图时读取某个
key
,例如name1
,创建⼀个watcher1
由于触发
name1
的getter
方法,便将watcher1
添加到name1
对应的Dep中当
name1
更新,setter
触发时,便可通过对应Dep
通知其管理所有Watcher
更新
// 负责更新视图 class Watcher {constructor(vm, key, updater) {this.vm = vmthis.key = keythis.updaterFn = updater // 创建实例时,把当前实例指定到Dep.target静态属性上Dep.target = this// 读一下key,触发getvm[key]// 置空Dep.target = null} // 未来执行dom更新函数,由dep调用的update() {this.updaterFn.call(this.vm, this.vm[this.key])} }
声明
Dep
class Dep {constructor() {this.deps = []; // 依赖管理}addDep(dep) {this.deps.push(dep);}notify() { this.deps.forEach((dep) => dep.update());} }
创建
watcher
时触发getter
class Watcher {constructor(vm, key, updateFn) {Dep.target = this;this.vm[this.key];Dep.target = null;} }
依赖收集,创建
Dep
实例function defineReactive(obj, key, val) {this.observe(val);const dep = new Dep();Object.defineProperty(obj, key, {get() {Dep.target && dep.addDep(Dep.target);// Dep.target也就是Watcher实例return val;},set(newVal) {if (newVal === val) return;dep.notify(); // 通知dep执行更新方法},}); }
##
浅谈vue双向绑定的原理相关推荐
- 浅谈vue双向绑定原理
简析mvvm框架 目前angular,reat和vue都是mvvm类型的框架 以vue为例 这里的vm 就是vue框架,它相当于中间枢纽的作用,连接着model 和view. 当前台显示的view发生 ...
- vue双向绑定的原理
之前我有个学生在面试的时候,面试官问vue的双向绑定如何实现?学生说用v-module实现.又问那么双向绑定的原理是什么?就回答不上来了,这个offer工资在18k左右,其他问题都回答上来了,如果这个 ...
- VUE双向绑定的原理(简单版)+虚拟DOM 节点的创建和更新
手动敲敲代码,就很容易理解了,供参考 1.以下是VUE双向绑定的原理(简单版) 主要是监听和defineProperty实现简单的双向绑定 <html><head></h ...
- Vue双向绑定:原理篇(详细)
文章目录 前言 什么是响应式 数据劫持 发布者-订阅者模式 模式简介 发布者 Observer 订阅器 dep 订阅者 Watcher 整体流程 初始化data data变为响应式数据 解析模板 收集 ...
- 浅聊vue双向绑定原理Object.defineProperty-/-Proxy
什么是双向绑定呢?vue又是怎么做的我们接下来就聊一聊 什么是双向绑定? 当数据模型data变化时,页面视图会得到响应更新 vue又是怎么做的? vue其实现原理是对data的getter/sette ...
- Vue学习笔记--Vue双向绑定实现原理
我们知道Vue可以实现数据双向绑定,Angular和Vue都是采用的MVVM 模式,意思就是当M(模型层)层数据进行修改时,VM层会监测到变化,并且通知V(视图层)层进行相应的修改,反之修改V层则会通 ...
- Vue面试题分享之Vue双向绑定数据原理
采用数据劫持结合发布-订阅者模式的方式,通过Object.definproperty()来劫持data里面各个属性的setter和getter钩子,在数据变动的时候,触发set方法,监测到数据发生变化 ...
- vue双向绑定原理源码解析
当我们学习angular或者vue的时候,其双向绑定为我们开发带来了诸多便捷,今天我们就来分析一下vue双向绑定的原理. 简易vue源码地址:https://github.com/maxlove123 ...
- 浅谈vue 之双向绑定和响应式(vue的响应式)
初识vue小伙伴通常都会被他的双向绑定所感叹,神奇?方便?而且在不少的面试中也会被面试官问到,上来就是:请问vue双向绑定的原来是什么?我们就来研究研究这是个什么东西: v-model 官方其实已经说 ...
最新文章
- 20145202、20145225、20145234 《信息安全系统设计基础》实验五 简单嵌入式WEB 服务器实验...
- [react] 什么是浅层渲染?
- c语言链表实现数组逆置,数组与链表等顺序表逆置
- 集合的get方法中参数从多少开始_源码分析CopyOnWriteArrayList 中的隐藏知识,你Get了吗?...
- ppt文字磨砂玻璃效果制作教程
- 关于 git pull 和 git pull origin develop 的区别
- Win11怎么创建系统映像?
- win7替换桌面图标
- Codeforces1509.B. TMT Document
- 冻结训练的理解与使用
- C++ 寻找完数 | Java 完数
- WMS多仓库调拨模块设计
- [学习笔记]基于ffmpeg的视频解码,输出YUV图像到文件。
- 不要轻易使用TerminateThread中止线程
- gh60(OK60RGB)刷固件折腾日志(MacOs版)
- 计算机病毒与防范 论文,计算机病毒与防范论文
- 奇虎360支持Unity引擎 将推3D页游无插件安装
- [时间管理]TED-如何掌控你的时间
- 基于JAVA社区管理系统计算机毕业设计源码+系统+lw文档+部署
- usaco-milk2-pass
热门文章
- 服务器处理器(Xeon)和家用处理器(酷睿 锐龙)有什么区别?
- CIO如何管理企业业务流程
- 2019PMP考试考场规则+答题卡注意事项
- 被ASP的小问题难倒!
- Python--[项目]机器学习之电影推荐系统[基于物品的协同过滤](代码版)
- python好就业么_Python语言就业前景怎么样?好吗?
- 查看Mac本机的Python3的安装路径
- 从0开始,精通Go语言Rest微服务架构和开发
- URL access forbidden for unknown reason svn: E170001: OPTIONS of 403 Forbidden (https://**/**)
- 网站的视觉路径和版式设计