摘要:上一篇也許是最佳小實踐加入在組件之間流通數(shù)據(jù)更確切的說,這被叫做單向數(shù)據(jù)流數(shù)據(jù)沿著一個方向從父組件流到子組件。這個將這個新的對象附加到上,并將它返回,用來更新。這一次,將當(dāng)前的狀態(tài)仍舊是空數(shù)組和對象一起傳遞給了。
上一篇:react、react-router、redux 也許是最佳小實踐1
加入 reduxReact 在組件之間流通數(shù)據(jù).更確切的說,這被叫做“單向數(shù)據(jù)流”——數(shù)據(jù)沿著一個方向從父組件流到子組件。由于這個特性,對于沒有父子關(guān)系的兩個組件之間的數(shù)據(jù)交流就變得不是那么顯而易見。這里 Redux 就排上用場了。Redux提供了一個解決方案,通過將應(yīng)用程序所有的狀態(tài)都存儲在一個地方,叫做“store”。然后組件就可以“dispatch”狀態(tài)的改變給這個store,而不是直接跟另外的組件交流。所有的組件都應(yīng)該意識到狀態(tài)的改變可以“subscribe”給store。如下圖:
原理講完,下面開始加入代碼。
先看看一個小例子。
開始之前,需要先用 Redux.createStore() 創(chuàng)建一個store,然后將所有的reducer作為參數(shù)傳遞進(jìn)去,讓我們看一下這個只傳遞了一個reducer的小例子:
var userReducer = function(state, action) { if (state === undefined) { state = []; } if (action.type === "ADD_USER") { state.push(action.user); } return state; } var store = Redux.createStore(userReducer); store.dispatch({ type: "ADD_USER", user: {name: "xiaoming"} });
上面的程序干了些什么呢:
這個store只由一個reducer創(chuàng)建。
這個reducer 初始化狀態(tài)的時候使用了一個空數(shù)組 。*
在被分派的這個action里面使用了新的user對象。
這個reducer將這個新的user對象附加到state上,并將它返回,用來更新store。
*在這個例子里reducer實際上被調(diào)用了兩次 —— 一次是在創(chuàng)建store的時候,一次是在分派action之后。
當(dāng)store被創(chuàng)建之后,Redux立即調(diào)用了所有的reducer,并且將它們的返回值作為初始狀態(tài)。第一次調(diào)用reducer傳遞了一個 undefined 給state。經(jīng)過reducer內(nèi)部的代碼處理之后返回了一個空數(shù)組給這個store的state作為開始。
所有的reducer在每次action被分派之后都會被調(diào)用。因為reducer返回的狀態(tài)將會成為新的狀態(tài)存儲在store中,所以 Redux總是希望所有的reducer都要返回一個狀態(tài)。
在這個例子中,reducer第二次的調(diào)用發(fā)生在分派之后。記住,一個被分派的action描述了一個改變狀態(tài)的意圖,而且通常攜帶有數(shù)據(jù)用來更新狀態(tài)。這一次,Redux將當(dāng)前的狀態(tài)(仍舊是空數(shù)組)和action對象一起傳遞給了reducer。這個action對象,現(xiàn)在有了一個值為1ADD_USER的type屬性, 讓reducer知道怎樣改變狀態(tài)。
正式redux登場在 src 下面創(chuàng)建一個 redux、actions、 data(存放一些初始數(shù)據(jù))文件夾,然后在 data文件夾下面創(chuàng)建一個db.js,這個文件寫上一些初始的數(shù)據(jù):
src/data/db.js
const data = [ { id: 1, title: "明天要去打醬油", content: "系呀系呀我們一起打醬油" }, { id: 2, title: "周末去書吧讀書", content: "書籍是人類進(jìn)步的階梯" }, { id: 3, title: "備份一下數(shù)據(jù)庫", content: "備份服務(wù)器的數(shù)據(jù)庫,一般都是分開的,分布式數(shù)據(jù)庫" }, { id: 4, title: "周五記得把被子洗了", content: "洗杯子被子被子被子" }, { id: 5, title: "計劃五", content: "計劃五內(nèi)容" } ] export default data
好了,初始的數(shù)據(jù)我們有了,下面就是創(chuàng)建 store 了,在redux文件夾下面,創(chuàng)建一個planlist.js文件,這個文件就是操作 store 的動作 action集合處理的數(shù)據(jù),這時候我們會去action文件夾下面新建,action-type.js 和plan.js,代碼如下:
src/action/action-type.js
export const ADD = "ADD"; export const DELECT = "DELECT"; export const SHOW = "SHOW";
src/action/plan.js
import * as types from "./action-type.js"; // 添加計劃 export function addPlan(item) { return { type: types.ADD, item }; } // 刪除計劃 export function deletePlan(id) { return { type: types.DELECT, id }; } // 顯示隱藏彈層 export function show(show) { return { type: types.SHOW, show }; }
action 我們都定義好了現(xiàn)在我們就可以改變 store了。寫好我們的 reducer
src/redux/planlist.js
import * as types from "../actions/action-type.js"; import data from "../data/db.js" const initialState = { show: false, // 是否顯示彈出 planlist: data // 初始的計劃表 }; const planReducer = function(state = initialState, action) { let list = state.planlist; switch(action.type) { // 添加計劃 case types.ADD: list.push(action.item); return Object.assign({}, state, { planlist: list }); // 刪除計劃 case types.DELECT: let newstate = list.filter((item) => item.id != action.id); return Object.assign({}, state, { planlist: newstate });; // 顯示、隱藏彈出層 case types.SHOW: return Object.assign({}, state, { show: action.show }); } return state; } export default planReducer;
在redux 下面再創(chuàng)建reducers.js和store.js,
src/redux/reducers.js
import { combineReducers } from "redux"; // Reducers import planlist from "./planlist"; // Combine Reducers var reducers = combineReducers({ planlist: planlist }); export default reducers;
src/redux/store.js
import { createStore } from "redux"; import reducers from "./reducers.js"; const store = createStore(reducers); export default store;
這會我們的 store 就完全的創(chuàng)建好了,下面就是把 store 跟我們的組件,完全的結(jié)合起來。這就用到 react-redux 的 connect 模塊。
這個東西 就是把組件跟 store 連接起來的模塊。
然后在,App.js加入我們的。store
src/App.js
import React, { Component } from "react" import { BrowserRouter as Router, Route, Link } from "react-router-dom" // 引入 store import { Provider, connect } from "react-redux"; import store from "./redux/store.js" import logo from "./logo.svg" import Plan from "./components/plan.js" import Home from "./components/home.js" import Popup from "./components/pupop.js" import TestRouter from "./components/testrouter.js" import Detail from "./components/detail.js" import "./App.css" import "./components/comment.css" import createHistory from "history/createBrowserHistory" const history = createHistory() class App extends Component { constructor(props) { super(props); } render() { return ( // store的掛載); } } export default App Welcome to React Plan
- 首頁
- 計劃表
- 二級路由
然后在 plan.js連接 store
src/component/plant.js
import React, { Component } from "react" import { connect } from "react-redux"; import store from "../redux/store.js"; // 引入 定義的 action import {show, deletePlan} from "../actions/plan.js"; class Plan extends Component { constructor(props) { super(props); } // 顯示彈出 show () { let b = this.props.planlist.show; store.dispatch(show(!b)); } // 刪除計劃 delete (id) { store.dispatch(deletePlan(id)); } // js 跳轉(zhuǎn)路由 detail (id) { this.props.history.push(`/detail/${id}`) } render () { return () } } const mapStateToProps = function(store) { return { planlist: store.planlist }; }; // 連接 store,作為 props export default connect(mapStateToProps)(Plan);計劃表
添加計劃
{ this.props.planlist.planlist.map((item, index) => { return ( 標(biāo)題 操作 ) }) } {item.title} 刪除
同理下面的 js,都是用這個模塊連接
src/component/detail.js
import React, { Component } from "react" import { connect } from "react-redux"; import store from "../redux/store.js"; class Detail extends Component { constructor(props) { super(props); // 根據(jù)路由 id 跟 store 做過濾 let item = props.planlist.planlist.filter((data) => data.id == props.match.params.id) console.log(item) this.state = { plan: item[0] } } render() { return () } } const mapStateToProps = function(store) { return { planlist: store.planlist }; }; // 連接 tore 和組件 export default connect(mapStateToProps)(Detail);計劃詳情
id: {this.state.plan.id}
標(biāo)題: {this.state.plan.title}
內(nèi)容: {this.state.plan.content}
src/component/popup.js
import React, { Component } from "react" import { connect } from "react-redux"; import store from "../redux/store.js"; import {show, addPlan} from "../actions/plan.js"; class Pupop extends Component{ constructor (props) { super(props) this.state = { id: "", title: "1", content: "1" } } // 取消按鈕操作 close () { let b = this.props.planlist.show; this.setState({ id: "", title: "", content: "" }) store.dispatch(show(!b)); } // 輸入框事件 handleChage (str, e) { this.setState({ id: Math.ceil(Math.random()*10000), [str]: e.target.value }) } // 確認(rèn)操作 conform () { store.dispatch(addPlan(this.state)); this.setState({ id: "", title: "", content: "" }) this.close(); } render() { let self = this; return () } } const mapStateToProps = function(store) { return { planlist: store.planlist }; }; // 連接 store和組件 export default connect(mapStateToProps)(Pupop); X計劃標(biāo)題
計劃內(nèi)容
取消 確認(rèn)
完工。github地址
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/83408.html
摘要:通過聲明式編程模型定義組件,是最強大的核心功能。無論是的瀏覽器書簽,還是的導(dǎo)航功能,只要是可以使用的地方,就可以使用。二級路由使用渲染組件屬性狀態(tài)請選擇一個主題。也許是最佳小實踐地址,覺得有幫助的話,請點擊一下,嘿嘿 小前言 這是一個小小的有關(guān)react的小例子,希望通過一個小例子,可以讓新手更好的了解到react、react-router4.0、redux的集中使用方法。 這是基...
摘要:譯者按最近依舊如火如荼相信大家都躍躍欲試我們團(tuán)隊也開始在領(lǐng)域有所嘗試年應(yīng)該是逐漸走向成熟的一年讓我們一起來看看國外的開發(fā)者們都總結(jié)了哪些最佳實踐年在全世界都有很多關(guān)于新的更新和開發(fā)者大會的討論關(guān)于去年的重要事件請參考那么年最有趣的問題來了我 譯者按:最近React(web/native)依舊如火如荼,相信大家都躍躍欲試,我們團(tuán)隊也開始在React領(lǐng)域有所嘗試. 2016年應(yīng)該是Reac...
摘要:首先聲明這篇文章是想說明一下最新版本的的新特性帶來的極大的開發(fā)體驗提升而不是如何利用開發(fā)應(yīng)用這個特性就是對的支持在的中有說明具體可以參考這里在版本之前我們在開發(fā)應(yīng)用尤其是在配合一類庫的時候經(jīng)常用到諸如之類的封裝而這些函數(shù)其實都可以用裝飾器的 首先聲明, 這篇文章是想說明一下最新版本的 TypeScript(3.0) 的新特性帶來的極大的 React 開發(fā)體驗提升. 而不是如何利用 Ty...
閱讀 1369·2021-11-15 11:45
閱讀 3136·2021-09-27 13:36
閱讀 2880·2019-08-30 15:54
閱讀 999·2019-08-29 12:38
閱讀 2920·2019-08-29 11:22
閱讀 2999·2019-08-26 13:52
閱讀 2043·2019-08-26 13:30
閱讀 599·2019-08-26 10:37