美文网首页
利用Proxy实现简单的数据双向绑定

利用Proxy实现简单的数据双向绑定

作者: 小宇cool | 来源:发表于2020-06-28 09:25 被阅读0次
1. 1什么是Proxy?

Proxy直译过来就是代理的意思, Proxy对象用来定义基本操作的自定义行为(如属性查找,枚举,赋值,函数调用等).它可以帮我们完成许多事情.例如对对象数据的处理.构造函数的数据验证,说白了就是我们访问对象前添加了一层拦截.我们可以对其进行许多操作.而这些由你自己定义.

基本语法

let proxy = new Proxy(target,handler)

参数

target 要使用Proxy包装的目标对象,(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)

handler一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

下面是一个简单的实例

const obj = {name:"zs",age:434};
let proxy = new Proxy(obj,{
    //obj 为目标对象, attr 为对象的属性
    get(obj,attr){ //当我们获取代理对象的属性值是会走这个方法
        return obj[attr]
    },
    // obj为目标对象, attr为属性名, value为属性值
    set(obj,attr,value){//当我们设置代理对象的属性值是会走这个方法
        if(property === "age"){
            if(value >= 100 ) throw new Error("the data format is not correct")
            obj[property] = value
        }
        //表示成功
         return true
    }
})
proxy.age = 120,
console.log(proxy.name )

上面的代码中当我们通过代理对象设置name属性值时, 会调用set方法,此时我们判断

设置的属性是不是age, 如果是,则判断age的值是不是大于100,如果是则抛出一个错误,当我们设置的数字不符合格式时, 我们设置的属性值就不会生效.只有当age设置的数字符合要求时,才能设置上属性值.

相当于我们对象添加了一层拦截,只有当我们的数据符合我们拦截是所设置的要求时,我们才能得到自己想要的结果.

代理对象相当于一层中介,我们不直接操作对象数据,而是通过这个代理对象操作数据.

1 2. 简单的数据双向绑定

了解了基本原理后,我们就可以通过代理来实现一个简单数据双向绑定

下面是代码的部分

假设我们HTML有如下结构代码

<input type="text" v-model="content">
<input type="text" v-model="title">
<input type="text" v-model="title">
<h3 v-bind="title"></h3>

下面是js代码部分

function view(option) {// 接受一个参数对象
        this.initData = option.data;// 给实例对象添加初始化数据对象
        let proxy = new Proxy(this.initData, {
            set(obj, prototype, value) {// 当我们设置proxy的属性名时会走这个方法
                //更新视图
                document
                    .querySelectorAll(`[v-model="${prototype}"]`)// 获取相应的表单元素
                    .forEach((item) => {
                        item.value = value
                    })
                document.querySelectorAll(`[v-bind="${prototype}"]`)// 获取相应的普通的标签元素
                    .forEach((item) => {
                    item.innerHTML = value
                })
                return true
            },
            get(obj, prototype) { }
        })
        this.data = proxy;
        // 初始化绑定监听事件
        this.init = function () {
            let els = document.querySelectorAll("[v-model");
            els.forEach((item) => {
                item.addEventListener("input", function () {
                    // 此时通过getAttribute获取的是我们绑定在DOM元素上的属性值, 也就是相对应数据的属性名
                    proxy[this.getAttribute("v-model")] = this.value
                })
            })
        }
        // 初始化渲染
        this.renderInit = function () {
            for (let key in this.initData) {//对数据进行遍历, 获取key获取相应的DOM元素并更新视图.
                let renerList = document.querySelectorAll(`[v-model="${key}"]`);
                let renerInputList = document.querySelectorAll(`[v-bind="${key}"]`);
                renerInputList.forEach((item) => item.innerHTML = this.initData[key])
                renerList.forEach((item) => item.value = this.initData[key])
            }
        }
      this.renderInit()// 渲染视图
    }
    let data = {
        title: "张三434",
        content: "43",
    }
    let vm = new view({
        data,//传递的数据对象, ES6简写方式, 当属性名和属性值相同时,可以简写这种形式.
    })
    vm.init()
    //我们通过实例对象上的data属性改变title属性值, 此时也会被代理对象所拦截并响应.
    vm.data.title = "$34"

上面代码我们通过给构造函数传递的参数option的data属性, 给实例化对象身上添加了一个initData属性, 然后对实例对象的initData对象添加了一层代理. 然后给实例对象上添加一个data属性指向这个代理对象, 当我们通过实例的data属性改变相应的数据时,此时代理对象也会拦截到, 并更新相应的视图.

我们通过给实例对象添加了一个init初始化方法, 当我们调用init方法时,会获取页面上使用属性使用了v-model的元素,并为他们添加了input事件, 当这个事件触发的时候,我们通过获取当前元素v-model绑定的数据名. 和value值.来相应的设置proxy代理对象的键值对, 此时我们代理对象的set方法会调用, 通过传递过来的属性名, 获取相应的需要动态显示的元素,然后给相应的DOM元素更新视图.

相关文章

网友评论

      本文标题:利用Proxy实现简单的数据双向绑定

      本文链接:https://www.haomeiwen.com/subject/qglifktx.html