-
2021-06-11 15:02:28
vue2数据双向绑定原理
// An highlighted block function compile(node, vm) { var reg = /\{\{(.*)\}\}/ // 节点类型为元素 if (node.nodeType === 1) { var attr = node.attributes // 解析属性 for (var i = 0; i < attr.length; i++) { if (attr[i].nodeName == 'v-model') { var name = attr[i].nodeValue // 获取v-model绑定的属性名 node.addEventListener('input', function(e) { // 给相应的data属性赋值,进而触发属性的set方法 vm[name] = e.target.value }) node.value = vm.data[name] // 将data的值赋值给该node node.removeAttribute('v-model') } } } // 节点类型为text if (node.nodeType === 3) { if (reg.test(node.nodeValue)) { var name = RegExp.$1 // 获取匹配到的字符串 name = name.trim() // node.nodeValue = vm.data[name] // 将data的值赋值给该node new Watcher(vm, node, name) } } } function nodeToFragment(node, vm) { var flag = document.createDocumentFragment() var child while ((child = node.firstChild)) { compile(child, vm) flag.appendChild(child) // 将子节点劫持到文档片段中 } return flag } function defineReactive(obj, key, val, dep) { // 响应式的数据绑定 Object.defineProperty(obj, key, { get: function() { if (Dep.target) { dep.addSub(Dep.target) } console.log(dep) return val }, set: function(newVal) { if (newVal === val) { return } else { val = newVal dep.notify() } } }) } function observe(obj, vm) { var dep = new Dep() Object.keys(obj).forEach(function(key) { defineReactive(vm, key, obj[key], dep) }) } function Dep() { this.subs = [] } Dep.prototype = { addSub(sub) { this.subs.push(sub) }, notify() { this.subs.forEach(element => { element.update() }) } } function Watcher(vm, node, name) { Dep.target = this this.name = name this.node = node this.vm = vm this.update() Dep.target = null } Watcher.prototype = { update() { this.get() this.node.nodeValue = this.value }, get() { this.value = this.vm[this.name] } } function Vue(options) { this.data = options.data observe(this.data, this) var id = options.el var dom = nodeToFragment(document.getElementById(id), this) // 编译完成后,将dom返回到app中。 document.getElementById(id).appendChild(dom) } var vm = new Vue({ el: 'app', data: { text: 'hello world', text2: 'dfdfdf' } })
更多相关内容 -
vue2双向数据绑定原理
2022-03-21 14:59:14vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。 具体步骤: 第一步: 需要...先上文字描述:
vue.js是采用
数据劫持
结合发布者-订阅者模式
的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。具体步骤:
第一步: 需要
observer(观察者)
对数据对象进行递归遍历
,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值
,就会触发setter
,那么就能监听到了数据变化第二步:
compile(模板解析器)
解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图第三步:
Watcher(订阅者)
是Observer
和Compile
之间通信的桥梁,主要做的事情是:
1、在自身实例化时往属性订阅器(dep
)里面添加自己
2、自身必须有一个update
()方法
3、待属性变动dep.notice()
通知时,能调用自身的update()方法
,并触发Compile中绑定的回调
,则功成身退。第四步:
MVVM
作为数据绑定的入口,整合Observer、Compile和Watcher三者,
通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。回答以上内容即可,下方内容,可以帮助大家理解
代码实现vue2双向数据绑定
vue.js文件
class Vue{ constructor(options){ this.$data = options.data // 调用数据劫持的方法 Observe(this.$data) // 属性代理 Object.keys(this.$data).forEach(key=>{ Object.defineProperty(this,key,{ enumerable:true, configurable:true, get(){ return this.$data[key] }, set(newValue){ this.$data[key] = newValue } }) }) // 调用模板编译的函数 Compile(options.el,this) } } // 定义一个数据劫持的方法 function Observe(obj){ // 递归的终止条件 if(!obj || typeof obj !== 'object') return const dep = new Dep() // 通过Object.keys(obj) 获取到当前obj上的每个属性 Object.keys(obj).forEach(key=>{ // 当前被循环的key所对应的属性值 let value = obj[key] // 把value这个子节点,进行递归 Observe(value) // 需要为当前的key所对应的属性,添加getter和setter Object.defineProperty(obj,key,{ enumerable:true, configurable:true, get(){ Dep.target && dep.addSub(Dep.target) console.log(`有人读取了${key}的值`); return value }, set(newVal){ value = newVal Observe(value) dep.notify() }, }) }) } // 对HTML结构进行模板编译的方法 function Compile(el,vm){ // 获取el对应的DOM元素 vm.$el = document.querySelector(el) const fragment = document.createDocumentFragment() while((childNode = vm.$el.firstChild)){ fragment.appendChild(childNode) } // 进行模板编译 replace(fragment) vm.$el.appendChild(fragment) function replace(node){ // 定义匹配插值表达式的正则 const regMustache = /\{\{\s*(\S+)\s*\}\}/ // 证明当前的node节点是一个文本子节点,需要进行正则的替换 if(node.nodeType===3){ // 注意:文本子节点,也是一个DOM对象,如果要获取文本子节点的字符串内容,需要调用textContent属性获取 const text = node.textContent const execResult = regMustache.exec(text) if(execResult){ const value = execResult[1].split('.').reduce((newObj,k)=>newObj[k],vm) node.textContent = text.replace(regMustache,value) new Watcher(vm,execResult[1],(newValue)=>{ node.textContent = text.replace(regMustache,newValue) }) } // 终止递归的条件 return } // 判断当前的node节点是否为input输入框 if(node.nodeType===1 && node.tagName.toUpperCase() === 'INPUT'){ const attrs = Array.from(node.attributes) const findResult = attrs.find((x)=>x.name==='v-model') if(findResult){ const expStr = findResult.value const value = expStr.split('.').reduce((newObj,k)=>newObj[k],vm) node.value = value new Watcher(vm,expStr,(newValue)=>{ node.value = newValue }) // 监听文本框的input输入事件,拿到文本框最新的值,把最新的值,更新到vm上即可 node.addEventListener('input',(e)=>{ const keyArr = expStr.split('.') const obj = keyArr.slice(0,keyArr.length-1).reduce((newObj,k)=>newObj[k],vm) obj[keyArr[keyArr.length-1]] = e.target.value }) } } // 证明不是文本节点,可能是一个DOM元素,需要进行递归处理 node.childNodes.forEach(child=>replace(child)) } } // 收集依赖/收集订阅者 class Dep{ constructor(){ // 今后,所有的watcher都要存到这个数组中 this.subs = [] } // 向 subs 数组中,添加watcher的方法 addSub(watcher){ this.subs.push(watcher) } // 负责通知每个watcher的方法 notify(){ this.subs.forEach(watcher=>watcher.update()) } } class Watcher{ constructor(vm,key,cb){ this.vm = vm this.key = key this.cb = cb Dep.target = this key.split('.').reduce((newObj,k)=>newObj[k],vm ) Dep.target = null } update(){ const value = this.key.split('.').reduce((newObj,k)=>newObj[k],this.vm) this.cb(value) } }
html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"> <h3>姓名:{{name}}</h3> <h3>年龄:{{age}}</h3> <h3>info.a的值是:{{info.a}}</h3> <div>name的值:<input type="text" v-model="name"></div> <div>info.a的值:<input type="text" v-model="info.a"></div> </div> <script src="./vue.js"></script> <script> const vm = new Vue({ el:"#app", data:{ name:'zs', age:20, info:{ a:'a1', c:'c1' } } }) </script> </body> </html>
-
详解Vue双向数据绑定原理解析
2020-08-29 11:10:56本篇文章主要介绍了详解Vue双向数据绑定原理解析 ,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
Vue的双向数据绑定原理
2021-06-16 18:56:39vue.js是采用 数据劫持 结合 发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter ,getter ,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。 具体步骤 需要 observer...vue.js是采用
数据劫持
结合发布者-订阅者模式
的方式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。具体步骤
- 需要
observer
的数据对象进行 递归遍历,包括子属性对象的属性,都加上setter
和getter
这样的话,给这个对象的某个属性赋值
,就会触发setter
,那么就能监听到了数据变化。 compile
解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图。watcher
订阅者是Observer
和compile
之间通信的桥梁,主要做的事情是:
1)在自身实例化时往属性订阅器(dep
)里面添加自己
2)自身必须有一个update()
方法
3)当属性变动dep.notice()
通知时,能调用自身的update()
方法,并触发 compile中绑定的回调。MVVM
作为数据绑定的入口,整合Observer、Compile
和Watcher
三者,通过Observer
来监听自己的model数据变化,通过Compile
来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
什么是setter、getter
答:首先,别误以为他们就是一会要说的get、set。
对象有两种属性:数据属性
: 就是我们经常使用的属性访问器属性
: 也称存取器属性(存取器属性就是一组获取和设置值的函数)
数据属性就是a和b;get和set就是关键字 它们后面各自对应一个函数,这个函数就是上面红字部分所讲的,存储器属性。
get对应的方法称为getter,负责获取值,它不带任何参数。set对应的方法为setter,负责设置值,在它的函数体中,一切的return都是无效的。
什么是Object.defineProperty()?
答:我们先看一句定义:
对象是由多个名/值对组成的无序的集合。对象中每个属性对应任意类型的值。
定义对象可以使用构造函数或字面量的形式:
除了以上添加属性的方式,当然还可以使用Object.defineProperty定义新属性或修改原有的属性;语法
Object.defineProperty(obj, prop, descriptor)
参数
- obj: 必需。目标对象;
- prop: 必需。需定义或修改的属性的名字;
- descriptor: 必需。目标属性所拥有的特性;
返回值
传入函数的对象,即第一个参数obj;
原理
在vue中
v-model
,v-name
,{{}}
等都可以对数据进行展示,也就是说假如一个属性都通过这三个指令了,那么每当这个属性改变的时候,相应的这个三个指令的html视图也必须改变;于是vue中就是每当有这样的可能用到双向绑定的指令,就在一个
Dep
中增加一个订阅者(addSub)
,其订阅者只是更新自己的指令对应的数据,也就是v-model='name'
和{{name}}
有两个对应的订阅者,各自管理自己的地方;每当属性的set方法触发,就循环更新
Dep
中的订阅者(notify)
;集合上面的那张图来看,就是
Observer
一旦有了set
触发,就会通知到Dep
,那Dep接到通知之后呢?从图上来看,下面所讲的就应该是Compile
了,也很简单:首先,先要知道它负责干什么?
compile主要做的事情是解析模板指令,将模板中的变量替换成数据;
其次知道它什么时候要工作,只有两种情况,先上图:
1)初始化,init的时候 初始化渲染页面视图;2)将每个指令对应的节点绑定更新函数,添加监听数据的订阅者;
Dep负责维护依赖,而订阅者则来自于compile,一旦有数据变动,则会通过Watcher绑定更新函数,此时Watcher也向Dep中添加了订阅者,一旦Dep接到Observer的通知,它就会再去通知Watcher,Watcher则会调用自身的update()方法,并触发Compile中绑定的回调,更新视图;
总结
首先我们为每个vue属性用Object.defineProperty()实现数据劫持,为每个属性分配一个订阅者集合的管理数组dep;
然后在编译的时候在该属性的数组dep中添加订阅者,v-model会添加一个订阅者,{{}}也会,v-bind也会,只要用到该属性的指令理论上都会;
接着为input会添加监听事件,修改值就等于为该属性赋值,则会触发该属性的set方法,在set方法内通知订阅者数组dep,订阅者数组循环调用各订阅者的update方法更新视图。
- 需要
-
Vue 3.0双向绑定原理的实现方法
2020-12-13 03:49:18proxy方法 ...可查看Vue 2.0双向绑定原理的实现 具体实现过程的代码如下: 1、定义构造函数 function Vue(option){ this.$el = document.querySelector(option.el); //获取挂载节点 this.$data = -
基于Vue2.0数据双向绑定原理-详解
2021-05-13 16:03:16到这里我们的整个的模板编译也已经完成,不过这里我们并没有实现过多的指令,我们只是简单的实现了 v-model 指令,本意是通过这篇文章让大家熟悉与认识 Vue 的双向绑定原理,并不是去创造一个新的 MVVM 实例。...在线使用-线上测试-源码
//代码: <div id="app"> <input v-model="name" type="text"> <h1>{{ name }}</h1> </div> <script src="./js/observer.js"></script> <script src="./js/watcher.js"></script> <script src="./js/compile.js"></script> <script src="./js/index.js"></script> <script> const vm = new Mvue({ el: "#app", data: { name: "我是摩登" } }); </script>
数据绑定
在正式开始之前我们先来说说数据绑定的事情,数据绑定我的理解就是让数据M(model)展示到 视图V(view)上。我们常见的架构模式有 MVC、MVP、MVVM模式,目前前端框架基本上都是采用 MVVM 模式实现双向绑定,Vue 自然也不例外。但是各个框架实现双向绑定的方法略有所不同,目前大概有三种实现方式。
- 发布订阅模式
- Angular 的脏查机制
- 数据劫持
而 Vue2.0 则采用的是数据劫持与发布订阅相结合的方式实现双向绑定,数据劫持主要通过
Object.defineProperty
来实现。Object.defineProperty
这篇文章我们不详细讨论
Object.defineProperty
的用法,我们主要看看它的存储属性 get 与 set。我们来看看通过它设置的对象属性之后有何变化。var people = { name: "Modeng", age: 18 } people.age; //18 people.age = 20;
上述代码就是普通的获取/设置对象的属性,看不到什么奇怪的变化。
var modeng = {} var age; Object.defineProperty(modeng, 'age', { get: function () { console.log("获取年龄"); return age; }, set: function (newVal) { console.log("设置年龄"); age = newVal; } }); modeng.age = 18; console.log(modeng.age);
你会发现通过上述操作之后,我们访问 age 属性时会自动执行 get 函数,设置 age 属性时,会自动执行 set 函数,这就给我们的双向绑定提供了非常大的方便。
剖析
我们知道 MVVM 模式在于数据与视图的保持同步,意思是说数据改变时会自动更新视图,视图发生变化时会更新数据。
所以我们需要做的就是如何检测到数据的变化然后通知我们去更新视图,如何检测到视图的变化然后去更新数据。检测视图这个比较简单,无非就是我们利用事件的监听即可。
那么如何才能知道数据属性发生变化呢?这个就是利用我们上面说到的
Object.defineProperty
当我们的属性发生变化时,它会自动触发 set 函数从而能够通知我们去更新视图。实现
通过上面的描述与分析我们知道 Vue 是通过数据劫持结合发布订阅模式来实现双向绑定的。我们也知道数据劫持是通过
Object.defineProperty
方法,当我们知道这些之后,我们就需要一个监听器 Observer 来监听属性的变化。得知属性发生变化之后我们需要一个 Watcher 订阅者来更新视图,我们还需要一个 compile 指令解析器,用于解析我们的节点元素的指令与初始化视图。所以我们需要如下:- Observer 监听器:用来监听属性的变化通知订阅者
- Watcher 订阅者:收到属性的变化,然后更新视图
- Compile 解析器:解析指令,初始化模版,绑定订阅者
监听器 Observer
监听器的作用就是去监听数据的每一个属性,我们上面也说了使用
Object.defineProperty
方法,当我们监听到属性发生变化之后我们需要通知 Watcher 订阅者执行更新函数去更新视图,在这个过程中我们可能会有很多个订阅者 Watcher 所以我们要创建一个容器 Dep 去做一个统一的管理。function defineReactive(data, key, value) { //递归调用,监听所有属性 observer(value); var dep = new Dep(); Object.defineProperty(data, key, { get: function () { if (Dep.target) { dep.addSub(Dep.target); } return value; }, set: function (newVal) { if (value !== newVal) { value = newVal; dep.notify(); //通知订阅器 } } }); } function observer(data) { if (!data || typeof data !== "object") { return; } Object.keys(data).forEach(key => { defineReactive(data, key, data[key]); }); } function Dep() { this.subs = []; } Dep.prototype.addSub = function (sub) { this.subs.push(sub); } Dep.prototype.notify = function () { console.log('属性变化通知 Watcher 执行更新视图函数'); this.subs.forEach(sub => { sub.update(); }) } Dep.target = null;
以上我们就创建了一个监听器 Observer,我们现在可以尝试一下给一个对象添加监听然后改变属性会有何变化。
var modeng = { age: 18 } observer(modeng); modeng.age = 20;
我们可以看到浏览器控制台打印出 “属性变化通知 Watcher 执行更新视图函数” 说明我们实现的监听器没毛病,既然监听器有了,我们就可以通知属性变化了,那肯定是需要 Watcher 的时候了。
订阅者 Watcher
Watcher 主要是接受属性变化的通知,然后去执行更新函数去更新视图,所以我们做的主要是有两步:
- 把 Watcher 添加到 Dep 容器中,这里我们用到了 监听器的 get 函数
- 接收到通知,执行更新函数。
function Watcher(vm, prop, callback) { this.vm = vm; this.prop = prop; this.callback = callback; this.value = this.get(); } Watcher.prototype = { update: function () { const value = this.vm.$data[this.prop]; const oldVal = this.value; if (value !== oldVal) { this.value = value; this.callback(value); } }, get: function () { Dep.target = this; //储存订阅器 const value = this.vm.$data[this.prop]; //因为属性被监听,这一步会执行监听器里的 get方法 Dep.target = null; return value; } }
这一步我们把 Watcher 也给弄了出来,到这一步我们已经实现了一个简单的双向绑定了,我们可以尝试把两者结合起来看下效果。
function Mvue(options, prop) { this.$options = options; this.$data = options.data; this.$prop = prop; this.$el = document.querySelector(options.el); this.init(); } Mvue.prototype.init = function () { observer(this.$data); this.$el.textContent = this.$data[this.$prop]; new Watcher(this, this.$prop, value => { this.$el.textContent = value; }); }
这里我们尝试利用一个实例来把数据与需要监听的属性传递进来,通过监听器监听数据,然后添加属性订阅,绑定更新函数。
<div id="app">{{ name }}</div> const vm = new Mvue({ el: "#app", data: { name: "我是摩登" } }, "name");
我们可以看到数据已经正常的显示在页面上,那么我们在通过控制台去修改数据,发生变化后视图也会跟着修改。
到这一步我们我们基本上已经实现了一个简单的双向绑定,但是不难发现我们这里的属性都是写死的,也没有指令模板的解析,所以下一步我们来实现一个模板解析器。
Compile 解析器
Compile 的主要作用一个是用来解析指令初始化模板,一个是用来添加添加订阅者,绑定更新函数。
因为在解析 DOM 节点的过程中我们会频繁的操作 DOM, 所以我们利用文档片段(DocumentFragment)来帮助我们去解析 DOM 优化性能。
function Compile(vm) { this.vm = vm; this.el = vm.$el; this.fragment = null; this.init(); } Compile.prototype = { init: function () { this.fragment = this.nodeFragment(this.el); }, nodeFragment: function (el) { const fragment = document.createDocumentFragment(); let child = el.firstChild; //将子节点,全部移动文档片段里 while (child) { fragment.appendChild(child); child = el.firstChild; } return fragment; } }
然后我们就需要对整个节点和指令进行处理编译,根据不同的节点去调用不同的渲染函数,绑定更新函数,编译完成之后,再把 DOM 片段添加到页面中。
Compile.prototype = { compileNode: function (fragment) { let childNodes = fragment.childNodes; [...childNodes].forEach(node => { let reg = /\{\{(.*)\}\}/; let text = node.textContent; if (this.isElementNode(node)) { this.compile(node); //渲染指令模板 } else if (this.isTextNode(node) && reg.test(text)) { let prop = RegExp.$1; this.compileText(node, prop); //渲染 {{ }}模板 } //递归编译子节点 if (node.childNodes && node.childNodes.length) { this.compileNode(node); } }); }, compile: function (node) { let nodeAttrs = node.attributes; [...nodeAttrs].forEach(attr => { let name = attr.name; if (this.isDirective(name)) { let value = attr.value; if (name === "v-model") { this.compileModel(node, value); } node.removeAttribute(name); } }); }, //略 }
因为代码比较长如果全部贴出来会影响阅读,我们主要是讲整个过程实现的思路,文章结束我会把源码发出来,有兴趣的可以去查看全部代码。
到这里我们的整个的模板编译也已经完成,不过这里我们并没有实现过多的指令,我们只是简单的实现了
v-model
指令,本意是通过这篇文章让大家熟悉与认识 Vue 的双向绑定原理,并不是去创造一个新的 MVVM 实例。所以并没有考虑很多细节与设计。现在我们实现了 Observer、Watcher、Compile,接下来就是把三者给组织起来,成为一个完整的 MVVM。
创建 Mvue
这里我们创建一个 Mvue 的类(构造函数)用来承载 Observer、Watcher、Compile 三者。
function Mvue(options) { this.$options = options; this.$data = options.data; this.$el = document.querySelector(options.el); this.init(); } Mvue.prototype.init = function () { observer(this.$data); new Compile(this); }
然后我们就去测试一下结果,看看我们实现的 Mvue 是不是真的可以运行。
<div id="app"> <h1>{{ name }}</h1> </div> <script src="./js/observer.js"></script> <script src="./js/watcher.js"></script> <script src="./js/compile.js"></script> <script src="./js/index.js"></script> <script> const vm = new Mvue({ el: "#app", data: { name: "完全没问题,看起来是不是很酷!" } }); </script>
我们尝试去修改数据,也完全没问题,但是有个问题就是我们修改数据时时通过
vm.$data.name
去修改数据,而不是想 Vue 中直接用vm.name
就可以去修改,那这个是怎么做到的呢?其实很简单,Vue 做了一步数据代理操作。数据代理
我们来改造下 Mvue 添加数据代理功能,我们也是利用
Object.defineProperty
方法进行一步中间的转换操作,间接的去访问。function Mvue(options) { this.$options = options; this.$data = options.data; this.$el = document.querySelector(options.el); //数据代理 Object.keys(this.$data).forEach(key => { this.proxyData(key); }); this.init(); } Mvue.prototype.init = function () { observer(this.$data); new Compile(this); } Mvue.prototype.proxyData = function (key) { Object.defineProperty(this, key, { get: function () { return this.$data[key] }, set: function (value) { this.$data[key] = value; } }); }
到这里我们就可以像 Vue 一样去修改我们的属性了,非常完美
-
Vue 双向数据绑定原理
2019-03-07 14:20:57vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来...vue实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set... -
Angular和Vue双向数据绑定的实现原理(重点是vue的双向绑定)
2020-09-01 03:54:15主要介绍了Angular和Vue双向数据绑定的实现原理(重点是vue的双向绑定),非常不错,具有参考借鉴价值,感兴趣的朋友一起看看吧 -
vue2双向绑定原理
2021-06-16 16:32:031、vue双向绑定是通过“数据劫持”结合“发布者订阅”模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图也发生变化,视图变化,数据也随之改变。 方法:Object.defineProperty(obj, prop, descriptor... -
Vue的双向数据绑定实现原理解析
2021-01-19 14:46:12这篇文章主要介绍了Vue的双向数据绑定实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一、概述 vuejs是采取数据劫持结合发布者-订阅者模式的... -
vue3双向数据绑定原理
2021-10-12 15:44:171.1 通过ref起别名,通过$refs获取实例、 绑定input事件、将值定义在响应数据rective中 <input type="text" ref="reftxt" @input="getValue" :value="txt"> 1.2 导入需要的钩子 reactive(响应数据)、toRefs... -
vue双向数据绑定原理探究(附demo)
2020-08-31 15:46:52本文主要介绍了vue双向数据绑定的原理,文章结尾附上完整demo下载。具有一定的参考价值,下面跟着小编一起来看下吧 -
vue数据双向绑定原理解析(get & set)
2020-11-29 10:18:27angular,react,vue等mv*模式的框架都实现了数据双向绑定;angular是通过脏检查即新老数据的比较来确定哪些数据发生了变化,从而将它更新到view中;vue则是通过设置数据的get和set函数来实现的,这种方式在性能上是... -
vue2.0源码之数据双向绑定原理和实现
2021-08-11 11:43:50vue源码之数据双向绑定原理一.双向绑定的原理介绍二.代码简单实现 这里什么说是vue2.0的双向绑定原理是因为和vue3.0的实现方式是有区别的。 一.双向绑定的原理介绍 vue的双向绑定是数据和视图的同步变化,即当数据... -
vue双向数据绑定原理
2020-06-20 12:03:411.1 vue双向数据绑定原理,又称vue响应式原理,是vue的核心,双向数据绑定是通过数据劫持结合发布订阅模式的方式来实现的,也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变 ... -
Vue2.x实现双向数据绑定原理
2019-05-13 23:06:59Vue2.x实现双向数据绑定原理 它的实现的核心是通过Object.defineProperty(),对data的每个属性进行了get、set的拦截。 其实只用Object.defineProperty()已经可以实现双向数据绑定,只是这样效率非常低。 一般... -
vue中的数据绑定原理的实现
2020-12-01 12:33:44本文主要介绍了vue中的数据绑定原理的实现,分享给大家,也给自己留个笔记,具体如下: vue中的响应式数据绑定是通过数据劫持和观察者模式来实现的。当前学习源码为vue2.0 源码关键目录 src |---core | |---... -
vue双向数据绑定原理(vue2和vue3的区别)
2022-01-29 19:42:29vue.js是采用数据劫持结合发布者-订阅者模式的方式, 通过Object.defineProperty()来劫持各个属性的setter,getter, 在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。 具体步骤 第一步: 需要... -
通过源码分析Vue的双向数据绑定详解
2020-12-12 23:24:41前言 虽然工作中一直使用Vue作为基础库,但是对于其实现机理仅限于道听途说,这样对长期的技术发展很不利。所以最近攻读了其源码的一...Vue的双向数据绑定的设计思想为观察者模式,为了方便,下文中将被观察的对象称 -
面试题1:Vue的双向数据绑定原理是什么?
2021-06-09 19:42:08原理(Vue2.x): Vue.js它是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter;在数据变动时发布消息给订阅者,触发相应的监听回调。 我们知道,实现MVVM... -
Vue实现双向绑定的原理以及响应式数据的方法
2020-08-27 06:49:59主要介绍了Vue实现双向绑定的原理以及响应式数据的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
vue双向数据绑定原理、vue2和vue3原理的不同点
2020-07-30 11:49:56受疫情影响,今年各行业不景气,各岗位的跳槽...(一)Vue2双向数据绑定原理 简单理解: vue2数据双向绑定是由数据劫持结合发布-订阅的模式实现的,通过object.defineProperty()来劫持对象属性的getter和setter操作, -
vue数据双向绑定的实现与原理解析(核心完整代码)
2018-09-25 16:43:46先声明,该代码是网上一位大佬提供的,但是学习它的代码过程中...该压缩文件内容是vue数据双向绑定的实现与原理解析,提供核心完整代码,并有我的代码注释,浅显易懂,但是需要es6的学习和有一定的javascript基础才行。 -
Vue数据双向绑定底层实现原理
2020-10-15 23:30:04主要为大家详细介绍了Vue数据双向绑定底层实现原理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
vue 数据双向绑定 原理
2022-02-05 17:22:04vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。 vue会遍历此data中对象所有的属性 并使用Object.defineProperty把这些属性全部转为gettter/setter 而每个组件实例都有watcher对象 会在组件...