day24笔记
一、Redux
Redux 是 JavaScript 状态容器,提供可预测化的状态管理.
1.单一数据源(state)
整个应用状态,都应该被存储在单一store的对象树中。
2.只读状态
唯一可以修改状态的方式,就是发送(dispatch)一个动作(Action),通俗来讲,就是说只有getter,没有setter。
3.使用纯函数去修改状态(Reducer)
(其实就是一个函数返回{})
- Redux 的设计思想
(1)Web 应用是一个状态机,视图与状态是一一对应的。
(2)所有的状态,保存在一个对象里面。
- 下载方式
npm install(i) redux
“redux”: “^4.0.5” - 创建一个仓库(基本的取值过程)
//1、引入创建仓库的方法
import { createStore } from 'redux'
//2、初始化一个state状态
const initState = {
msg: '人生若只如初见'
}
//3、创建一个 reducer纯函数 这个函数有两个参数,第一个参数是state,第二个参数是action 行动 action行动中可定有type类型
function reducer(state = initState, action) {
switch (action.type) {
case 'a':
return {
...state
}
default:
return state
}
}
// 4、建一个仓库
const state = createStore(reducer)
//6、封装一个类似getter
export const getMsg = () => state.getState().msg
//5、暴露出当前的state
export default state
- 修改仓库状态(index.js)
//1、引入创建仓库的方法
import { createStore } from 'redux'
//2、初始化一个state状态
const initState = {
msg: '人生若只如初见',
num:5
}
//7、创建一个行动,并暴露 行动action必须有一个属性叫type
/* export const changeMsgAction = (msg)=>{
return{
type:'changeMsg',
msg:msg
}
}
*/
export const changeMsgAction = (msg)=>({
type:'changeMsg',
msg
})
export const changeNumAction =()=>({
type:'changeNum'
})
//3、创建一个 reducer纯函数 这个函数有两个参数,第一个参数是state,第二个参数是action 行动 action行动中可定有type类型
function reducer(state = initState, action) {
console.log(action,'switch中的action')
switch (action.type) {
case 'changeMsg':
return {
...state,
msg:action.msg
}
case 'changeNum':
return {
...state,
num:state.num +1
}
default:
return state
}
}
// 4、建一个仓库
const store = createStore(reducer)
//6、封装一个类似getter
export const getMsg = () => store.getState().msg
export const getNum = ()=>store.getState().num
//5、暴露出当前的state
export default store
- one.js(取值并修改状态的案例)
import React from 'react'
import Store, { getMsg,changeMsgAction,getNum } from '../../store'
class One extends React.Component {
constructor(){
super()
this.state = {
msg:'那还不如不见'
}
}
//组件一加载就调取监听方法(订阅者模式subscribe)
componentDidMount(){
Store.subscribe(()=>{
this.setState({})
})
}
//改变state的事件
changeMsg(msg){
Store.dispatch(changeMsgAction(msg))
}
render() {
const {msg} = this.state
return (
<div className="box">
<h1>我是组件一</h1>
<button onClick={this.changeMsg.bind(this,msg)}>我想要修改这首诗</button>
<h1>我是直接从state中取值----{Store.getState().msg}</h1>
<h1>取封装之后的state---{getMsg()}</h1>
<hr/>
<h1>当前的数量是--{getNum()}</h1>
</div>
)
}
}
export default One
二、React-Redux(类的创建方式)
- React-Redux 将所有组件分成两大类:UI 组件(presentational component)和容器组件(container component)
- UI组件
只负责 UI 的呈现,不带有任何业务逻辑
没有状态(即不使用this.state这个变量)
所有数据都由参数(this.props)提供
不使用任何 Redux 的 API
- 容器组件
负责管理数据和业务逻辑,不负责 UI 的呈现
带有内部状态
使用 Redux 的 API
- 下载并安装 React-Redux
npm install(i) react-redux
“react-redux”: “^7.2.0”,
三、Redux-thunk (中间件)
- 下载命令并安装
npm install redux-thunk
//版本号是
"redux-thunk": "^2.3.0"
四、获取动态列表案例
- 清空创建项目
- 准备数据,并且在浏览器中测试,数据可以获取
- 创建组件和路由
npm i react-router-dom
- 把一级路由创建出来并可以渲染
- index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//引入浏览器解析路由的插件
import {BrowserRouter} from 'react-router-dom'
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.getElementById('root'));
- app.js
import React from 'react';
import './App.css';
import List from './components/list'
import {Switch,Route,Redirect} from 'react-router-dom'
function App() {
return (
<div className="App">
<Switch>
<Route path='/list' component={List}></Route>
<Redirect to='/list'></Redirect>
</Switch>
</div>
);
}
export default App;
- 创建一个redux 并导出一个name(npm i redux)
//引入创建仓库的方法
import {createStore} from 'redux'
//初始化state
const initState={
name:'李白'
}
//创建一个reducer
function reducer(state=initState,action){
switch (key) {
case 'a':
return state
default:
return state
}
}
const store = createStore(reducer)
//暴露出name数据
export const getName = ()=>store.getState().name
export default store
- 创建一个React-redux(npm i react-redux)
- index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
//引入浏览器解析路由的插件
import {BrowserRouter} from 'react-router-dom'
//引入React-redux
import { Provider} from 'react-redux'
//全局引入Redux
import store from './store'
ReactDOM.render(<Provider store={store}><BrowserRouter><App /></BrowserRouter></Provider>, document.getElementById('root'));
- 封装list组件
- list.js
import React from 'react'
//应用React-redux 拆分成两部分
import { connect } from 'react-redux'
//从redux中取出你需要的数据(API)
import { getName,getList, changNameAction } from '../store'
class List extends React.Component {
render() {
const { name,changeName,musicList } = this.props
console.log(musicList,'musicList')
return (
<div>
<h1>这是音乐列表</h1>
<h1>姓名:{name}</h1>
<button onClick={changeName.bind(this,'白居易')}>点击更换名字</button>
</div>
)
}
}
//定义一个函数 函数作用是从仓库中去出state值
const mapStateToProps = () => {
return {
name: getName(),
musicList:getList()
}
}
//定义一个函数 函数的作用是从仓库中(dispatch)触发action
const mapDispatchToProps = (dispatch)=>{
return {
changeName:(name)=>dispatch(changNameAction(name))
}
}
export default connect(mapStateToProps,mapDispatchToProps)(List)
- 封装接口
- util=>axiosConfig.js =>axios.js
//axiosConfig
import axios from 'axios'
let http = axios.create()
http.interceptors.request.use(config=>{
return config
})
http.interceptors.response.use(res=>{
return res
})
export default http
//axios
import http from './axiosConfig'
let getData ={}
//封装一个音乐列表接口
getData.getMusic = ()=>{
return http.get('/mock/music.json')
}
export default getData
- 仓库中异步调取接口
- index.js(仓库)
//引入创建仓库的方法 并引用应用中间件的方法
import {createStore,applyMiddleware} from 'redux'
//引入type类型
import {CHANGE_NAME,CHANGE_LIST} from './type'
//引入redux-thunk中间件
import thunk from 'redux-thunk'
//引入封装好的接口文件
import api from '../util/axios'
//初始化state
const initState={
name:'李白',
list:[]
}
//修改名字
export const changNameAction =(name)=>{
return {
type:CHANGE_NAME,
name
}
}
//修改list列表的函数(同步 这段相当于mutation)
const changeList = (list)=>{
return {
type:CHANGE_LIST,
list
}
}
//导出一个获取list列表(创建一个异步函数)
export const reqListAction = ()=>{
return (dispatch,getState)=>{
//数据缓存
if(getState().list.length>0){
return
}
//调取音乐接口列表
api.getMusic()
.then(res=>{
console.log(res,'仓库中取列表')
return dispatch(changeList(res.data.data))
})
.catch(err=>{})
}
}
//创建一个reducer
function reducer(state=initState,action){
switch (action.type) {
case CHANGE_NAME://修改名字
return {
...state,
name:action.name
}
case CHANGE_LIST://修改列表
return {
...state,
list:action.list
}
default:
return state
}
}
//导出仓库 并使用redux-thunk中间件
const store = createStore(reducer,applyMiddleware(thunk))
//暴露出name数据
export const getName = ()=>store.getState().name
//暴露出列表
export const getList = ()=>store.getState().list
export default store
- 封装一个type模块
- type.js(抽离出这个模块,好处一次修改多次应用)
//导出一个修改名字的类型
export const CHANGE_NAME = 'changeName'
export const CHANGE_LIST = 'changeList'