vue的响应式核心方法 Object.defineProperty详解

  • 关于vue响应式原理的文章太多了,看了不少,仍是看看mdn的解释,完全理解一下到底什么是Object.defineProperty。这个方法具体怎么用。参数都是什么。才会完全理解vue到底怎么劫持数据而且响应的。

vue2.0的核心方法

Object.defineProperty(obj,prop,descriptor)javascript

vue核心简说

vue.js采用的是数据劫持++++发布-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。那么Object咱们知道是一个对象,defineProperty()这个方法是什么呢?做用是什么呢,我 们来一块儿分析一下html

mdn文档解释Object.definePropertyvue

核心的方法

Object.defineProperty()这个方法包含三个参数,java

  • obj是要在其上定义属性的对象,简单说就是你要操做的那个对象api

  • prop要定义或修改属性的名称,简单说就是你要操做的那个对象下的属性(对象下没有那个属性怎么办?能够本身设置的数组

  • descriptor将定义或修改的属性描述:注意这个不知道就要看api了,他有这几个属性bash

descriptor属性描述符

  1. 对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符

数据描述符是一个具备值的属性,该值多是可写的,也可能不是可写的。app

存取描述符是由getter-setter函数对描述的属性。函数

描述符必须是这两种形式之一;不能同时是二者。测试

  1. 共存关系

(1)数据描述符和存取描述符均具备如下可选键值(默认值是在使用Object.defineProperty()定义属性的状况下):

configurable 当且仅当该属性的 configurable 为 true 时,该属性描述符才可以被改变,同时该属性也能从对应的对象上被删除。默认为 false。

enumerable 当且仅当该属性的enumerable为true时,该属性才可以出如今对象的枚举属性中。默认为 false。

(2)数据描述符同时具备如下可选键值:

value 该属性对应的值。能够是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。

writable 当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。

(3)存取描述符同时具备如下可选键值:(划重点啊。这是关键啊,其实就是函数)

get一个给属性提供 getter 的方法,若是没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,可是会传入this对象(因为继承关系,这里的this并不必定是定义该属性的对象)。默认为 undefined。

set 一个给属性提供 setter 的方法,若是没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受惟一参数,即该属性新的参数值。 默认为 undefined。

上面啥意思呢,意思是说啊,descriptor属性描述符总共有6个是属性
configurable
enumerable

value
writable

get
set

可是6个不能同时设置,
不然会报错。其中共存属性能够一直存在。其余四个两两一组。有你没我。有我没你的意思

要么
configurable
enumerable
value
writable

要么
configurable
enumerable
get
set

复制代码
  1. 共存属性和数据描述符号属性讲解
var obj = {
    test:"hello"
}
//对象已有的属性添加特性描述 若是对象自己有这个属性,就正好能够操做了
Object.defineProperty(obj,"test",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
});
//对象新添加的属性的特性描述,若是对象没有这个属性,就写上,就至关于添加上这个属性,也能够进行操做
Object.defineProperty(obj,"newKey",{
    configurable:true | false,
    enumerable:true | false,
    value:任意类型的值,
    writable:true | false
})
复制代码

(1) value(数据描述符)

// 属性对应的值,可使任意类型的值,默认为undefined

var obj = {}
//第一种状况:不设置value属性
Object.defineProperty(obj,"newKey",{
 
});
console.log( obj.newKey );  //undefined
------------------------------
//第二种状况:设置value属性
Object.defineProperty(obj,"newKey",{
    value:"hello"
});
console.log( obj.newKey );  //hello
复制代码

(2) writable(数据描述符)

//属性的值是否能够被重写。设置为true能够被重写;设置为false,不能被重写。默认为false。

var obj = {}
//第一种状况:writable设置为false,不能重写。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //hello
 
//第二种状况:writable设置为true,能够重写
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true
});
//更改newKey的值
obj.newKey = "change value";
console.log( obj.newKey );  //change value
复制代码

(3)enumerable(共存描述符)

// 此属性是否能够被枚举(使用for...in或Object.keys())。设置为true能够被枚举;设置为false,不能被枚举。默认为false。


var obj = {}
//第一种状况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false
});
 
//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  // undefined
}
//----------------------------------------
//第二种状况:enumerable设置为true,能够被枚举。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:true
});
 
//枚举对象的属性
for( var attr in obj ){
    console.log( attr );  //newKey
}
复制代码

(4)configurable(共存描述符)

//是否能够删除目标属性或是否能够再次修改属性的特性(writable, configurable, enumerable)。
//设置为true能够被删除或能够从新设置特性;设置为false,不能被能够被删除或不能够从新设置特性。默认为false。

//这个属性起到两个做用:

//1.目标属性是否可使用delete删除

//2.目标属性是否能够再次设置特性


//-----------------测试目标属性是否能被删除------------------------
var obj = {}
//第一种状况:configurable设置为false,不能被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //hello
 
//第二种状况:configurable设置为true,能够被删除。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
//删除属性
delete obj.newKey;
console.log( obj.newKey ); //undefined
 
//-----------------测试是否能够再次修改特性------------------------
var obj = {}
//第一种状况:configurable设置为false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:false
});
 
//从新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey
 
//第二种状况:configurable设置为true,能够再次修改特性。
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:false,
    enumerable:false,
    configurable:true
});
 
//从新修改特性
Object.defineProperty(obj,"newKey",{
    value:"hello",
    writable:true,
    enumerable:true,
    configurable:true
});
console.log( obj.newKey ); //hello
复制代码
  1. 存取描述符号属性讲解

set是该属性值被设置时执行的回调函数(默认是undefined)

get是该属性值被得到时执行的回调函数(默认是undefined)

  1. Vue响应式和双向绑定的原理

Vue实例在初始化时,遍历在Observer(观察者)中全部属性经过Object.defineProperty()来实现他们的存取描述符(getter和setter),这样以来给任何对象的任意属性赋值都会触发该属性的setter,那么就能监听到数据变化。同时每一个属性都会设置一个Dep(消息订阅器),他内部维护了一个数组,用来记录全部Watcher(订阅者)。        而后Vue经过Compile(解析器)编译模板,将模板中的变量替换成对应的数据并渲染页面视图。此时Watcher会将本身添加到Dep中,到这里一个Vue实例的初始化完毕。        当属性值发生改变时,触发setter函数,setter会调用Dep.notify()通知每个订阅该属性的Watcher,Watcher会调用自身的update()函数对视图进行更新。这样一来双向绑定就实现了。

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>
复制代码
相关文章
相关标签/搜索