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>
    )
  }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章