react_結合 redux - 高階函數 - 高階組件 - 前端、後臺項目打包運行

 

 

Redux 獨立的集中式狀態管理 js 庫 - 參見 My Git前端

不是 react 庫,能夠與 angular、vue 配合使用,一般和 react 用vue

yarn add reduxreact

import {createStore} from "redux"git

const store = createStore(myCounter);    // 1. 核心 API - 參數是 reducer 函數---> 根據現有的狀態及 action 返回一個新的狀態,給 store 管理github

import {INCREMENT, DECREMENT} from "./action-types"    // 有幾個 case,就要定義幾個 action 工廠chrome

export default function myCounter(state=0, action){    // 由 store 內部調用,初始值爲 0 ./redux/reducers編程

switch(action.type){    // action 必定要有一個 type 屬性redux

case INCREMENT:{return state+action.numbe;brack;}跨域

case INCREMENT:{return state+action.numbe;brack;}服務器

default: return state

}

}

<App store={store}

 

import {INCREMENT, DECREMENT} from "./action-types"

export const INCREMENT = "increment";

export const DECREMENT = "decrement";

import * as actions from "../redux/actions";

this.props.store.dispatch(actions.increment(number));    // action creator 產生一個 action 對象,而後 dispatch 這個行爲 action

// 雖然等同於 this.props.store.dispatch({type: INCREMENT, number}); 可是通常不這麼作

// 工廠函數 - 每次調用,返回一個新的對象 - 每次都返回一個 actions

this.props.store.getState();

  • action

若是是 對象,則是 同步 action ---- 返回一個對象,描述行爲、state 參數

export const menuTitle = (menuTitle)=>({tyle: SETMENUTITLE, data: menuTitle})

若是是 函數,則是 異步 action

返回一個 函數,該函數接收一個 dispatch 參數

該函數內部進行異步操做,有告終果之後,再 dispatch 同步 action

export const login = ()=>{

return dispatch=>{

// 1. 執行異步代碼

const result = await requestLogin(username, password);

// 2. 分發同步 action

if(result.status === 0){

 

}else{

 

}

}

}

  • reducer

根據現有的 state 和 action 生成新的 state

  • const store = createStore(myReducer)    // 根據 n 個現有須要管理的 state 和 action 返回一個新的 state,給 store 集中管理
  • store 最核心的 管理對象---- 與 react 的交互就是 更新

存儲狀態數據的對象

維護着 state 和 reducer

核心方法

  • 獲取狀態 store.getState()        
  • 更新狀態 store.dispatch(action-creator)   

對象 action

  • 必須有 type 標識屬性,值爲字符串
  • 可選數據屬性,值爲任意類型
  • 訂閱一個監聽函數 subscribe(listener)

何時用 redux?

某個組件的狀態須要共享

一個組件須要改變全局狀態

一個組件須要改變另外一個組件的狀態

整體原則: 能不用就不用,若是不用比較吃力才考慮使用

不用 redux 時的集中狀態管理?

將多個組件的共用狀態放在共同的父組件中

將狀態的相關方法定義在與狀態相同的組件中

官方實例分析?

redux 編程:

---------------------------------------------------------------------------------------------------------

src/redux/store.js

import {createStore} from "redux"

import reducer from "./reducer"

export default creareStore(reducer);    // 建立 store 對象,內部會第一次自調用 reducer 函數獲得一個初始的狀態值進行保存

---------------------------------------------------------------------------------------------------------

src/redux/reducer.js

import {INCREMENT, DECREMENT} form "./action-types"

export default  function count(state=1 action){    // 管理 count 就能夠叫 count,state 自己就是要管理的數據,第一次展現顯示 1

switch(action.type){

case INCREMENT:{return state+action.number;}

case INCREMENT:{return state-action.number;}

default: return state;    // 不作任何處理

}

}

---------------------------------------------------------------------------------------------------------

src/redux/actions.js    // 包含 n 個 action-creator 函數

import {INCREMENT, DECREMENT} form "./action-types"

export const increate = (number)=>({type: INCREMENT, number});

export const decreate = (number)=>({type: DECREMENT, number});

---------------------------------------------------------------------------------------------------------

src/redux/action-types.js    // 多個 js 共用

export const INCREMENT = "increment";

export const DECREMENT = "decrement";

---------------------------------------------------------------------------------------------------------

src/index.js

import React from "react"

import ReactDOM from "react-dom"

import App from "./App.jsx"

import store from "./redux/store"

ReactDOM.render(<App store={store} />, document.getElementById("root"));

store.subscribe(()=>{

ReactDOM.ummountComponentAtNode(document.getElementById("root"));    // 先卸載原來的組件

ReactDOM.render(<App store={store} />, document.getElementById("root"));

})

---------------------------------------------------------------------------------------------------------

src/App.jsx

import React, {PureComponent} from "react"

import * as actions from "./redux/actions"

export default class App extends PureComponent{

increment = ()=>{

const number = +this.refs.numberSelect.value;

this.props.store,dispatch(actions.increment(number));

}

decrement = ()=>{

const number = +this.refs.numberSelect.value;

this.props.store,dispatch(actions.decrement(number));

}

render(){

const count = this.props.store.getState();

}

}

問題: react 與 redux 耦合度太強了,直接使用了 store

解決: 使用 react 的插件庫 react-redux ---- 簡化 react 中使用 redux

----------------------------------------- react 與 redux 的鏈接--------------------------------------------

Provider

向全部容器組件提供 store

connect(生成 容器組件,負責向 UI 組件傳遞標籤屬性

第一參數: 函數 ---- 通常屬性從 state 中獲取

state=>({title: state.menuTitle})

第二參數: 原始函數/簡寫對象{actionCreator1, action2}---- 函數屬性,執行 dispatch 分發 action-creator

)(UI組件)

---------------------------------------------------------

src/index.js

import React from "react"

import ReactDOM from "react-dom"

import App from "./App.jsx"

import store from "./redux/store"

import {Provider} from "react-redux"

-------------------------------------------------------------------------------------------------------------------

src/App.jsx

import React, {PureComponent} from "react"

import {connect} from 'react-redux'

imoprt Counter from "./components/Counter"

imoprt {increment, decrement]} from "./redux/actions"

function mapStateToProps(state){    // 讀取 state 數據,並將其映射成 UI 組件的通常屬性

return {count: state}

}

function mapDispatchToProps(dispatch){    // 爲 UI 組件映射函數屬性,函數內部必須 dispatch,分發 action,產生新的 state,從新 render

return {

incremrnt: number=>dispatch(increment(number))

decremrnt: number=>dispatch(decrement(number))

}

}

 

export default connect(

mapStateToProps,    // 用來肯定向 UI 組件傳遞哪一些通常屬性 count

mapDispatchToProps    // 用來肯定向 UI 組件傳遞哪些函數屬性 increment、decrement

)(Counter)        // 用 connect 函數包裝一下 App 組件,返回一個新的組件對象

-------------------------------------------------------------------------------------------------------------------

src/components/Counter.jsx

1

react-redux 將組件分爲

UI 組件

不會使用任何 redux 相關的語法

最終,值仍是要被 store 管理的 ,getState()、dispatch()、

容器組件: 經過 connect 包裝 UI 組件生成的組件,內部能夠看見 store

1. 向 UI 組件傳遞通常屬性,屬性值 會以 state 傳遞

傳遞 狀態 以及操做 store  的相關函數到 reducer 中

2. 屬性值函數內部必然執行 dispatch 去分發 action

最終的簡潔寫法-------------------------------------------------------------------------------------

redux 異步編程

下載 異步中間件 yarn add redux-thunk

store.js

import thunk from "redux-thunk"    // 中間件,擴展 redux 使其能夠 action-creator 能夠返回 函數

import {createStore, applyMiddleware} from "redux"

import reducer from "./reducer"

export default createStore(reducer, applyMiddleware(thunk));

actions.js 紅中增長 異步 action  

返回的是一個函數,函數會接收一個參數:dispatch

dispatch函數能夠執行異步代碼, 有告終果,再分發一個同步的 action

export const increment = (number)=>({type:"increment", number})

export const incrementAsync = number=>{

return dispatch=>{

setTimeout(()=>{

dispatch(increment(number))

}, 1000)

}

}

redux 與 chrome 調試工具

yarn add redux-devtools-extension

 

 combineReducers()

純函數 ---- 一樣的輸入,獲得一樣的輸出

不得修改參數    {...state, username: "test"}

不得調動 系統 I/O 的 API

不能調動不純的 Date.now()  或者 Math.random() 等函數

高階函數 ---- 參數是函數 或者 返回值是函數

filter、map、addEventListener、

高階組件 ---- 函數接收一個組件,產生的新組件

connect

前端項目 和 後臺服務器項目 各自獨立運行

會產生 資源未找到 或者 跨域

  • 須要 後臺工程師 進行代理服務器配置
  • 或者 將 前端項目 和 後臺服務器項目 合併

前端項目 置於 後臺服務器項目的 public

問題:

BrowserRouter 傳遞 state ---- 以至於訪問 被置爲後臺路由處理了

解決: 

自定義中間件處理

 

後臺沒有一個頁面可以處理時,查看是否有前臺頁面能夠返回

前臺路由路徑 不能與 後臺路由路徑 同樣

 專門的組件頁面 應對 404 和 500 頁面

相關文章
相關標籤/搜索