前言

原视频链接请点击,视频中带你以 vue 开发者的视角来看其中的设计模式及高级个性,且蕴含许多底层实现,强烈推荐。

响应式原理

React

此处特指在前端中如何通过改变state以更新view

/*     React */let update;const onStateChange = _update => {    update = _update;}const setState = newState => {    state = newState;    update();}onStateChange(() => {    view = render(state);});setState({a: 5});

在 React 中咱们规定只能通过setState函数来扭转state,如此一来便能够在每一次state扭转后调用render来更新view

Vue

在 Vue 中能够间接通过扭转 state 的值来扭转 view,而不用调用 setState 函数。这是通过 Object.defineProperty 劫持对象的settergetter 来实现的。

/*    Vue    realState 为真正惟一的状态, 原来的 state 则是它的一个代理*/let realState = Object.create(null);realState = Object.assign(realState,state);Object.keys(state).forEach(key => {    Object.defineProperty(state,key,{        get(){            return realState[key]        },        set(newValue){            realState[key] = newValue;            vm = render(realState);        }    });});

依赖

这里先给出课上的一个题目,稍后再探讨在 Vue 的理论使用。

/*    实现一个 Dep 类,其中蕴含两个办法 depend() 和 notify()。    另外再实现一个函数 autorun(),承受一个函数 func, 会主动运行func。    如果在 func 中调用 depend() 办法则会订阅该函数, 调用 notify() 则会运行所有订阅的函数。*/let activeUpdate;function autorun(update){    function updateWrapper(){  // 设置一个全局变量,这样能够在 depend() 中晓得以后是否正在执行 update 函数。        activeUpdate = updateWrapper;        update();        activeUpdate = null;    }    updateWrapper();}window.Dep = class Dep{    constructor(){        this.stacks = new Set();    }        depend(){        if(activeUpdate){            this.stacks.add(activeUpdate);        }    }        notify(){        this.stacks.forEach(func => func());    }}

察看发布者模式

这一步咱们想把后面两步联合起来,咱们心愿实现一个函数 observe ,传入一个对象,劫持它的 gettersetter。这样每当咱们调用 getter 时便收集它所有的依赖,而后在 setter 时调用 notify 触发所有的依赖。

function observe(state){    Object.keys(state).forEach(key => {        let value = state[key];        const dep = new Dep();        Object.defineProperty(state,key,{            get(){                dep.depend();                return value;            },            set(newValue){                value = newValue;                dep.notify();            }        });    });}