daily-interview / fe-interview

:smiley: 每日一道经典前端面试题,一起共同成长。
https://blog.csdn.net/u010494753
MIT License
172 stars 22 forks source link

Proxy如何实现数据劫持、双向绑定? #44

Open artdong opened 4 years ago

artdong commented 4 years ago

Proxy如何实现数据劫持、双向绑定?

artdong commented 4 years ago

proxy

Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。

语法

let p = new Proxy(target, handler);

参数

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

handler 一个对象,其属性是当执行一个操作时定义代理的行为的函数。

通过proxy,验证向一个对象的传值

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }

    // The default behavior to store the value
    obj[prop] = value;
  }
};

let person = new Proxy({}, validator);

person.age = 100;

console.log(person.age); 
// 100

person.age = 'young'; 
// 抛出异常: Uncaught TypeError: The age is not an integer

person.age = 300; 
// 抛出异常: Uncaught RangeError: The age seems invalid

proxy实现简单的双向绑定

html

<main>
    <p>请输入:</p>
    <input type="text" id="input">
    <p id="p"></p>
  </main>

js

const input = document.getElementById('input');
const p = document.getElementById('p');
const obj = {};

const newObj = new Proxy(obj, {
  get: function(target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function(target, key, value, receiver) {
    console.log(target, key, value, receiver);
    if (key === 'text') {
      input.value = value;
      p.innerHTML = value;
    }
    return Reflect.set(target, key, value, receiver);
  },
});

input.addEventListener('keyup', function(e) {
  newObj.text = e.target.value;
});