React 类组件和函数组件

组件(Component)

1、组件:能跟其他物件组合起来的物件
2、就目前而言,一个返回React元素的“函数”就是组件
3、在Vue里,一个构造选项就可以表示一个组件

元素与组件
元素:const div = React.createElement('div',...)
//这是一个React元素(d是小写的)
组件:const Div = ()=>React.createElement('div'..)
//这是一个React组件(D是大写的)

React 的两种组件

1、类组件

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

  add() {
    this.setState({ n: this.state.n + 1 });
  }

  render() {
    return (
      
儿子n :{this.state.n}
); } }

类组件注意事项:

  • this.state.n += 1 无效?
    //其实n已经变了,UI没自动更新,
    //调用 setState 才会触发更新(异步更新,这里复制原有n,得到一个新的n)
    //React不不像Vue一直监听data 所以不会更新
  • setState 会异步更新UI
    //setState 之后,state不会立马改变,立马读会失败
    //推荐使用setState(函数)

2、函数组件

const Grandson = () => {
  const [n, setN] = React.useState(0);
  return (
    
孙子n:{n}
); };

函数组件注意事项:
没有 this,一律使用参数和变量

组件使用方法:

  • 会被翻译成什么

  • 会被翻译为React.createElement('div')

  • 翻译为React.createElement(Welcome)

  • 可以用babel online直接翻译给你看

  • React.createElement的逻辑

  • 如果传入一个字符串div, 则会创建div

  • 如果传入一个函数,则会调用该函数,获取其返回值

  • 如果传入一个类,则在类前面加个new(这会导致执行constructor), 获取一个组件对象,然后调用对象的render方法,获取其返回值

props - 外部数据

const root =document.getElementById('root')
const React = window.React
const ReactDOM = window.ReactDOM
// import React from 'react'
// import ReactDOM from 'react-dom'

function App(){
  return(
    
爸爸
) } class Son extends React.Component{ constructor(){ super() this.state = { n:0 } } add(){ this.setState({n:this.state.n+1}) } render(){ return(
儿子 n:{this.state.n},{this.props.x} //---------类组件直接用this.props接收值
) } } const Grandson =(props) =>{ const [n,setN] = React.useState(0) return(
孙子 n:{n},{props.x}//---------函数组件接收一个props的参数不需要this就可以接收值
) } ReactDOM.render(App(),root);

state - 内部数据

  • 链接
  • 类组件用this.state读,this.setState写
  • 函数组件用useState返回数组,第一项读,第二项写
  • 关注数据的时候我们需要关注,初始化,怎么读,怎么写
  • 直接改state的n,ui不会刷新,vue里面是对data做了劫持,必须要用setState,
  • 另外不推荐对象局部改变了,又原封不动的给setState,效果是ok的但是一般推荐要产生一个新的对象
  • 这就叫做数据不可变,以前的数据不要改,要改就产生一个新的对象
    this.setState({ n: this.state.n + 1 });
  • 牛x的前端用setState(函数),这样写的好处,打印n的值发现不对,因为setState是异步的更新ui的过程,好处就是避免异步造成的误解
this.setState((state)=>{
  return {n: state.n+1}
})

// 如果用这种写法就很清楚的知道旧的state和新的state
// 打印n
this.setState(state=>{
  const n = state.n + 1
  console.log(n)
  return {n}
})

setState 注意事项

  • this.state.n += 1无效?
  • 其实n已经改变了,只不过UI不会自动更新而已
  • 调用setState才会触发UI更新(异步更新)
  • 因为React没有像Vue监听data一样监听state
  • setState会异步更新UI
  • setState之后,state不会马上改变,立马读state会失败
  • 更推荐的方式是setState(函数),函数接受一个旧的state返回一个新的state
  • this.setState(this.state)不推荐
  • React希望我们不要修改旧state(不可变数据)
  • 常用代码: setState({n: state.n + 1})
  • 总结,这是一种理念(函数式)
函数组件注意事项
  • 跟类组件类似的地方,也要通过setX(新值)来更新UI
  • 跟类组件不同的地方,没有this,一律用参数和变量

复杂的state

  • 如果state里不止有n怎么办

  • (类组件里有n和m)[https://codesandbox.io/s/friendly-aryabhata-eq24y]

  • (函数组件里有n和m)[https://codesandbox.io/s/funny-montalcini-wszxe]

  • 函数组件另一种(不推荐的写法)[https://codesandbox.io/s/distracted-taussig-dmkjz],写完会发现m被置空

总结复杂的state

  • 类组件的setState会自动合并第一层属性
  • (但是不会合并第二层属性)[https://codesandbox.io/s/dreamy-pike-w9je2],需要使用(Object.assign)[https://codesandbox.io/s/zen-margulis-gjr7t],或者(...操作符)[https://codesandbox.io/s/dawn-sound-rwyxv]
  • 函数组件的setX则完全不会合并state,需要使用Object.assign,或者(...操作符)
  • ...在react是经常使用的

事件绑定

类组件的事件绑定


// 传一个函数给onClick即可,注意C大写
// 思考一个问题,下面这样写行不行

// 有问题,这样使得this.addN里的this变成window

// 这样写是可以的,因为它返回一个绑定了当前this的新函数
// 但是这样写太麻烦,你不如第一种
// 但是第一种写法依然太长,可用this._addN = ()=> this.addN()
// 给箭头函数取个名字,然后写成,在构造函数中赋值

// 给箭头函数取个名字,然后写成

// 这样又不如写成
constructor() {
  this.addN = ()=> this.setState({n: this.state.n + 1})
}
render(){
  return 
}

但这样写不如声明addN结构清晰
最终的方案,类组件的事件绑定最好的方法

class Son extends React.Component {
  addN = () => this.setState({n: this.state.n + 1});
  render() {
    return 
  }
}

你可能感兴趣的:(React 类组件和函数组件)