知识点收尾为项目开始
知识点
redux专场
帮助react维护状态数据
verson 1
//redux/index.js import {createStore} from 'redux' function PersionReducer(stata=[],action){ switch(action.type){ case 'insert': break case 'select': break case 'update': break case 'delete': break default: return state } } const store = createStore(PersionReducer) export default store //调用 import store from './reudx' store.getState() store.dispatch({type: 'inser', data: obj})
version 2
多个数据进行识别
//redux/index.js import {createStore} from 'redux' function PersionReducer(stata=[],action){ switch(action.type){ case 'person/insert': break case 'person/select': break case 'person/update': break case 'person/delete': break case 'goods/insert': break default: return state } } const store = createStore(PersionReducer) export default store //调用 import store from './reudx' store.getState() store.dispatch({type: 'person/inser', data: obj})
version 3
变量整合
version 3.1
//redux/index.js import {createStore} from 'redux' export const InsertAction = data=>{type: 'person/insert', data: obj} export const UpdateAction = data=>{type: 'person/update', data: obj} export const DeleteAction = data=>{type: 'person/delete', data: obj} export const SelectAction = data=>{type: 'person/select', data: obj} function PersionReducer(stata=[],action){ switch(action.type){ case 'person/insert': break case 'person/select': break case 'person/update': break case 'person/delete': break default: return state } } const store = createStore(PersionReducer) export default store //调用 import store from './reudx' import {InsertAction} from './reudx' store.getState() store.dispatch(InsertAction(data))
version 3.2
//redux/index.js import {createStore} from 'redux' const InsertType = 'person/inser' const UpdateType = 'person/update' const DeleteType = 'person/delete' const SelectType = 'person/select' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: obj} function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } const store = createStore(PersionReducer) export default store //调用 import store from './reudx' import {InsertAction} from './reudx' store.getState() store.dispatch(InsertAction(data))
version 4
代码拆分
//actionType.js export const InsertType = 'person/inser' export const UpdateType = 'person/update' export const DeleteType = 'person/delete' export const SelectType = 'person/select' //action.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: obj} //reducer.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export default function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } //index.js import {createStore} from 'redux' import PersionReducer from './reducer' const store = createStore(PersionReducer) export default store
version 5
combineReducer 合并多个reducer
//actionType.js export const InsertType = 'person/inser' export const UpdateType = 'person/update' export const DeleteType = 'person/delete' export const SelectType = 'person/select' //action.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: obj} //reducer.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export default function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } //index.js import {createStore,combineReducer } from 'redux' import PersionReducer from './reducer' const store = createStore(combineReducer({ persion: PersionReducer //goods: goods })) export default store //调用 import store from './reudx' import {InsertAction} from './reudx' store.getState() store.dispatch(InsertAction(data))
version 6
react-redux:解决在组件当中redux和业务逻辑代码混写的局面
npm i react-redux -S
使用步骤
1、在要使用的标签根部使用provider标签进行包围
2、使用connect将store当中的数据和方法绑定到action的props
//actionType.js export const InsertType = 'person/inser' export const UpdateType = 'person/update' export const DeleteType = 'person/delete' export const SelectType = 'person/select' //action.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: obj} //reducer.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export default function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } //index.js import {createStore,combineReducer } from 'redux' import PersionReducer from './reducer' const store = createStore(combineReducer({ persion: PersionReducer //goods: goods })) export default store //调用 //App.js import store from './redux/index.js' <provider store={store}> <Persion></Presion> </provider> //Persion.jsx import {connect} from 'react-redux' import {InsertAction} from './reudx' class Persion extends react.Component{ UNSAFE_componentWillMount(){ this.props.persionAction() console.log(this.props.persion) } ..... } ..... const 绑定state数据的回调函数 = (state)=>{ //自动接受的store下的state数据 return { persion: state.persion } } const 绑定action操作的回调函数 = (dispatch)=>{ persionAction: data=>dispath(InsertAction(data)) } export default connect(绑定state数据的回调函数,绑定action操作的回调函数)(Persion)
version 6.1
bindActionCreators动态绑定action方法
//actionType.js export const InsertType = 'person/inser' export const UpdateType = 'person/update' export const DeleteType = 'person/delete' export const SelectType = 'person/select' //action.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: obj} //reducer.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export default function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } //index.js import {createStore,combineReducer } from 'redux' import PersionReducer from './reducer' const store = createStore(combineReducer({ persion: PersionReducer //goods: goods })) export default store //调用 //App.js import store from './redux/index.js' <provider store={store}> <Persion></Presion> </provider> //Persion.jsx import {connect} from 'react-redux' *********import * as actions from './reudx' *********import {bindActionCreators} from 'redux' class Persion extends react.Component{ UNSAFE_componentWillMount(){ this.props.persionAction() console.log(this.props.persion) } ..... } ..... const 绑定state数据的回调函数 = (state)=>{ //自动接受的store下的state数据 return { persion: state.persion } } *********const 绑定action操作的回调函数 = dispatch=>bindActionCreators(actions,dispatch) export default connect(绑定state数据的回调函数,绑定action操作的回调函数)(Persion)
version 7
redux-thunk 异步任务
npm i redux-thunk -S
//actionType.js export const InsertType = 'person/inser' export const UpdateType = 'person/update' export const DeleteType = 'person/delete' export const SelectType = 'person/select' //action.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export const InsertAction = data=>{type: InsertType, data: obj} export const UpdateAction = data=>{type: UpdateType, data: obj} export const DeleteAction = data=>{type: DeleteType, data: obj} export const SelectAction = data=>{type: SelectType, data: data} ********** export default AsyncPerion=()=>{ return dispatch=>{ axios.get(url).ther(res=>{ if(res.code === 200){ dispatch(SelectAction(res.list)) } }) } } ********** //reducer.js import {InsertType,UpdateType,DeleteType,SelectType} from './actionType' export default function PersionReducer(stata=[],action){ switch(action.type){ case InsertType: break case SelectType: break case UpdateType: break case SelectType: break default: return state } } //index.js **********import {createStore,combineReducer,applyMiddleware } from 'redux' **********import {componentWithDevTools} from 'redux-devtools-extension' **********import thunk from 'redux-thunk' import PersionReducer from './reducer' const store = createStore(combineReducer({ persion: PersionReducer //goods: goods **********}),componentWithDevTools(applyMiddleware(thunk))) export default store //调用 //App.js import store from './redux/index.js' <provider store={store}> <Persion></Presion> </provider> //Persion.jsx import {connect} from 'react-redux' import * as actions from './reudx' import {bindActionCreators} from 'redux' class Persion extends react.Component{ UNSAFE_componentWillMount(){ ***************this.props.AsyncPerion() this.props.persionAction() console.log(this.props.persion) } ..... } ..... const 绑定state数据的回调函数 = (state)=>{ //自动接受的store下的state数据 return { persion: state.persion } } const 绑定action操作的回调函数 = dispatch=>bindActionCreators(actions,dispatch) export default connect(绑定state数据的回调函数,绑定action操作的回调函数)(Persion)
反馈
不知道react-redux处理过的值(存在于<layout>props中的state和各种dispatch方法)能不能在往下传递,例如layout下面仍有子组件需要触发store.dispatch,该怎么写?(试过用组件父传子的方式,将layout的整个props作为属性值往下传递,但是子组件的props并未改变)
const 绑定state数据的回调函数 = (state)=>{ console.log(state) //自动接受的store下的state数据 return { persion: state.persion } } export default connect(绑定state数据的回调函数)(Persion)
hook
React – A JavaScript library for building user interfaces
react拥有两种组件,类组件和函数组件,其中函数组件默认没有生命周期和状态数据,hook填补了这个空缺。
Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
useState
没有状态数据的前提下,函数组件当中的数据修改后很难刷新
export default function layout(){ var msg = 0 const addMsg=()=>{ msg++ console.log(msg) } return <> <p>{msg}</p> <button onClick={addMsg}>加</button> </> }
使用useState
1、定义useState方法,然后传入初始值
2、useState会返回两个参数,分别是state数据和可以刷新设置数据的方法
import React, { useState } from 'react'; export default function Layout(){ const [count, setCount] = useState(0); const addMsg=()=>{ setCount(count + 1) } return <> <p>{count}</p> <button onClick={addMsg}>加</button> </> }
如果state是多个数据,必须都发生修改,否则,没有修改的数据被置空覆盖了
import React, { useState } from 'react'; import img from "../asserts/image/1.jpg" export default function Layout(){ const [count, setCount] = useState({isShow:1,title: "隐藏"}); const toggle = ()=>{ if(count.isShow){ setCount({title: "显示"}) }else{ setCount({isShow:1,title: "隐藏"}) } console.log(count) } return <> <p> { count.isShow===1?<img src={img} style={{width:"100px"}} />:"" } </p> <button onClick={toggle}>{count.title}</button> </> }
useEffect
作用: 可以让函数组件拥有自己的生命周期
useEffect会在组件第一次挂载完毕, 更新完毕, 组件即将卸载的时候自动触发,相当于类组件中componentDidMount , componentDidUpdate, componentWillUnmount三个钩子函数的集合
-
componentDidMount :组件初始化挂载之后,执行useEffict当中的语句,不执行useEffict当中返回的函数
-
componentDidUpdate :组件初始化挂载之后,先执行useEffict当中返回的函数,再执行useEffict当中的语句
-
componentWillUnmount:只执行useEffict当中返回的函数
import React, { useEffect,useState } from 'react'; export default function Home(){ let [state,setState] = useState("我是home组件") useEffect( ()=>{ var obj = document.querySelector("#home_id") console.log("我执行了",obj) return ()=>{ console.log("我是home组件的嵌套函数,我执行了",obj) }//这个函数在组件卸载前执行 } ) const change = ()=>{ setState("hello,我确实是home组件") } return <> <p id="home_id" onClick={change}>{state}</p> </> }
useEffect在所有组件内数据发送修改都执行,这个不合适。
useEffect拥有两个参数
-
第一个参数是一个操作函数,包含两部分,执行的语句,和返回的函数
-
第二个参数是一个数组,数组的元素是要监听的变量
import React, { useEffect,useState } from 'react'; export default function Home(){ let [state,setState] = useState("我是home组件") let [hhh,setHhh] = useState("hhhh") useEffect( ()=>{ var obj = document.querySelector("#home_id") console.log("我执行了",obj) return ()=>{ console.log("我是home组件的嵌套函数,我执行了",obj) } },[state] ) const change = ()=>{ setState("hello,我确实是home组件") } const changeHhh = ()=>{ setHhh("哈哈哈") } return <> <p id="home_id" onClick={change}>{state}</p> <p id="home_id" onClick={changeHhh}>{hhh}</p> </> }
useEffict返回的函数通常用来回收内容。
import React, { useEffect,useState } from 'react'; var timer = "" export default function Home(){ let [now,setTime] = useState(Date.now()) useEffect( ()=>{ return ()=>{ clearInterval(timer) console.log("我是home组件的嵌套函数,我执行了") } },[] ) const start= ()=>{ timer = setInterval(()=>{ setTime(Date.now()) },1) } const end=()=>{ clearInterval(timer) } return <> <p>{now}</p> <button onClick={start}>开始</button> <button onClick={end}>停止</button> </> }
useReducer
作用: 可以让函数组件拥有自己的状态数据
-
参数1: 数据处理 函数reducer
-
参数2: 数据默认值
-
返回值: 数组
-
第一个元素: 状态数据对象
-
第二个元素: dispatch数据更新方法, dispatch可以发送一个数据操作对象action给数据处理函数reducer
-
代码如下:
import React, { useReducer } from 'react'; export default function Home() { const reducer = (state, action) => { var data = action.data switch (action.type) { case 'add': var obj = state + data return obj case 'cut': var objs = state - data return objs default: return state } } const [state, dispatch] = useReducer(reducer, 0) const change_add = () => { dispatch({type: 'add',data: 10}) } const change_cut = () => { dispatch({type: 'cut',data: 5}) } return <> <div style={{ width: "200px", margin: "0 auto" }}> <button onClick={change_add}>增加</button> <p>{state}</p> <button onClick={change_cut}>减少</button> </div> </> }
context
在复杂的嵌套情况下,组件之间传参不能很方便,所以需要有一个之间可以传参的方法,就是context
生成消费者模式
consumer(消费者)
第一种写法:
1、导入myContext
2、使用<myContext.Consumer>标签
3、标签内部需要由一个函数接受myContext的数据
4、使用数据
import React, { Component } from 'react' import '../asserts/css/base.css' import Father from './Father' import myContext from '../utils/context' export default class Grandpa extends Component { state={ msg: "先辈参数 abc" } render() { return ( <div className="grandpa"> 我是先辈组件 --- 先辈参数 - {this.state.msg} <br/> <myContext.Consumer> { (context)=>{ console.log(context) return <> { context.list.map(item=>( <p key={item.id}>{item.name}</p> )) } </> } } </myContext.Consumer> <br/> <Father msg={this.state.msg}></Father> </div> ) } }
第二种写法:
import React, { Component } from 'react' import '../asserts/css/base.css' import Father from './Father' import myContext from '../utils/context' export default class Grandpa extends Component { state={ msg: "先辈参数 abc" } static contextType = myContext //contextType固定写法 render() { console.log(this.context) return ( <div className="grandpa"> 我是先辈组件 --- 先辈参数 - {this.state.msg} <br/> { this.context.list.map(item=>( <p key={item.id}>{item.name}</p> )) } <br/> <Father msg={this.state.msg}></Father> </div> ) } }
provider(生产者)
采用<myContext.Provider value={this.state.gList}>传递参数context
自行百度 老师没讲对
确实在子组件当中调用context的结果
项目开始
项目创建
创建项目库
创建项目
安装依赖
npm i events react-router-dom@5.2.0 axios -S
调整结构
修改端口
封装axios
import { Component } from 'react' import axios from 'axios' axios.defaults.baseURL ="/api" axios.interceptors.response.use(response=>{ return response.data }) Component.prototype.$http = axios export default axios
设置跨域
npm install --save-dev http-proxy-middleware@1.0