js proxy代理,实现数据双向绑定

代理(拦截器)是对象的访问控制,setter/getter 是对单个对象属性的控制,而代理是对整个对象的控制。

  • 读写属性时代码更简洁
  • 对象的多个属性控制统一交给代理完成
  • 严格模式下 set 必须返回布尔值

语法

const p = new Proxy(target, handler)

参数

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

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

基本用法

// "use strict"
let zs = {
    name: "张三"
}
let proxy = new Proxy(zs, { 
    get(obj, property) {
        return obj[property]
    },
    set(obj, property, value) {
        obj[property] = value;
        // return true 严格模式下,要返回一个布尔值
    }
})
console.log(proxy)  // Proxy {name: "张三"}
console.log(proxy.name)  // 张三
proxy.name = "李四";
console.log(proxy.name)  // 李四

代理函数

如果代理以函数方式执行时,会执行代理中定义 apply 方法。

apply 参数:函数,上下文对象,参数

function factorial(num) {
    return num === 1 ? 1 : num * factorial(num - 1)
}
let proxy = new Proxy(factorial, {
    apply(func, that, args) {
        console.log("我来啦")
        console.log(func)
        console.log(that)
        console.log(args)
    }
})
proxy()
proxy-1.png

输出的参数是数组

尝试改变 proxy 的 this 指向,并传递参数

proxy.call(this, 5)
proxy-2.png

实现阶乘

apply(func, that, args) {
    let jc = func(args[0]);
    /* 也可以这样
    let jc = func.apply(null, args); */
    console.log(jc) // 120
}

代理数组

const lessons = [
    {
        title: "媒体查询响应式布局",
        category: "css"
    },
    {
        title: "FLEX 弹性盒模型",
        category: "css"
    },
    {
        title: "MYSQL多表查询随意操作",
        category: "mysql"
    }
];
let proxy= new Proxy(lessons, {
    get(array, index) {
        console.log(array);
        console.log(index);
    }
})
proxy[0]
proxy-3.png

截取字符

let proxy = new Proxy(lessons, {
    get(array, index) {
        let { title } = array[index];
        array[index].title = title.length > 6 ? 
            title.substring(0, 6) + '.'.repeat(3) : title
        return array[index]
    }
})
console.log(proxy[2])
proxy-4.png

类似 v-model 实现数据双向绑定

v-model.gif



我也将要发生改变

function View() {
    let proxy = new Proxy({}, {
        get(obj, property) {
            return obj[property]
        },
        set(obj, property, value) {
            console.log("我来啦");
            console.log(property, value) // 二、输出 title 和 输入框的值
        }
    })
    this.init = function() {
        const els = document.querySelectorAll("[v-model]");
        els.forEach(item => {
            item.addEventListener("keyup", function() {
                proxy[this.getAttribute("v-model")] = this.value;  // 一、这里触发后会走 setter
            })
        })
    }
}
let view = new View();
view.init();

页面渲染

set(obj, property, value) {
    document.querySelectorAll(`[v-model="${property}"]`)
        .forEach(item => {
        item.value = value
    })
    document.querySelectorAll(`[v-bind="${property}"]`)
        .forEach(item => {
        item.innerHTML = value
    })
}

你可能感兴趣的:(js proxy代理,实现数据双向绑定)