基于es6 proxy的单向数据绑定

基于es6 proxy的单向数据绑定

admin
2019-01-29 / 0 评论 / 268 阅读 / 正在检测是否收录...

看了一些关于vue3.0的更新内容,主要是围绕性能方面的提升和对MVVM数据绑定的完全重写。3.0中不再使用 Object.defineProperty 而是原生ES6 Proxy,关于Proxy

Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

在vue2.x中,使用Object.defineProperty实现数据劫持。一般的做法如下:

let obj = {};
// 遍历data的所有属性
let dataKeys = Object.keys(data);
dataKeys.map(key => {
// 为data的所有属性添加set方法
   Object.defineProperty(data, key, {
      set: function(newVal) {
         // 修改v-text属性对应的data中的key的值
         document.querySelector(el + " *[v-text=" + key + "]").textContent = newVal;
      }
   });
});
      // 将处理好的data赋值给要返回的对象
obj.data = data;
return obj;

上面的代码中可以看出,主要有两个问题:

  1. 要为对象的每一个属性添加数据劫持,一般结合Object.keys()遍历对象属性实现。如果对象的层级结构不是简单的层级结构,只能一直遍历处理。
  2. 不能监听数组的变化,数组的push, pop, shift, unshift, splice, sort, reverse等方法不会触发set的侦听。我们在使用vue修改数组时能触发view的更新是因为vue内部做了变相的处理。

针对Vue 3.0的这个更新,做了一个简单的单向数据绑定的例子,说明3.0中使用Proxy实现数据绑定的基本原理(只是简单的单向绑定,数据的更改会反映到视图上)

<div id="app">
    <h1 v-text="title"></h1>
    <p>当前时间:<span v-text="time"></span></p>
</div>
function ViewBind({ el = 'body', data = {}} = {}) {
  // 要返回的对象实例
  let obj = {};
  const proxy = new Proxy(data, {
    get(obj, property) {
      return obj[property]
    },
    set(obj, property, newValue) {
      obj[property] = newValue;
      const bindEle = document.querySelector(el + " *[v-text=" + property + "]");
      if (bindEle) {
        bindEle.textContent = newValue;
      }
    }
  });
  obj.data = proxy;
  return obj;
};
const app = new ViewBind({
  el: '#app',
  data: {
    count: 0,
    title: '这是标题',
    time: +new Date()
  }
});
setInterval(() => {
  // 定时修改页面上<span v-text="time">元素中的内容
  app.data.time = +new Date();
  app.data.count = app.data.count + 1;
  app.data.title = '这是标题' + app.data.count;
}, 1000)

上面的代码中通过ViewBind实例化了一个对象,定时修改对象的属性,视图上通过v-text绑定的内容就会自动更新,效果如下
proxy-mvvm.gif

0

评论 (0)

取消