Object.defineProperty()和new Proxy()的区别、VUE双向数据绑定的原理和仿写

Object.defineProperty()

给对象新增属性,或者设置对象的原有属性
Object.defineProperty(‘给那个对象新增属性’,‘新增的属性名叫啥’,{给新增的属性设置线管的配置项key:value})
value:配置项:给属性指定值
writable配置项:设置该属性是否可以修改 true/false
getter方法配置项:当读取属性值的时候该方法自动调用
getter方法的返回值就是你给这个属性设置的值
setter方法配置项:当属性值被修改的时候该方法自动调用
setter方法有一个参数,这个参数是可以接收传过来的值
注意:当配置项中有getter和setter的时候不能出现value和writable配置项

new Proxy()

两个参数 第一个 代理的哪一个对象,第二个一个对象包含函数就是给对象添加配置项
包含了数组的方法更加全面

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>

<body>
    <div id="container">div>
body>
<script>
 /* Object.defineProperty()
        给对象新增属性,或者设置对象的原有属性
        Object.defineProperty('给那个对象新增属性','新增的属性名叫啥',{给新增的属性设置线管的配置项key:value})
        value:配置项:给属性指定值
        writable配置项:设置该属性是否可以修改 true/false
        enumerable配置项:该属性是否可以遍历 true/false
        configurable配置项:该属性是否可以删除 true/false
        getter方法配置项:当读取属性值的时候该方法自动调用
             getter方法的返回值就是你给这个属性设置的值
        setter方法配置项:当属性值被修改的时候该方法自动调用
             setter方法有一个参数,这个参数是可以接收传过来的值
        注意:当配置项中有getter和setter的时候不能出现value和writable配置项
    */
    const phone = {};
    let temp
    Object.defineProperty(phone, "color", {
        // value:'太空灰',
        // writable:true,
        //当读取对象中的属性值会调用 phone.color
        get() {
            console.log('getter方法调用了');
            return temp
        },
        //当修改对象中的属性值时会调用 phone.color='red'
        set(val) {
            console.log('setter方法执行了', val);
            temp = val
        }
    })
    //编写一个对象,把对象的属性显示到页面上,再进行对对象的属性修改时页面跟随变化
    const obj = {
        name: '一号',
        age: 18
    }
    const container = document.getElementById('container');
    // console.log(container);
    // textContent和innerHTML类似
    //我们现在对obj.name修改发现修改后页面并不变化需要从新渲染
    //obj.name = '二号'; //虽然数据变了,但是页面没有变化需要从新渲染
    //container.textContent=obj.name; //从新渲染才可以
    //第二种 使用代理Proxy
    //我们使用代理就可以解决这个问题
    //两个参数 第一个 代理的哪一个对象,第二个一个对象包含函数就是给对象添加配置项
    const p1 = new Proxy(obj, {
        get(target, property, receiver) {
            // 数据对象 属性名   Proxy实例
            //获取的时候
            //obj[property] 就是获取对象中的所有属性
            return obj[property]
        },
        set(target, property, value, receiver) {
            // 数据对象 属性名  修改的值 Proxy实例
            //修改的时候
            obj[property] = value
            container.textContent = obj.name;
        }
    })
    console.log(p1.name);
    p1.name = '三号'


 // 双向数据绑定
    const vm = {}
    const target = {
        name: '张三'
    }
    Object.defineProperty(vm, "name", {
        getter() {
            return target.name
        },
        setter(val) {
            target.name = val
        }
        //这时候你去修改vm.name会影响target.name 你修改target.name会影响vm.name
    })
    // 对比下面的代码
    // const target={
    //     name:'张三'
    // }
    // const vm=new Vue({
    //     el:'#app',
    //     data:target  data:{name}===target.name
    // })
    //仿写vue中的双向数据绑定
    class Vue {
        // options就是一个js对象,对象内有一个data配置项
        constructor(options) {
            //获取对象中属性名为data的
            Object.keys(options.data).forEach((propertyName, index) => {
                console.log(propertyName, index);
                //如果代理的元素第一个元素是$或_就不代理
                let firstChar = propertyName.charAt(0)
                if (firstChar != '_' && firstChar != '$') {
                    //这里用propertyName是因我们可能是给多个元素进行代理
                    Object.defineProperty(this, propertyName, {
                        get() {
                            //读取一个对象中的两种方式 obj.name || obj['name']
                            return options.data[propertyName]
                        },
                        set(val) {
                            options.data[propertyName] = val
                        }
                    })
                }
            })
            //对methods中所有的函数进行代理
            Object.keys(options.methods).forEach((methodsName,index)=>{
                this[methodsName]=options.methods[methodsName]
            })
        }
    }
script>

html>

你可能感兴趣的:(vue.js,javascript,前端)