前言
原视频链接请点击,视频中带你以 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
劫持对象的setter
和 getter
来实现的。
/* 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
,传入一个对象,劫持它的 getter
和 setter
。这样每当咱们调用 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(); } }); });}