# react 笔记

由于之前一直都是vuer,然后并未开始了解`react`,所以以下均作为学习笔记日后回顾。

# 安装和使用

安装一个react的项目

npx create-react-app myproject

定义一个组件 : 定义一个类集成React.Component

class App extends React.Component {
  render() {
    return <div>HELLO</div>;
  }
}

Jsx语法需要引入React包,否则无法编译

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);

# VSCODE 快捷语法

常用快捷键

rcc
rce
rcep
rfce
rcredux

# JSX 语法

  • 在模板上写入js代码,必须使用{}包起来

    例:

    使用到便利绑定dom,需要给每个dom绑定一个key值

    return (
    <Fragment>
      <ul>
     {this.state.map((item,index)=>{
          return <li key={index}>{item}</li>
        })}
      </ul>
      <Fragment/>
    )
    
  • 绑定事件:在原生 js 基础上讲事件名首字母大写
<input onChange={this.handleClick.bind(this, params)} />
  • 定义数据和相关操作

    export default class App extends Component{
      constructor(props){
        super(props)
        this.state = {
          inputValue:'',
          list:[]
        }
      }
      render(){
        return (
        )
      }
    }
    

    这一点类似于小程序中的事件绑定

    • 取数据this.state.inputValue
    • 改编数据 this.setState({inputValue:'11'})

    一般使用 setState()尽量使用函数绑定

    this.setState(() => ({
      list: ""
    }));
    
  • 注释

    {/*多行注释*/}
    {//单行注释}
    
  • 插入 HTML 代码

    <li dangerSetInnterHTML={{ __html: html片段 }}></li>
    

# react 相关知识点

# 组件传值

父组件向子组件传值

<TodoItem content={item} />

vue 中 <TodoItem :content=item/>

子组件取值

this.props.content;

vue 中,通过 props 拿到数据之后即可使用

子组件调用父组件方法

{/*1. 父组件传入方法给子组件,需要把this指向父组件*/}
<TodoItem handleItem = {this.deleteItem.bind(this)} />

{//子组件使用方法}
this.props.handleItem()

vue 中直接使用 this.$emit("eventName",param) 向父组件抛出事件,并传递参数param.父组件监听即可。如果子组件想要调用父组件方法。直接使用 this.$parent.method

# 定义事件,传参

jsx语法中定义事件需要在原生事件名基础大写

render(){
  return (
  <div onClick={this.handleClick.bind(this)}></div>
  )
}

如果需要传递参数的话,需要用箭头函数接受,这样就不需要绑定this

onChange = {()=>{this.handleClick()}}

vue 中就不需要管this,直接使用 bind 语法即可,@click="method"

# 单向数据流

react只允许父组件向子组件传值,但是子组件不允许直接改变父组件传递过来的值,这个值是只读属性。这种传递方式方便调试维护

如果要更改,就应该传递父组件方法修改

# PropTypes 和 defaultProps

子组件设置父组件传递过来的值得校验

import PropTypes from 'prop-types'
TodoItem.propTypes = {
  content:PropTypes.string
  ...
}

// 设置默认值
TodoItem.defaultProps = {
  content:'front'
}

vue 中在 props 中设置,可以设置每个 props 的默认值和类型

# render 函数和 state 和 props 关系

state或者props发生变化时,render都会重新调用渲染 dom

# ref

在 react 中操作dom需要使用ref绑定dom节点

<input
  ref={input => {
    this.input = input;
  }}
/>;
{
  /*使用dom*/
}
this.input;

注意:使用refsetState搭配使用时可能会碰到dom更新不及时的问题,这是因为setState是一个异步执行的函数

如果碰到上述问题可以借助 setState 的第二个参数,回调执行

commit(){
  this.setState((prevState)=>({
    list:[...prevState.list,prevState.inputValue],
    inputValue:''
  }),()=>{
    // 操作dom
    this.input
  })
}

vue 中使用 :现在 dom 上写上 ref,然后使用this.refs.即可

# 生命周期函数

//首先是个初始化定义props和state
constructor()

//然后进入挂载阶段,这里只有第一次进入页面才会执行 它代表的过程是组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。
componentWillMount(){
    console.log('挂载之前执行')
}
// 组件第一次渲染完成,此时dom节点已经生成,可以在这里调用ajax请求,返回数据setState后组件会重新渲染
componentDidMount(){
  console.log('挂载完成执行')
}
// clear你在组建中所有的setTimeout,setInterval 和事件监听
componentWillUnmount(){
  console.log('组件销毁之前')
}

// 更新阶段 分为props更新和state更新
1. state更新
shouldComponentUpdate(){
  console.log('确认state是否需要更新')
  return boolean;
}
// 如果shouldComponentUpdate需要更新,执行下面
componentWillUpdate(){
  console.log('组件更新前')
}
render(){
  console.log('组件更新')
}
componentDidUpate(){
  console.log('组件更新完成')
}

2. props更新
// 这个钩子执行条件: 1. 这个组件要从父组件接受参数 2.第一次不执行,组件已经存在父组件时才会执行
componentWillReceiveProps(){
  console.log('组件接受props之前')
}
// 接下来依然是执行组件更新钩子
shouldComponentUpdate(nextProps,nextState){
  return true
}
componentWillUpdate(nextProps,nextState){}
render(){}
componentDidUpdate(prevProps,prevState){}


// 最后是组件即将移除钩子
componentWillUnmouent(){}

// 后续更新增加
getDerivedStateFromProps(nextProps, prevState)
getSnapshotBeforeUpdate(prevProps, prevState)

部分使用场景

//节省子组件render次数 但是都可以用hooks修改

shoudComponentUpdate(nextState,nextProps){
  if(nextProps.content !== this.props.content){
    return true
  }else{
    return false
  }
}

API的调用

componentDidMount(){
  ... ajax请求
}

# react 性能优化

  1. react使用虚拟 dom 减少不必要的dom的获取,节省性能。
  2. react底层的setState函数是异步执行的,他可以把多次 state 数据改变归到一次执行
  3. react虚拟 dom 的比对采用同层比对和key值比对从而提升比对的速率提升性能
  4. 可以利用shouldComponentWillUpdate减少子组件执行render函数次数
  5. 函数的作用于绑定一般放在构造函数中执行,只执行一次即可

# 动态绑定样式

  • 使用逻辑运算符

    render(){
      return (
      <div className={this.state.error && ’icon-class}>hello</div>
      )
    }
    
  • 三元运算符

    render(){
      return (
      <div className={this.state.error? 'icon-class':'icon-error'}></div>
      )
    }
    
  • 定义函数,类似于computed写法

    getClassName(){
      return this.state.error ? 'icon-class':''
    }
    render(){
      return (
      <div className={this.getClassName()}>
      )
    }
    
  • 内联style

    render(){
      return(
      <div style={this.state.error?{display:'none'}:{display:'inline-block'}}></div>
      )
    }
    

# react-router

默认情况下dva使用的是 history 也就是带哈希的路由,还有一个是 browserhistory 不带哈希的

定义路由

在路口App.js引入路由类型

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <BrowserRouter>
          <div>
            <Header />
            <Route path="/" exact component={Home}></Route>
            <Route path="/login" exact component={Login}></Route>
            <Route path="/write" exact component={Write}></Route>
            <Route path="/detail/:id" exact component={Detail}></Route>
          </div>
        </BrowserRouter>
      </Provider>
    );
  }
}

获取路由参数

  • query

    this.props.location.search;
    
  • params

    this.props.match.params;
    

路由跳转

  • Link 方法跳转

    import { Link } from "react-router-dom";
    
    <Link to={}></Link>;
    
  • 函数式编程跳转

    this.props.push(`params`);
    
Last update: 7/20/2021, 8:53:54 AM