《Evan You 尤雨溪讲解 vue 源码及高级特性》笔记

前言

原视频链接请点击,视频中带你以 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();
            }
        });
    });
}

你可能感兴趣的:(javascript,vue.js,html5)