Skip to content

LuoQaxa/myreact

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

myreact

实现一个简易版本的react,理清react的主干内容和重要知识点

一 jsx

jsx是一种语法糖,js能够写在html中。本质上是利用babel,转换为React.createElement()方法的调用。 这也是为什么每一个jsx文件中,虽然没有用到React也需要引入。

实现:

const element = (
  <div style={{ color: 'green', fontSize: '25px'}}>hello react jsx</div>
)

ReactDOM.render(
  element,
  document.getElementById('root')
)

难点:

  1. jsx语法糖原理:babel转换 -> React.createElement -> virtualDOM。需要自己实现React.createElement方法。
  2. ReactDOM.render: 由于html结构是一个嵌套结构,所以在渲染vdom的时候需要用到递归。在render方法里创建dom元素和为dom添加对应的属性,并将dom append到对应的父节点里
  3. 递归:

二 组件

组件有两种方式:纯函数组件和用class定义的组件

实现:

class A extends Component {

  render() {
    <div style={{ color: 'green', fontSize: '25px'}}>hello component</div>
  }
}

const B = () => {
  return (
    <div style={{ color: 'green', fontSize: '25px'}}>hello react jsx</div>
  )
}

ReactDOM.render(
  <A/>,
  document.getElementById('root')
)

难点:

  1. 组件形式<A/>经过babel的编译后 -> React.createElement(A, null) ,这样意味着vdomnodeName为一个函数,在render的时候需要判断vdom.nodeName如果为函数做相应的处理。

三 影响组件的两大属性:props 和 state

实现

class A extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 1
    }
  }

  click() {
    this.setState({
      count: ++this.state.count
    })
  }

  render() {
    return (
      <div>
        <button onClick={this.click.bind(this)}>Click Me!</button>
        <div>{this.props.name}:{this.state.count}</div>
      </div>
    )
  }
}

ReactDOM.render(
  <A name='luoqian'/>,
  document.getElementById('root')
)

难点:

  1. 所有组件都继承Component构造函数,这个函数的原型上添加setState方法,当调用时重新渲染更新后的vdom
  2. 组件的props是如何传入组件的:在render的时候将vdom.attribute传入new Vdom.nodeName(vdom.attribute),在组件的constructor中将props传入,调用super(props)调用Component构造函数,将props添加到实例属性上。
  3. ReactDOM.render在每次热更新的时候需要清空当前渲染的dom。

四 整理项目结构

将方法拆分到单独的文件中

难点:

  1. Component.prototype.setState的方法中传入的是新的state,将新的state和和旧的state组合后,调用componentrender方法获得该组件的vdom。再调用ReactDOM.render方法重新渲染页面。

五 生命周期

实现:

class A extends Component {
  componentWillReceiveProps(props) {
    console.log('componentWillReceiveProps')
  }

  render() {
    return (
      <div>{this.props.count}</div>
    )
  }
}

class B extends Component {
  constructor(props) {
    super(props)
    this.state = {
      count: 1
    }
  }

  componentWillMount() {
    console.log('componentWillMount')
  }

  componentDidMount() {
    console.log('componentDidMount')
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log('shouldComponentUpdate', nextProps, nextState)
    return true
  }

  componentWillUpdate() {
    console.log('componentWillUpdate')
  }

  componentDidUpdate() {
    console.log('componentDidUpdate')
  }

  click() {
    this.setState({
      count: ++this.state.count
    })
  }

  render() {
    console.log('render')
    return (
      <div>
        <button onClick={this.click.bind(this)}>Click Me!</button>
        <A count={this.state.count} />
      </div>
    )
  }
}

ReactDOM.render(
  <B />,
  document.getElementById('root')
)

难点

首先你要十分清楚react的生命周期,执行生命周期函数,其实就是拿到定义的函数执行。那么如何拿到这些函数?第一个问题就是component实例如何拿到 createComponent函数用于获取这个实例。

六 diff算法

About

实现一个简易版本的react

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published