Skip to main content

响应式

Vue 最让人熟知的就是双向绑定,这基于它优秀的响应式设计。

getter/setter#

实现一个函数convert

  • 传入一个对象作为参数
  • Object.defineProperty实现对象 properties 的 getter 和 setter
核心代码
function convert(obj) {  Object.keys(obj).forEach((key) => {    let value = obj[key];    Object.defineProperty(obj, key, {      get: function () {        console.log(`getting key "${key}": ${value}`);        return value;      },      set: function (newValue) {        console.log(`setting key "${key}": ${newValue}`);        value = newValue;      },    });  });}

dependency tracking#

依赖追踪——订阅者/发布者模式

  • 创建一个包含depend,notify方法的类
  • 创建一个自动更新的高阶函数autorunupdatefunction 作为 input
核心代码
class Dep {  constructor() {    this.subs = new Set();  }
  depend() {    if (activeUpdate) {      this.subs.add(activeUpdate);    }  }
  notify() {    this.subs.forEach((sub) => sub());  }}
let activeUpdate;
// WTFfunction autorun(update) {  function wrapperUpdate() {    activeUpdate = wrapperUpdate;    update();    activeUpdate = null;  }  wrapperUpdate();}

mini observer#

合并convert(),autorun(),在此之前,rename convert() to observe()

  • observe()将对象的 properties 变成响应式,对每个 property 都分配一个Dep实例。
  • autorun()接受一个更新函数,并在更新函数订阅的 property 发生变化时重新运行它。
核心代码
function observe(obj) {  Object.keys(obj).forEach((key) => {    let value = obj[key];    let dep = new Dep();    Object.defineProperty(obj, key, {      get: function () {        dep.depend();        return value;      },      set: function (newValue) {        const isChanged = value !== newValue;        if (isChanged) {          value = newValue;          dep.notify();        }      },    });  });}
class Dep {  constructor() {    this.subs = new Set();  }
  depend() {    if (activeUpdate) {      this.subs.add(activeUpdate);    }  }
  notify() {    this.subs.forEach((sub) => sub());  }}
let activeUpdate;
function autorun(update) {  function wrapperUpdate() {    activeUpdate = wrapperUpdate;    update();    activeUpdate = null;  }  wrapperUpdate();}