import { extend, isFn, options, clearArray, noop } from "./util"; import { CurrentOwner } from "./createElement"; /** *組件的基類 * * @param {any} props * @param {any} context */ var mountOrder = 1; export function Component(props, context) { //防止用戶在構造器生成JSX CurrentOwner.cur = this; this.__mountOrder = mountOrder++; this.context = context; this.props = props; this.refs = {}; this.state = null; this.__pendingCallbacks = []; this.__pendingStates = []; this.__current = noop; /* * this.__hydrating = true 表示組件正在根據虛擬DOM合成真實DOM * this.__renderInNextCycle = true 表示組件須要在下一週期從新渲染 * this.__forceUpdate = true 表示會無視shouldComponentUpdate的結果 */ } Component.prototype = { constructor: Component,//必須重寫constructor,防止別人在子類中使用Object.getPrototypeOf時找不到正確的基類 replaceState() { console.warn("此方法末實現"); // eslint-disable-line }, setState(state, cb) { debounceSetState(this, state, cb); }, isMounted() { return !!this.__dom; }, forceUpdate(cb) { debounceSetState(this, true, cb); }, __mergeStates: function (props, context) { var n = this.__pendingStates.length; if (n === 0) { return this.state; } var states = clearArray(this.__pendingStates); var nextState = extend({}, this.state); for (var i = 0; i < n; i++) { var partial = states[i]; extend(nextState, isFn(partial) ? partial.call(this, nextState, props, context) : partial); } return nextState; }, render() { } }; function debounceSetState(a, b, c) { if (a.__didUpdate) {//若是用戶在componentDidUpdate中使用setState,要防止其卡死 setTimeout(function () { a.__didUpdate = false; setStateImpl.call(a, b, c); }, 300); return; } setStateImpl.call(a, b, c); } function setStateImpl(state, cb) { if (isFn(cb)) { this .__pendingCallbacks .push(cb); } let hasDOM = this.__dom; if (state === true) {//forceUpdate this.__forceUpdate = true; } else {//setState this .__pendingStates .push(state); } if (!hasDOM) { //組件掛載期 //componentWillUpdate中的setState/forceUpdate應該被忽略 if (this.__hydrating) { //在掛載過程當中,子組件在componentWillReceiveProps裏調用父組件的setState,延遲到下一週期更新 this.__renderInNextCycle = true; } } else { //組件更新期 if (this.__receiving) { //componentWillReceiveProps中的setState/forceUpdate應該被忽略 return; } this.__renderInNextCycle = true; if (options.async) { //在事件句柄中執行setState會進行合併 options.enqueueUpdate(this); return; } if (this.__hydrating) { // 在componentDidMount裏調用本身的setState,延遲到下一週期更新 // 在更新過程當中, 子組件在componentWillReceiveProps裏調用父組件的setState,延遲到下一週期更新 return; } // 不在生命週期鉤子內執行setState options.flushBatchedUpdates([this]); } }