React系列 --- 簡單模擬語法(一)
React系列 --- Jsx, 合成事件與Refs(二)
React系列 --- virtualdom diff算法實現分析(三)
React系列 --- 從Mixin到HOC再到HOOKS(四)
React系列 --- createElement, ReactElement與Component部分源碼解析(五)
React系列 --- 從使用React瞭解Css的各類使用方案(六)
React系列 --- 從零構建狀態管理及Redux源碼解析(七)
React系列 --- 擴展狀態管理功能及Redux源碼解析(八)算法
咱們先不講什麼語法原理,先根據API效果強行模擬語法使用,實現一個簡易版的React.segmentfault
第一步咱們先用類建立一個元素返回,而且綁定點擊事件,代碼以下,能夠正常看到一個按鈕出現了.app
class AddButton { createDOM(domString) { const div = document.createElement("div"); div.innerHTML = domString; return div; } render() { this.dom = this.createDOM(`<button>0</button>`); this.dom.addEventListener("click", () => console.log("click"), false); return this.dom; } } document.body.appendChild(new AddButton().render());
實現類狀態和修改狀態方法dom
class AddButton { constructor() { this.state = { num: 0 }; } createDOM(domString) { const div = document.createElement("div"); div.innerHTML = domString; return div; } setState(state) { this.state = state; this.dom = this.render(); } handleAdd() { const num = this.state.num + 1; this.setState({ num: num }); } render() { this.dom = this.createDOM(`<button id="btn">${this.state.num}</button>`); this.dom.addEventListener("click", () => this.handleAdd(), false); console.log(this.dom); return this.dom; } } document.body.appendChild(new AddButton().render());
渲染以後看到this dom
輸出已經發現改變了,可是視圖並無渲染,那是由於這是結尾一次性插入,下面就渲染視圖這塊往下走this
咱們如今把插入數據的操做內置到class裏面,新增一個方法插入新元素移除舊元素.code
class AddButton { constructor() { this.state = { num: 0 }; } createDOM(domString) { const div = document.createElement("div"); div.innerHTML = domString; return div; } changeDom() { const oDom = this.dom; this.dom = this.render(); document.body.insertBefore(this.dom, oDom); document.body.removeChild(oDom); } setState(state) { this.state = state; this.changeDom(); } handleAdd() { const num = this.state.num + 1; this.setState({ num: num }); } render() { this.dom = this.createDOM(`<button id="btn">${this.state.num}</button>`); this.dom.addEventListener("click", () => this.handleAdd(), false); return this.dom; } } document.body.appendChild(new AddButton().render());
如今效果雖然實現,可是仍是得開頭手動把元素插入視圖component
咱們先將一些共有方法提取到一個單獨類繼承
class Component { constructor() {} createDOM(domString) { const div = document.createElement("div"); div.innerHTML = domString; return div; } changeDom() { const oDom = this.dom; this.dom = this._render(); this.wrapper.insertBefore(this.dom, oDom); this.wrapper.removeChild(oDom); } setState(state) { this.state = state; this.changeDom(); } _render(wrapper) { if (wrapper) this.wrapper = wrapper; this.dom = this.createDOM(this.render()); this.dom.addEventListener("click", () => this.handleAdd(), false); return this.dom; } }
而後組件只須要直接繼承Component
而後處理本身邏輯便可事件
class AddButton extends Component { constructor() { super(); this.state = { num: 0 }; } handleAdd() { const num = this.state.num + 1; this.setState({ num: num }); } render() { return `<button id="btn">${this.state.num}</button>`; } }
還有一個問題是點擊事件暫時仍是耦合進Component
裏面,先略過不提.rem
你們都知道React會提供這麼一個方法將組件插入一個指定元素,咱們直接模擬
const ReactDom = { render(component, wrapper) { wrapper.appendChild(component._render(wrapper)); } }; ReactDom.render(new AddButton(), document.getElementById("root"));
還有一個重要的傳輸數據實現以下
const ReactDom = { render(component, wrapper) { wrapper.appendChild(component._render(wrapper)) } } class Component { constructor(props = {}) { this.props = props } createDOM(domString) { const div = document.createElement("div") div.innerHTML = domString return div } changeDom() { const oDom = this.dom this.dom = this._render() this.wrapper.insertBefore(this.dom, oDom) this.wrapper.removeChild(oDom) } setState(state) { this.state = state this.changeDom() } _render(wrapper) { if (wrapper) this.wrapper = wrapper this.dom = this.createDOM(this.render()) this.dom.addEventListener("click", () => this.handleAdd(), false) return this.dom } } class AddButton extends Component { constructor(props) { super(props) this.state = { num: 0 } } handleAdd() { const num = this.state.num + 1 this.setState({ num: num }) } render() { console.log(this.props) return `<button id="btn">${this.state.num}</button>` } } ReactDom.render(new AddButton({a:1}), document.getElementById("root"))
至此,拋開實際思路不說,咱們已經簡單模擬出來React的通常語法實現了.