一、生命周期函數(shù)
掛載卸載過程
constructor props context
componentWillMount 服務(wù)器與客戶端
componentDidMount ajax請求
componentWillUnmount 清除動畫
更新過程
componentwillRecieveUpdata(nextProps)
shouldComponentwillupdata(nextProps,nextState) 組件渲染監(jiān)聽
componentDidupdata()
componentWillupdata
render 更新組建
二箕般、網(wǎng)絡(luò)請求與反向代理
1瘤泪、網(wǎng)絡(luò)請求
下載: npm i -S axios
// 組件掛載完畢后键痛,執(zhí)行的方法 只執(zhí)行一次
componentDidMount() {
axios.get('http://localhost:3000/data/users.json')
.then(ret => {
console.log(ret);
})
}
2、反向代理
下載:npm i -S http-proxy-middleware
新建:setupProxy.js
const {createProxyMiddleware: proxy} = require('http-proxy-middleware')
module.exports = app => {
app.use('/api', proxy({
target: 'http://localhost:8082',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}))
}
三羊精、高階組件(HOC)
- 一個函數(shù)斯够,傳給它一個組件,它返回一個新的組件
- 首先創(chuàng)建一個高階組件函數(shù)
- 指定函數(shù)參數(shù)喧锦,參數(shù)應(yīng)該以大寫字母開頭
- 在函數(shù)內(nèi)部創(chuàng)建一個類組件读规,提供復(fù)用的狀態(tài)邏輯代碼并返回
- 在該組件中,渲染參數(shù)組件燃少,同時將狀態(tài)通過prop傳遞給參數(shù)組件
- 調(diào)用該高階組件束亏,傳入要增強的組件,通過返回值拿到增強后的組件阵具,并將其渲染到頁面
1碍遍、普通寫法
定義高階組件
import React, { Component } from 'react';
// Fragment jsx不會解析為html,但是它能當(dāng)作 頂級元素 相當(dāng)于vue中的template
// react提供一種簡寫 <></>
// 高階組件是一個函數(shù)且 參數(shù) 是一個首字母要大寫的組件
function withCmp(Cmp) {
// 需要一個類組件且此組件要有返回
return class HocCmp extends Component {
// 渲染
render() {
// let title = this.props.title+'----...'
return (
<>
<h1>頭部</h1>
{
// 子組件 通過props傳給參數(shù)組件
}
<Cmp {...this.props}></Cmp>
<h4>底部</h4>
</>
)
}
}
}
export default withCmp
調(diào)用高階組件
import React, { Component } from 'react'
// Home組件增強一些功能阳液,使用此組件就自帶頭和尾怕敬,但是有時候又可不沒有
// 對于Home組件使用高階組件進行包裹
import Home from './pages/Home'
// 導(dǎo)入高階組件 函數(shù)
import hocCmp from './hoc/withCmp'
let Myhome = hocCmp(Home)
export default class App extends Component {
state = {
title: '我是一個標(biāo)題',
desc: '描述'
}
render() {
return (
<div>
{/* 高階組件 */}
<Myhome state={this.state} />
<Home title={this.state.title} />
</div>
)
}
}
2、裝飾器渲染
裝飾器是一種函數(shù)帘皿,寫成 @函數(shù)名
1东跪、安裝:npm i -D customize-cra react-app-rewired
2、修改package.json文件中scripts命令
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
}
3鹰溜、創(chuàng)建config-overrides.js配置文件
// 環(huán)境是一個commonjs規(guī)范環(huán)境
const path = require('path')
// customize-cra 把webpack配置定義成方法越庇,方便使用調(diào)用,不用去寫webpack配置
const { addDecoratorsLegacy, override } = require('customize-cra')
// 自定義一些webpack配置 定義成函數(shù)
const customize = () => (config, env) => {
config.resolve.alias['@'] = path.join(__dirname, 'src')
return config
}
// 模塊導(dǎo)出 override=> 把你現(xiàn)在的配置和react中的webpack配置合并奉狈,它優(yōu)先級更高
module.exports = override(
// 讓webpack支持 decorator
addDecoratorsLegacy(),
customize()
)
4卤唉、使用裝飾器
不用的寫法
裝飾器寫法
解決警告問題
我們解決這個警告 需要在根目錄配置一個tsconfig.json 文件
{
"compilerOptions": {
"experimentalDecorators": true,
"allowJs": true
}
}
3、memoization(計算屬性-記憶組件)
連續(xù)兩次相同傳參仁期,第二次會直接返回上次的結(jié)果桑驱,每次傳參不一樣,就直接調(diào)用函數(shù)返回新的結(jié)果跛蛋,會丟失之前的記錄熬的,并不是完全記憶,可以在它的參數(shù)中傳入state數(shù)據(jù)從而實現(xiàn)了類似Vue中的計算屬性功能
安裝:npm i -S memoize-one
# 引入
import memoizeOne from 'memoize-one'
# 使用
getValue = memoizeOne(
(x,y) => x+y
)
# 調(diào)用
render(){
let total = this.getValue(this.state.x, this.state.y)
return <div>{total}</div>
}
4赊级、memo(自帶)
React.memo()是一個高階函數(shù)押框,它與 React.PureComponent類似,但是一個函數(shù)組件而非一個類
import React from 'react'
export default React.memo(
props => {
console.log('child---render')
return (
<div>{props.title}</div>
)
}
)
三理逊、狀態(tài)管理(redux)
項目組件的數(shù)量和層級也變得越來越多橡伞,越來越深盒揉,此時組件間的數(shù)據(jù)通信就變得異常的復(fù)雜和低效,為了解決這個問題兑徘,引入了狀態(tài)管理(redux)從而很好的解決多組件之間的通信問題刚盈。
安裝:npm i -S redux
三大原則
- 單一數(shù)據(jù)源 store
- State 是只讀的
-
使用純函數(shù)(reducer)來執(zhí)行修改
import {createStore} from 'redux'
// 數(shù)據(jù)源
const defaultStore={
name:'張珊'
}
// 不能直接修改state
function reducers(state=defaultStore,action){
try {
if(action.type=='incr'){
return {
name:'sad'+state.name
}
}
} catch (error) {
return state
}
}
// 創(chuàng)建倉庫
const store=createStore(
reducers,
window._REDUX_DEVTOOLS_EXTENSION__&&window.__REDUX__DEVTOOLS_EXTENSION__()
)
// 導(dǎo)出
export default store
app.jsx
import React, { Component } from 'react'
import store from './index'
export default class App extends Comment {
constructor(props) {
super(props)
// 1、獲取數(shù)據(jù)store
this.state = store.getState()
// 2挂脑、訂閱藕漱,數(shù)據(jù)修改自己更新狀態(tài)數(shù)據(jù)
store.subscribe(() => {
this.setState(state => store.getState())
})
}
render(){
return(
<div>
<h3>{this.state.name}</h3>
<button onClick={this.incr}>名稱</button>
</div>
)
}
incr=()=>{
// 3、action creator 必須是對象
const actionCreator={
type:'incr',
payload:1
}
// 4崭闲、派發(fā)一個reducer任務(wù)
store.dispatch(actionCreator)
}
}
1肋联、react-redux與redux-thunk
react-redux:edux給我們提供一些高階組件
redux-thunk:redux異步操作
npm i -S redux react-redux redux-thunk
1)、全局共享store
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
import store from './store'
import App from './App'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)
2)刁俭、定義方法 action
countAction.js
import React,{Component} from 'react'
import {connect}from 'react-redux'
import * as actions from './store/actions/countAction'
/*
裝飾器
參數(shù)1:吧redux的state映射成props
參數(shù)2 mapPropsToDispath
*/
@connect(state=>(state),actions)
export default class App extends Component{
render(){
return(
<div>
<h3>{this.props.count}</h3>
shouye
<button onClick={this.incr}></button>
</div>
)
}
incr=()=>{
this.props.incr()
}
}
4)橄仍、入口記錄相關(guān)內(nèi)容
index.js
import {createStore,applyMiddleware,compose} from 'redux'
import thunk from 'redux-thunk'
import reducer from './reducers/countReducer'
// 記錄日志中間件
const mym=store=>next=>action=>{
console.log(action,store)
next(action)
}
// 配置chrom的dedux
const composeEnhancers=typeof window=='object'
&&window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__?
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}):compose
const engancer=composeEnhancers(
applyMiddleware(thunk,mym)
)
// 導(dǎo)出
export default createStore(
reducer,
engancer
)
5)、定義數(shù)據(jù)源
countRedycer.js
import CountMethod from '../methods/CountMethod'
const defaultState={
count:1
}
export default (state=defaultState,action)=>{
try {
return CountMethod[actions.type](state,action.payload)
} catch (error) {
return state
}
}
6)薄翅、整合數(shù)據(jù)返回對應(yīng)的值
// 處理
class CountMethod{
incr(state,data){
return {
count: state.count+data
}
}
}
export default new CountMethod
四沙兰、路由
- 前端路由功能:讓用戶從一個視圖(組件)導(dǎo)航到另一個視圖(組件)
- 前端路由是一套映射規(guī)則,在React中翘魄,是URL路徑與組件的對應(yīng)關(guān)系
- 使用React路由簡單來說鼎天,就是配置路徑和組件
npm i -S react-router-dom
使用路由
1、定義路由模式 index.js
import React from 'react'
import reactDom from 'react-dom'
import App from './App.jsx'
// 全局共享store
import { Provider } from 'react-redux'
import {HasRouter as Router} from 'react-router-dom'
import store from './store'
reactDom.render(
<Provider store={store}>
<Router>
<App />
</Router>
</Provider>,
document.querySelector('#root')
2暑竟、定義路由導(dǎo)航
import React,{COmponent} from 'react'
import { Route } from 'react-router-dom'
// 導(dǎo)入相關(guān)模塊
import Home from './views/home'
import News from './views/News'
class App extends Comment{
constructor(props){
super(props)
}
render(){
return(
<>
{/*
path:路徑
component:渲染的組件
exact:嚴格匹配
*/}
<Route exact path='/' component={Home}></Route>
<Route path='/news' component={News}></Route>
</>
)
}
}
聲明式導(dǎo)航
使用Link或NavLink組件完成
Link :組件最終會渲染為 HTML 標(biāo)簽 <a>
NavLink:給已經(jīng)渲染的元素添加參數(shù)
// react中的路由規(guī)則都是以組件的方式定義
import { Route, Link, NavLink } from 'react-router-dom'
// 導(dǎo)入渲染的視圖組件
import Home from './views/Home'
import News from './views/News
<li><NavLink exact activeClassName="active" to="/">首頁</NavLink></li>
<li><NavLink activeClassName="active" to="/news">新聞列</NavLink></li>
{/* path訪問的uri路徑 component就是匹配成功后渲染的組件 */}
{/* exact 嚴格匹配 */}
{/* Rouet組件中匹配成功的渲中會自動在this.props添加路由導(dǎo)航相關(guān)屬性方法 */}
<Route exact path="/" component={Home} />
<Route path="/news" component={News} />
路由參數(shù)
<Route path=’/aa/:id’ component={Main}>
- params
在路由目標(biāo)頁面中通過 this.props.match.params
- query
通過地址欄中的 ?key=value&key=value,通過 this.props.location.search
- state
隱式轉(zhuǎn)參斋射,一點用于數(shù)據(jù)的收集 this.props.location.state