初探vue响应式

vue2响应式的精髓是defineProperty属性。

基础知识

获取属性标签:getOwnPropertyDescriptor

var obj={a:1,b:2};
console.log(Object.getOwnPropertyDescriptor(obj,'a'));
//输出:{value: 1, writable: true, enumerable: true, configurable: true}

设置属性标签:defineProperty

var obj={a:1,b:2};
Object.defineProperty(obj,'b',{
    writable:false,//不可被重写
    enumerable:false,//不可被for..in..循环遍历
    configurable:false //不可被delete
});
console.log(obj.b,obj.a);
//输出:2 1
obj.b=2222;obj.a=1111;
console.log(obj.b,obj.a);
//输出:2 1111
for(var item in obj){
    console.log(item);
}
//输出:a
console.log(delete obj.a); //输出:true
console.log(obj); //输出:{b: 2}
console.log(delete obj.b);//输出:false
console.log(obj);//输出:{b: 2}

简易设置:seal和freeze

var obj1={a:1,b:2};
Object.freeze(obj1);
console.log(Object.getOwnPropertyDescriptor(obj1,'a'));
//输出:{value: 1, writable: false, enumerable: true, configurable: false}
var obj2={a:1,b:2};
Object.seal(obj2);
console.log(Object.getOwnPropertyDescriptor(obj2,'a'));
//输出:{value: 1, writable: true, enumerable: true, configurable: false}

get和set

var obj={a:1,b:2};
Object.defineProperty(obj,'b',{
    set:function(newVal){
        console.log('this newVal is'+newVal);
    },
    get:function(){
        console.log('you get b');
    }
});
console.log(obj);
//输出:{a: 1}
console.log(obj.b);
//输出:you get b
//输出:undefined //由此看出get()方法必须return一个值


设置obj.b的值

var obj={a:1,b:2};
var _value=obj.b;
Object.defineProperty(obj,'b',{
    set:function(newVal){
        console.log('this newVal is '+newVal);
        _value=newVal;
    },
    get:function(){
        console.log('you get b');
        return _value;
    }
});
obj.b=22222;
console.log(obj.b);
//输出:this newVal is 22222
//输出:you get b
//输出:22222

​

vue2的简单实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div id="app"></div>
<script type="text/javascript">
    function Vue(){
    this.$data={a:1};
    this.el=document.getElementById('app');
    this.virtualdom='';
    this.observe(this.$data);
    this.render();
}
Vue.prototype.observe=function (obj) {
    var self=this;
    var value;
    for(var key in obj){
        value=obj[key];
        if(typeof value==='object'){
            this.observe(value);
        }else{
            Object.defineProperty(this.$data,key,{
                get:function () {
                    //此时vue进行依赖收集
                    return value;
                },
                set:function (newVal) {
                    // 此时vue触发收集的依赖更新
                    value=newVal;
                    self.render();
                }
            });
        }
    }
};
Vue.prototype.render=function () {
    //此时vue读取视图模板,生成AST语法树
    this.virtualdom='i am '+this.$data.a;
    this.el.innerHTML=this.virtualdom;
};
var vm=new Vue();
setTimeout(function () {
    console.log('change');
    console.log(vm.$data);
    vm.$data.a=444444;
},2000);
</script>
</body>
</html>

vue 3的原理

与vue2的区别,在数据监视方面,改用Proxy。

Proxy对象用于定义基本操作的自定义行为,和defineProperty类似,功能几乎一样,用法上有不同。

defineProperty:对原有对象进行劫持,本身是定义属性标签,使用其做数据双项绑定改变了原数据的属性标签,污染了原对象

Proxy:代理原对象,生成一个新的对象;不用监听某一具体属性,省去了vue2的for..in循环;省去了vue2的_value变量

var obj2={a:11,b:22};
var obj3=new Proxy(obj2,{
    get:function (target,key,receiver) {
        console.log(target,key,receiver);
        //输出:{a: 11, b: 22} "a" Proxy {a: 11, b: 22}
        //输出:{a: 11, b: 22} "b" Proxy {a: 11, b: 22}
        return Reflect.get(target,key);
    },
    set:function (target,key,value,receiver) {//value:新值
        console.log(target,key,value,receiver);
        //输出:{a: 3333, b: 22} "a" Proxy {a: 3333, b: 22}
        //输出:{a: 3333, b: 22} "b" Proxy {a: 3333, b: 22}
        return Reflect.set(target,key,value);
    }
});
console.log(obj3.a);//输出:11
obj3.a=3333;
console.log(obj3.a);//输出:3333
console.log(obj3.b);//输出:22

vue3的数据绑定简易实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>
<div id="app"></div>
<!--<script type="text/javascript" src="js/test.js"></script>-->
<script type="text/javascript">
    function Vue(){
        this.$data={a:1};
        this.el=document.getElementById('app');
        this.virtualdom='';
        this.observe(this.$data);
        this.render();
    }
    Vue.prototype.observe=function () {
        var self=this;
        this.$data=new Proxy(this.$data,{
            get:function(target,key){
                return target[key];
            },
            set:function (target,key,newVal) {
                target[key]=newVal;
                self.render();
            }
        });
    };
    Vue.prototype.render=function () {
        //此时vue读取视图模板,生成AST语法树
        this.virtualdom='i am '+this.$data.a;
        this.el.innerHTML=this.virtualdom;
    };
    var vm=new Vue();
    setTimeout(function () {
      console.log('change');
      console.log(vm.$data);
      vm.$data.a=444444;
    },2000);
</script>
</body>
</html>

virtual dom虚拟层,并不正式存在

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值