浅析react组件

105 阅读3分钟

元素与组件

元素 : const div = React.createElement('div',...)

组件: const Div = ()=> React.createElement('div',...)

元素的d尽量小写,组件的D尽量大写


函数组件与类组件

  1. 函数组件:
const Welcome = (props)=> {
  return (
    <section>
      <div>
        hi, {props.name}
      </div>
    </section>
  );
}

<Welcome name='Tom' />
  1. 类组件
class Welcome extends React.Component {
  constructor() {
    super();
  }

  render() {
    return (
      <section>
        <div>
          hi, {this.props.name}
        </div>
      </section>
    )
  }
}

<Welcome name='Tom' />

在react中,无论我们时写html标签<div></div> 还是写组件 <Welcome /> 都会被翻译成React.createElement('div') / React.createElement(Welcome) 我们可以通过babel online自己尝试以下。


react的外部数据

  1. 传入外部数据

在reat中,我们可以直接在组件标签上添加其外部数据

//传字符串
<Welcome name='Tom' />

//传变量
<Welcome number={0} />
  1. 引入外部数据
//在函数组件中
{props.name}

//在类组件中
{this.props.name}

react的内部数据

  1. 在类组件中
class App extends React.Component {
  constructor() {
    super();
    this.state = {n: 0}
    //在constructor中声明n
  }

  addN = () => {
    this.setState((state) => {
    //使用this.setState修改n
      const n = state.n + 1
      return {n}
    })
  }

  render() {
    return (
      <section>
        <div>
          {this.state.n}
        </div>
        <hr/>
        <button onClick={this.addN}>+1</button>
      </section>
    )
  }
}

这里的setState是异步操作

  1. 在函数组件中
const App = () => {
  const [n,setN]=React.useState(0)
  //使用析构赋值,声明n和setN
  return (
    <section>
      {n}
      <hr/>
      <button onClick={()=>{setN(n + 1)}}>+1</button>
      //使用setN 修改n
    </section>
  )
}

state中复杂数据的问题

在上面的state中只有一个数据,所以我们无论如何set都不会有问题,但当state中有多个数据时,问题就出现了。

  1. 类组件

在类组件中,setState会帮你自动合并第一层属性(eg:当有m n 两个数据时,修改其中一个不会影响另一个)

但是如果你修改了其中第二层的一个数据,那么react不会帮你保留其他数据。(如果你想保留,可以使用 ...this.state.xxx)

  changeUser=()=>{
    this.setState((state)=>{
      const user = {...this.state.user,name: 'jack'}
      return {user}
    })
  }
  1. 函数组件

在函数组件中,react不会帮你合并任何值

const App = ()=>{
  const [state,setState] = React.useState({n:0,m:0})
  return(
    <section>
     n :  {state.n}
     <hr/>
     <button onClick={()=>{setState({...state,n: state.n + 1})}}>n + 1</button>
      <hr/>
      m:{state.m}
      <hr/>
      <button onClick={()=>{setState({...state,m:state.m+1})}}>m + 1</button>
    </section>
  )
}

我们可以通过展开操作符来解决这一问题,或者,在声明m n 时,分开声明。


事件绑定(类组件)

在react中,我们有两种声明方法的方式。

//第一种
class App extends React.Component {
  constructor() {
    super();
    this.state = {n: 0}
  }

  addN() {
    this.setState(state => {
      const n = state.n + 1
      return {n}
    })
  }

  render() {
    return (
      <section>
        n : {this.state.n}
        <button onClick={() => {
          this.addN()
        }}> + 1
        </button>
      </section>
    )
  }
}

此时的addN是在原型链上的

而button的原理是 button.onClick.call(null)的,所以如果不使用箭头函数,那么this就会指向window。

class App extends React.Component {
  constructor() {
    super();
    this.state = {n: 0}
  }

  addN = () => {
    this.setState(state => {
      const n = state.n + 1
      return {n}
    })
  }

  render() {
    return (
      <section>
        n : {this.state.n}
        <button onClick={this.addN} > + 1</button>
      </section>
    )
  }
}

此时的addN是是不在原型链上的,而是在实例上的,而且由于箭头函数没有this,所以this会直接指向实例,会正确触发函数。


vue 与 react 的区别

  1. 相同

vue和react都是对视图的封装。

  • vue通过构造选项表示组件

  • react通过类/函数表示组件

都提供了createElement的简写

  • react——jsx

  • vue——template模板语法

  1. 不同

react将html放在js中写

vue将js放在html中写