React Simple Analog Grammar

Preface

Let's not talk about any grammatical principles. First, we simulate the grammatical usage forcibly according to the API effect, and realize a simple version of React.

render

The first step is to create an element to return with the class and bind the click event. The code is as follows. You can see a button appears normally.

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());

state && setState

Implementing Class State and Modifying State Method

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());

After rendering, you can see that the DOM output has been changed, but the view has not been rendered, because this is a one-time insertion of the end, so let's go down to render the view.

Rendering

Now we build the operation of inserting data into the class and add a new method to insert new elements to remove the old ones.

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());

Now the effect is achieved, but you still have to start by manually inserting elements into the view

Extracting public classes

Let's first extract some common methods into a single class

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

Then the component simply inherits the Component and processes its own logic.

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

Another question is whether the click event is temporarily coupled into Component, not to mention it.

ReactDom.render

Everyone knows that React provides a way to insert components into a specified element, which we simulate directly.

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

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

Props

Another important implementation of data transmission is as follows

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"))

So far, we have simply simulated the general grammar implementation of React, regardless of the actual thinking.

Keywords: Javascript React

Added by yazz on Wed, 07 Aug 2019 06:18:44 +0300