Vue深入-18【Vue2与Vue3核心之『响应式原理』】

(1).defineproperties

class Compute{
    plus(a,b){
        return a+b;
    }
    minus(a,b){
        return a-b;
    }
    mul(a,b){
        return a*b;
    }
    div(a,b){
        return a/b;
    }
}
class Calculator extends Compute{
    constructor(doc){
        super();
        const oCal = doc.getElementsByClassName('J_calculator')[0];
        this.fInput = oCal.getElementsByTagName('input')[0];
        this.sInput = oCal.getElementsByTagName('input')[1];
        this.oBtnGroup = oCal.getElementsByClassName('btn-group')[0];
        this.oBtnItems = this.oBtnGroup.getElementsByTagName('button');
        this.oResult = oCal.getElementsByClassName('result')[0];
        this.data = this.defineData();
        this.btnIdx = 0; 
    }
    init(){
        this.bindEvent();
    }
    bindEvent(){
        this.oBtnGroup.addEventListener('click',this.onFieldBtnClick.bind(this));
        this.fInput.addEventListener('input',this.onNumberInput.bind(this));
        this.sInput.addEventListener('input',this.onNumberInput.bind(this));
    }
    defineData(){
        let _obj = {},
            fNumber = 0,
            sNumber = 0,
            field = 'plus';
        const _self = this;
        Object.defineProperties(_obj,{
            fNumber:{
                get(){
                    return fNumber;
                },
                set(newValue){
                    fNumber = newValue;
                    _self.computeResult(fNumber,sNumber,field);
                }
            },
            sNumber:{
                get(){
                    return sNumber;
                },
                set(newValue){
                    sNumber = newValue;
                    _self.computeResult(fNumber,sNumber,field);
                }
            },
            field:{
                get(){
                    return field;
                },
                set(newValue){
                    field = newValue;
                    _self.computeResult(fNumber,sNumber,field);
                }
            }
        })   
        return _obj 
    }
    onFieldBtnClick(ev){
        const e = ev || window.event,
             tar = e.target || e.srcElement,
             tagName = tar.tagName.toLowerCase();
        tagName === 'button' && this.fieldUpdate(tar)     
    }
    fieldUpdate(target){
        this.oBtnItems[this.btnIdx].className = '';
        this.btnIdx = [].indexOf.call(this.oBtnItems,target);
        target.className += ' current';
        this.data.field = target.getAttribute('data-field');
    }
    onNumberInput(ev){
        const e = ev || window.event,
              tar = e.target || e.srcElement,
              className = tar.className,
              val = Number(tar.value.replace(/\s+/g,'')) || 0;
              switch(className){
                  case 'f-input':
                      this.data.fNumber = val;
                      break;
                  case 's-input':
                      this.data.sNumber = val;
                      break;    
              }
    }
    computeResult(fNumber,sNumber,field){
        this.oResult.innerText = this[field](fNumber,sNumber);
    }
}
new Calculator(document).init()

数据劫持-给对象进行扩展-属性进行设置

(2).proxy

并不是数据劫持,而是代理,是自定义对象属性的获取、赋值、枚举、函数调用等功能

1.使用形式

函数
let fn = function(){
    console.log('我是function');
}
fn.a = 123
let newFn = new Proxy(fn,{
    get(fn,prop){
        return fn[prop]+'proxy return'
    }

})
console.log(newFn.a);// 123proxy return

对象
let target = {
    a:1,
    b:2
}
let proxy = new Proxy(target,{
    get(target,prop){
        return 'proxy'+target[prop];
    },
    set(target,prop,value){
        target[prop] = value;
        console.log(target[prop]);
    }
})
console.log(proxy.a);//proxy 1
console.log(target.a); 1
proxy.b = 3
console.log(target.b);3 更改代理也会影响原数据

2.操作对象的14种方法

var obj = {a:1,b:2}
1.获取原型[[GetPrototypeOf]]
var proto = Object.getPrototypeOf(obj)
2.设置原型[[SetPrototypeOf]]
Object.setPrototypeOf(obj,{c:3,d:4})
3.获取对象的可扩展性[[IsExtensible]]
let ext = Object.isExtensible(obj)
console.log(ext)
Object.freeze(obj);true
let ext2 = Object.isExtensible(obj)
console.log(ext2);false

封闭对象=seal 不可增加 不可删除 可修改 可读
冻结对象=freeze 不可增加 不可删除 不可修改 可读

4.获取自有属性[[GetOwnProperty]]
Object.setPrototypeOf(obj,{c:3,d:4});
console.log(Object.getOwnPropertyNames(obj))a b

5.禁止扩展对象
Object.preventExtensions(obj);
obj.c = 3;
console.log(obj)//1 2 没有3 是可删除的

6.拦截对象操作[[DefineOwnProperty]]
Object.defineProperty()
7.判断是否是自身属性[[HasProperty]]
console.log(obj.hasOwnProperty('a'));
8.[[GET]]
console.log(obj.a)
9.[[SET]]
obj.a=3
obj['a']=3
10.[[Delete]]
delete obj.a
console.log(obj)
11.[[Enumerate]]
for (var k in obj){
    console.log(obj[k])
}
12.获取键集合[[OwnPropertyKeys]]
console.log(Object.keys(obj));
13.函数调用执行
function test(){} test();
obj.test = function(){} obj.test()
14.实例化
function Test(){} new Test();

(3).重写

function MyProxy(target,handler){
    let _target = deepClone(target);

    function deepClone(org,tar){
        var tar = tar || {},
            toStr = Object.prototype.toString,
            arrType = '[object Array]';
        for(var key in org){
            if(org.hasOwnProperty(key)){
                if(typeof(org[key]) === 'object' && org[key] !== null){
                    tar[key] = toStr.call(org[key]) === arrType ? [] : {}
                    deepClone(org[key],tar[key]);
                }else{
                    tar[key] = org[key]
                }
            }
        }  
        return tar;  
    }
    Object.keys(_target).forEach((key)=>{
        Object.defineProperty(_target,key,{
            get(){
                return handler.get && handler.get(target,key)
            },
            set(newVal){
                handler.set && handler.set(target,key,newVal)
            }
        })
    })
    return _target;
}

(4).proxy还可以写其他方法

let target = {
    a:1,
    b:2
}
let proxy = new Proxy(target,{
    get(target,prop){
        return 'proxy'+target[prop];
    },
    set(target,prop,value){
        target[prop] = value;
        // console.log(target[prop]);
    },
    has(target,prop){
        console.log(1111)
        console.log(target[prop])
    },
    deleteProperty(target,prop){
        delete target[prop];
        console.log(1)
    }
})
delete proxy.b;
console.log('a' in proxy) 打印1 111 1 false

(5).reflect

14中方法除去枚举都放到了reflect上,好处是可以返回状态

let target = {
    a:1,
    b:2
}
let proxy = new Proxy(target,{
    get(target,prop){
        return Reflect.get(target,prop)
    },
    set(target,prop,value){
       const isOk = Reflect.set(target,prop,value);
       if(isOk){
           console.log(target[prop]);
       }
       
    }
})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值