React簡單模擬語法(一)

React系列

React簡單模擬語法(一)
Jsx, 合成事件與Refs(二)
virtualdom diff算法實現分析(三)
從Mixin到HOC再到HOOKS(四)
createElement, ReactElement與Component部分源碼解析(五)

前言

我們先不講什么語法原理,先根據API效果強行模擬語法使用,實現一個簡易版的React.

render

第一步我們先用類創建一個元素返回,并且綁定點擊事件,代碼如下,可以正常看到一個按鈕出現了.

class AddButton {
  createDOM(domString) {
    const div = document.createElement("div");
    div.innerHTML = domString;
    return div;
  }

  render() {
    this.dom = this.createDOM(``);
    this.dom.addEventListener("click", () => console.log("click"), false);
    return this.dom;
  }
}

document.body.appendChild(new AddButton().render());

state && setState

實現類狀態和修改狀態方法

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(``);
    this.dom.addEventListener("click", () => this.handleAdd(), false);
    console.log(this.dom);
    return this.dom;
  }
}

document.body.appendChild(new AddButton().render());

渲染之后看到this dom輸出已經發現改變了,但是視圖并沒有渲染,那是因為這是結尾一次性插入,下面就渲染視圖這塊往下走

重新渲染

我們現在把插入數據的操作內置到class里面,新增一個方法插入新元素移除舊元素.

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(``);
    this.dom.addEventListener("click", () => this.handleAdd(), false);
    return this.dom;
  }
}

document.body.appendChild(new AddButton().render());

現在效果雖然實現,但是還是得開頭手動把元素插入視圖

抽取公用類

我們先將一些共有方法提取到一個單獨類

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 ``;
  }
}

還有一個問題是點擊事件暫時還是耦合進Component里面,先略過不提.

ReactDom.render

大家都知道React會提供這么一個方法將組件插入一個指定元素,我們直接模擬

const ReactDom = {
  render(component, wrapper) {
    wrapper.appendChild(component._render(wrapper));
  }
};

ReactDom.render(new AddButton(), document.getElementById("root"));

Props

還有一個重要的傳輸數據實現如下

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 ``
  }
}

ReactDom.render(new AddButton({a:1}), document.getElementById("root"))

至此,拋開實際思路不說,我們已經簡單模擬出來React的一般語法實現了.

聲明:所有內容來自互聯網搜索結果,不保證100%準確性,僅供參考。如若本站內容侵犯了原著者的合法權益,可聯系我們進行處理。
發表評論
更多 網友評論0 條評論)
暫無評論

返回頂部

主站蜘蛛池模板: 天堂mv在线免费看| 国产人妖在线播放| 欲乱美女诗涵番外5| ts人妖另类在线| 国产91刮伦脏话对白| 无套内射无矿码免费看黄| 香港特级a毛片免费观看| 久久精品久久久久观看99水蜜桃| 国产精品亚韩精品无码a在线| 欧美日韩你懂的| 69sex久久精品国产麻豆| 亚洲最大成人网色| 国产精品公开免费视频| 日韩精品中文字幕无码专区 | 富女玩鸭子一级毛片| 绝顶高潮videos| avtt天堂网久久精品| 亚洲视频综合网| 国产精品成人久久久久久久| 最近在线观看视频2019| 蜜柚视频网在线观看免费版| 中文字幕一区二区三区免费视频 | av一本久道久久综合久久鬼色| 亚洲综合图片小说区热久久| 国产精品亚洲精品日韩电影| 日韩精品久久无码人妻中文字幕| 美女扒开尿口让男人捅| 91视频最新地址| 久久天天躁狠狠躁夜夜| 免费看的一级毛片| 国产精品天干天干| 无翼日本全彩漫画大全全彩| 狼友av永久网站免费观看| 67194成是人免费无码| 久久久久久久女国产乱让韩| 免费A级毛片无码无遮挡| 国产成人免费午夜在线观看| 性做久久久久免费看| 极品美女一级毛片免费| 精品一区精品二区制服| 黑人xxxx日本|