React入门概念

React

安装

  1. 全局安装脚手架create-react-app
npm i -g create-react-app
  1. 创建项目
create-react-app projectName
  1. 打开项目
cd projectName
  1. 启动项目
npm start
  1. 项目默认的配置项是隐藏的,通过执行以下命令可以暴露配置项
npm run eject

文件结构

在这里插入图片描述

React和ReactDom

React负责逻辑控制,数据 -> VDOM,创建虚拟DOM
react中的的JSX语法
JSX => React.createElement(…)

ReactDom渲染实际DOM,VDOM -> DOM 。

ReactDOM.render(
  <div>react</div>,
  document.getElementById('root')
);

JSX

JSX是⼀种JavaScript的语法扩展,其格式⽐较像模版语⾔,但事
实上完全是在JavaScript内部实现的。

使用JSX

1、表达式{}的使用

const name = 'react';
const jsx = <h1>{name}</h1>

2、函数

function sayHi(name){
  return `${name} says hi`;
}
const jsx = <h1>{sayHi('react')}</h1>

3、条件语句

const name = 'react';
const show = true
const content = show ? <h1>{name}</h1> : null
const jsx = <h1>{content}</h1>

4、数组

const arr = [1,2,3,4].map(val =><li key={val}>{val}</li>)
const jsx=(
  <div>
    <ul>{arr}</ul>
  </div>
)

5、属性
静态值用双引号,动态值则是一个花括号。

import logo from './logo.svg'
const jsx = (
  <div>
    <img src={logo} style={{width:50}} />
  </div>
)

组件

组件是抽象的独⽴功能模块,react应⽤程序由组件构建⽽成。

组件有两种形式
function组件class组件

1、 class组件
class组件通常拥有状态和⽣命周期,继承了 Component,实现render⽅法。
创建一个组件

import React,{ Component } from 'react'

export default class Com1 extends Component{
  render(){
  const content = '这是一个组件'
    return (
      <div>
       	{content}
      </div>
    )
  }
}

在需要使用该组件是时候直接引入即可。

import Com1 from '@/components/com1'

2、 function组件
函数组件通常⽆状态,仅关注内容展示,返回渲染结果即可。

function com2(){
	return(
		<div>
			这是function组件
		</div>
	)
}

从React16.8开始引⼊了hooks,函数组件也能够拥有状态。

组件状态管理

如果组件中数据会变化,并影响⻚⾯内容,则组件需要拥有状态(state)并维护状态。

class组件中的状态管理

class组件使⽤state和setState维护状态

创建一个组件

import React,{ Component } from 'react'

export default class Com1 extends Component{
  constructor(props){
    super(props); // 继承Component
    this.state={
      name : '组件1'
    }
    // 使⽤state属性维护状态,在构造函数中初始化状态
  }
  render(){
    return (
      <div>
        {this.state.name}
      </div>
    )
  }
}

state中的状态不能直接更改

this.state.name = '这就是组件1啊' // 错误

而是要采用setState()

this.setState({
	name:'这就是组件1啊'
})

setState()方法是异步的,也就说你在该函数里面改变某个值后,立即调用该属性,其值并未发生改变。

this.setState({
	name:'这就是组件1啊'
})
console.log(this.state.name) // 组件1

如果想在改变后立即调用,有以下三种方式:

  1. 传递函数给setState方法
  	this.setState({
      name:'这是组件1啊'
    },()=>{
      console.log(this.state.name) // 这是组件1啊
    })
import React,{ Component } from 'react'

export default class Com1 extends Component{
  constructor(props){
    super(props);
    this.state={
      counter: 0
    }
  }
  componentDidMount(){
    this.setState({
      counter:this.state.counter+3
    })
    this.setState({
      counter:this.state.counter+1
    }) // 调用了两次,其实只执行了最后一个+1
  }
  render(){
    return (
      <div>
        {this.state.counter} // {/* 1 */} 
      </div>
    )
  }
}
this.setState((nextState,props)=>({
  counter:nextState.counter+1
}))
this.setState((nextState,props)=>({
  counter:nextState.counter+1
}))
// 此时执行counter 为 2
  1. 使用定时器
    其实就是利用了事件队列。
  componentDidMount() {
    setTimeout(() => {
      this.changeValue();
      console.log(this.state.name); // 这就是组件1啊
    }, 0);
  }
  changeValue = () => {
    this.setState({
      name: '这就是组件1啊' // 初始值是 组件1
    })
  }
  1. 原生事件中修改
  componentDidMount() {
    document.body.addEventListener('click',this.changeValue,false)
  }
  changeValue = () => {
    this.setState({
      name: '这就是组件1啊'
    })
  }

总结: setState只有在合成事件和⽣命周期函数中是异步的,在原⽣事件如addEventListener和setTimeout、setInterval中都是同步的。

原⽣事件绑定不会通过合成事件的⽅式处理,⾃然也不会进⼊更新事务的处理流程。setTimeout也⼀样,在setTimeout回调执⾏时已经完成了原更新组件流程,也不会再进⼊异步更新流程,其结果⾃然就是是同步的了。

function组件中的状态管理
函数组件通过hooks api维护状态

import React,{ useState,useEffect } from 'react'

export default function Com2(){
  const [name,setName] = useState('组件2')
  useEffect(()=>{
    setTimeout(()=>{
      setName('这是组件2了')
    })
  })
  return (
    <div>{name}</div>
  ) 
}

其实可以把useEffect()看作是class组件中的componentDidMount()componentDidUpdate()以及componentWillUnmount()三者的组合。

事件处理

事件回调函数注意绑定this指向,常⻅三种⽅法:

  1. 构造函数中绑定并覆盖:this.change =this.change.bind(this)
  2. ⽅法定义为箭头函数:change = ()=>{},使⽤箭头函数,不需要指定回调函数this,且便于传递参数
  3. 事件中定义为箭头函数:onChange={()=>this.change()}

react⾥遵循单项数据流,没有双向绑定,输⼊框要设置value
和onChange,称为受控组件

组件通信

props传递
属性:

// 父
<Son name="leo"></Son>

// son.js
<h1>{this.props.name}</h1>

函数

// 父
<Son change={this.onChange}></Son>

// son.js
this.props.change(this.state.name) // 可以把子组件的信息传入父组件,这个叫做状态提升。

生命周期

在这里插入图片描述
v16.4之后的生命周期中废弃了以下三个方法:

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

如果要使用的话需要在头部加上UNSAFE_

同时引入了两个新的生命周期函数:

  • static getDerivedStateFromProps
  • getSnapshotBeforeUpdate

在这里插入图片描述
废弃缘由:

原来(React v16.0前)的⽣命周期在React v16推出的Fiber之后
就不合适了,因为如果要开启async rendering,在render函数
之前的所有函数,都有可能被执⾏多次

原来(React v16.0前)的⽣命周期有哪些是在render前执⾏的呢?

  • componentWillMount
  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate

static getDerivedStateFromProps(props,state)
getDerivedStateFromProps 会在调⽤ render ⽅法之前调⽤,并且在初始挂载及后续更新时都会被调⽤。它应返回⼀个对象来更新 state,如果返回 null 则不更新任何内容。

请注意,不管原因是什么,都会在每次渲染前触发此⽅法。与UNSAFE_componentWillReceiveProps 形成对⽐,后者仅在⽗组件重新渲染时触发,⽽不是在内部调⽤ setState 时。

static getDerivedStateFromProps(props, state) 在组件创建时和更新时的render⽅法之前调⽤,它应该返回⼀个对象来更新状态,或者返回null来不更新任何内容。

import React, { Component } from 'react'

export default class Com1 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '组件1',
    }
  }
  static getDerivedStateFromProps(props,state){
    const {name} = state
    return name !== '组件11'?null:{name:'如果输入结果等于组件11就返回这个state'}
  }
  change(e){
    this.setState({
      name:e.target.value
    })
  }
  render() {
    return (
      <div>
        {this.state.name} {/* 1 */}
        <input onChange={(e)=>this.change(e)} value={this.state.name}/>
      </div>
    )
  }
}

getSnapshotBeforeUpdate(prevProps, prevState)
getSnapshotBeforeUpdate() 在最近⼀次渲染输出(提交到DOM 节点)之前调⽤。它使得组件能在发⽣更改之前从 DOM中捕获⼀些信息(例如,滚动位置)。此⽣命周期的任何返回值将作为参数传递给 componentDidUpdate()。就相当于获取了上一次渲染的state的值。

此⽤法并不常⻅,但它可能出现在 UI 处理中,如需要以特殊⽅
式处理滚动位置的聊天线程等。

import React, { Component } from 'react'

export default class Com1 extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '组件1',
    }
  }
  getSnapshotBeforeUpdate(prevProps,prevState){
    const {name} = prevState
    console.log('get Snapshot: ',name) // 输出组件1
    return null
  }
  componentDidUpdate(){ // 假如第一次更新name的值为‘组件11’
    console.log('componentDidUpdate: ',this.state.name) // 输出组件11
  }
  change(e){
    this.setState({
      name:e.target.value
    })
  }
  render() {
    return (
      <div>
        {this.state.name} {/* 1 */}
        <input onChange={(e)=>this.change(e)} value={this.state.name}/>
      </div>
    )
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章