Vue响应式和双向绑定的原理
前言 我们都知道,Vue是一个构建数据驱动的web界面的渐进式框架。Vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。(摘自百度百科)这段Vue的定义明确了Vue的几大特点:数据驱动、渐进式、响应式、组件化、声明式渲染。&nb
前言
我们都知道,Vue是一个构建数据驱动的web界面的渐进式框架。Vue.js的目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。(摘自百度百科)这段Vue的定义明确了Vue的几大特点:数据驱动、渐进式、响应式、组件化、声明式渲染。
对于Vue的渐进式和组件化这里不作赘述,本文具体看看Vue的数据驱动、响应式的原理,文末还会试着实现一个简单的双向绑定。
什么是数据驱动和双向绑定?
所谓数据驱动,就是当数据发生变化的时候,用户界面发生相应的变化,开发者不需要手动的去修改dom,Vue会自动的根据数据渲染页面。这就是声明式渲染的概念,开发者借助Vue提供的API,只需要关注结果而不用关注具体是怎么实现的(与命令式渲染的区别),同时这也是Vue响应式的基础。我们都知道Vue是一个MVVM模式的框架,model和view的变化会通过viewmodel实时的反映在对方上(也就是我们常说的双向绑定),这样以来开发人员就不必过多关注dom操作而专注于业务逻辑,同时不触碰dom使得我们的代码易于维护。那么,Vue是怎么做到这一点的呢?
Vue响应式和双向绑定的原理
Vue的双向绑定是采用“数据劫持结合发布-订阅者”模式实现的。我们结合官方文档的图来具体看一下Vue双向绑定的原理。
Vue实例在初始化时,遍历在Observer(观察者)中所有属性通过Object.defineProperty()来实现他们的存取描述符(getter和setter),这样以来给任何对象的任意属性赋值都会触发该属性的setter,那么就能监听到数据变化。同时每个属性都会设置一个Dep(消息订阅器),他内部维护了一个数组,用来记录所有Watcher(订阅者)。
然后Vue通过Compile(解析器)编译模板,将模板中的变量替换成对应的数据并渲染页面视图。此时Watcher会将自己添加到Dep中,到这里一个Vue实例的初始化完毕。
当属性值发生改变时,触发setter函数,setter会调用Dep.notify()通知每一个订阅该属性的Watcher,Watcher会调用自身的update()函数对视图进行更新。这样一来双向绑定就实现了。
关于Object.defineProperty(obj,prop,descriptor)
在使用js实现简单的双向绑定之前,我们要先来看一下这个不可或缺的函数,Object.defineProperty(obj,prop,descriptor)可以定义或修改对象的一个属性,并对这个属性的描述符进行设置。
对于该函数的参数,obj是需要进行定义或修改的属性所属于的对象。prop是需要进行定义或修改的属性。descriptor是prop属性的描述符,它是以对象的形式传入的,有六个选项:value是该属性的值、writable表示该属性是否可写、enumerable表示该属性是否可以被遍历获得、configurable表示该属性是否可删除以及writable以外的描述符是否可改、set是该属性值被设置时执行的回调函数(默认是undefined)、get是该属性值被获得时执行的回调函数(默认是undefined)。在descriptor的六个选项中,数据描述符(value和writable)和存取描述符(get和set)是不可共存的。
js手撸一个简单的双向绑定
废话不多说,先上代码。
<!DOCTYPE html>
<html lang="en">
<head>
<title>双向绑定demo</title>
<meta charset="UTF-8">
</head>
<body>
<div id="app">
<div>双向绑定demo</div>
<input type="text" id="input">
<div>
<span>input:</span>
<span id="output"></span>
</div>
</div>
</body>
<script>
var obj={}
Object.defineProperty(obj,'input',{
get:function(){
return obj.input
},
set:function(value){
document.getElementById('input').value = value
document.getElementById('output').innerHTML = value
}
})
document.addEventListener('keyup',function(e){
obj.input = e.target.value
})
</script>
</html>
这里我摆了一个输入框和一个span,span的文本、输入框的值和obj的属性input实现双向绑定。直接看js部分,定义了一个对象obj,用Object.defineProperty()给obj添加了一个属性input,并给该属性设置了get和set。给文本添加监听,当按键弹起时,修改obj对象的input属性,这时触发input属性的setter修改span内的文本。效果如下:
当直接修改obj的input属性时,触发input的setter,修改输入框的值和span内的文本,效果如下:
这样一个简单的双向绑定demo就完成了。
以上是我对Vue响应式和双向绑定的理解,如有错误还请大牛指正,如有不同意见也欢迎质疑,希望对大家有所帮助,也希望同样在准备春招的朋友一切顺利。
更多推荐
所有评论(0)