摘要:組件將元素作為結(jié)果返回。是把數(shù)據(jù)從項(xiàng)目傳到的有效載荷。有以下職責(zé)維持應(yīng)用的提供方法獲取提供方法更新通過(guò)注冊(cè)監(jiān)聽(tīng)器通過(guò)返回的函數(shù)注銷(xiāo)監(jiān)聽(tīng)器。系列目錄前端大統(tǒng)一時(shí)代即將來(lái)臨項(xiàng)目實(shí)戰(zhàn)環(huán)境搭建項(xiàng)目實(shí)戰(zhàn)基本原理項(xiàng)目實(shí)戰(zhàn)登錄頁(yè)面編輯中
React相關(guān)
React 是一個(gè)采用聲明式,高效而且靈活的用來(lái)構(gòu)建用戶界面的框架。
JSX本質(zhì)上來(lái)講,JSX 只是為React.createElement(component, props, ...children)方法提供的語(yǔ)法糖。比如下面的代碼:
const element = (Hello, world!
);
編譯為:
const element = React.createElement( "h1", {className: "greeting"}, "Hello, world!" );
React.createElement()這個(gè)方法首先會(huì)進(jìn)行一些避免bug的檢查,之后會(huì)返回一個(gè)類似下面例子的對(duì)象:
const element = { type: "h1", props: { className: "greeting", children: "Hello, world" } };
這樣的對(duì)象被稱為React元素,它代表所有你在屏幕上看到的東西。
我們用 React 開(kāi)發(fā)應(yīng)用時(shí)一般只會(huì)定義一個(gè)根節(jié)點(diǎn)。要將 React 元素渲染到根DOM節(jié)點(diǎn)中,我們通過(guò)把它們都傳遞給ReactDOM.render()的方法來(lái)將其渲染到頁(yè)面上:
ReactDOM.render( element, document.getElementById("root") );
每當(dāng) React 元素發(fā)生變化時(shí),ReactDOM首先會(huì)比較元素內(nèi)容先后的不同,然后操作瀏覽器DOM更新改變了的部分。
組件 & Props當(dāng) React 遇到的元素是用戶自定義的組件,它會(huì)將 JSX 屬性作為單個(gè)對(duì)象傳遞給該組件,這個(gè)對(duì)象稱之為props。無(wú)論是使用函數(shù)或是類來(lái)聲明一個(gè)組件,它決不能修改它自己的 props 。
例如,這段代碼會(huì)在頁(yè)面上渲染出Hello,Sara:
//使用 ES6 class 來(lái)定義一個(gè)組件,組件名稱必須以大寫(xiě)字母開(kāi)頭。 class Welcome extends React.Component { render() { returnHello, {this.props.name}
; } } const element =; ReactDOM.render( element, document.getElementById("root") );
我們來(lái)回顧一下在這個(gè)例子中發(fā)生了什么:
我們對(duì)
React 將{name: "Sara"}作為props傳入并調(diào)用 Welcome 組件。
Welcome 組件將Hello, Sara
元素作為結(jié)果返回。
ReactDOM 將DOM更新為Hello, Sara
。
組件的通過(guò)props獲取屬性,且其不能修改;當(dāng)我們需要修改當(dāng)前組件的狀態(tài)時(shí),要用到state來(lái)設(shè)置局部狀態(tài),需要通過(guò)this.setState()來(lái)更新組件局部狀態(tài):
class Toggle extends React.Component { constructor(props) { super(props); //初始化this,并賦值this.props this.state = {isToggleOn: true}; //初始化this.state this.handleClick = this.handleClick.bind(this); //為this.handleClick綁定this對(duì)象 } handleClick() { this.setState(prevState => ({ isToggleOn: !prevState.isToggleOn })); //用this.setState()更新this.state } render() { return ( ); } } ReactDOM.render(, document.getElementById("root") );
每一個(gè)組件都有幾個(gè)你可以重寫(xiě)以讓代碼在處理環(huán)節(jié)的特定時(shí)期運(yùn)行的“生命周期方法”。方法中帶有前綴will的在特定環(huán)節(jié)之前被調(diào)用,而帶有前綴did的方法則會(huì)在特定環(huán)節(jié)之后被調(diào)用。
裝配:這些方法會(huì)在組件實(shí)例被創(chuàng)建和插入DOM中時(shí)被調(diào)用:
- constructor(`props`) - componentWillMount() - render() - componentDidMount()
更新:屬性或狀態(tài)的改變會(huì)觸發(fā)一次更新。當(dāng)一個(gè)組件在被重渲時(shí),這些方法將會(huì)被調(diào)用:
- componentWillReceiveProps(`nextProps`) - shouldComponentUpdate(`nextProps`, `nextState`) - componentWillUpdate(`nextProps`, `nextState`) - render() - componentDidUpdate(`prevProps`, `prevState`)
卸載:當(dāng)一個(gè)組件被從DOM中移除時(shí),該方法被調(diào)用:
- componentWillUnmount()
當(dāng)項(xiàng)目視圖交互復(fù)雜且頻繁的時(shí)候,依舊采用 state 進(jìn)行狀態(tài)更改會(huì)顯得異常繁瑣和不可預(yù)測(cè)。
這時(shí)我們就需要借助 Redux 框架,將狀態(tài)數(shù)據(jù)全部轉(zhuǎn)交給 Redux 處理,React 專一負(fù)責(zé)視圖顯示,這樣會(huì)讓項(xiàng)目邏輯變得簡(jiǎn)單而清晰。
三大原則:
整個(gè)應(yīng)用的 state 被儲(chǔ)存在一棵 object tree 中,并且這個(gè) object tree 只存在于唯一一個(gè)store中。
惟一改變 state 的方法就是觸發(fā)action,action 是一個(gè)用于描述事件的普通對(duì)象。
為了描述 action 如何改變 state tree ,你需要編寫(xiě)reducers。
ActionAction 是把數(shù)據(jù)從項(xiàng)目傳到 store 的有效載荷。它是 store 數(shù)據(jù)的唯一來(lái)源。通常你會(huì)通過(guò)store.dispatch()將 action 傳到 store。
Action 本質(zhì)上是 JavaScript 普通對(duì)象,添加新 todo 任務(wù)的 action 是這樣的:
{ type: "ADD_TODO", text: "Build my first Redux app" }
Action 創(chuàng)建函數(shù)就是生成 action 的方法。在 Redux 中的 action 創(chuàng)建函數(shù)只是簡(jiǎn)單的返回一個(gè) action:
function addTodo(text) { return { type: "ADD_TODO", text: text } }
這樣做將使 action 創(chuàng)建函數(shù)更容易被移植和測(cè)試。只需把 action 創(chuàng)建函數(shù)的結(jié)果傳給 dispatch() 方法即可發(fā)起一次 dispatch 過(guò)程。
dispatch(addTodo(text)); //或者創(chuàng)建一個(gè) 被綁定的 action 創(chuàng)建函數(shù) 來(lái)自動(dòng) dispatch: const boundAddTodo = (text) => dispatch(addTodo(text)); boundAddTodo(text);
store 里能直接通過(guò) store.dispatch() 調(diào)用 dispatch() 方法,但是多數(shù)情況下你會(huì)使用 react-redux 提供的connect()幫助器來(lái)調(diào)用。
ReducerAction 只是描述了有事情發(fā)生了這一事實(shí),而reducer要做的事情正是指明應(yīng)用如何更新 state 。reducer 就是一個(gè)純函數(shù),接收舊的 state 和 action,返回新的 state。
(previousState, action) => newState
保持 reducer 純凈非常重要。永遠(yuǎn)不要在 reducer 里做這些操作:
修改傳入?yún)?shù);
執(zhí)行有副作用的操作,如 API 請(qǐng)求和路由跳轉(zhuǎn);
調(diào)用非純函數(shù),如 Date.now() 或 Math.random()。
我們將以指定 state 的初始狀態(tài)作為開(kāi)始。Redux 首次執(zhí)行時(shí),state 為 undefined,此時(shí)我們可借機(jī)設(shè)置并返回應(yīng)用的初始 state:
const initialState = {}; //初始化state function todoApp(state = initialState, action) { switch (action.type) { case "ADD_TODO": return Object.assign({}, state, { text: action.text }) default: return state //在 default 情況下返回舊的 state } }
每個(gè) reducer 只負(fù)責(zé)管理全局 state 中它負(fù)責(zé)的一部分。每個(gè) reducer 的 state 參數(shù)都不同,分別對(duì)應(yīng)它管理的那部分 state 數(shù)據(jù)。
combineReducers()所做的只是生成一個(gè)函數(shù),這個(gè)函數(shù)來(lái)調(diào)用你的一系列 reducer,每個(gè) reducer 根據(jù)它們的 key 來(lái)篩選出 state 中的一部分?jǐn)?shù)據(jù)并處理,然后這個(gè)生成的函數(shù)再將所有 reducer 的結(jié)果合并成一個(gè)大的對(duì)象。
import { combineReducers } from "redux"; const todoApp = combineReducers({ visibilityFilter, todos }) export default todoApp;
注意上面的寫(xiě)法和下面完全等價(jià):
export default function todoApp(state = {}, action) { return { visibilityFilter: visibilityFilter(state.visibilityFilter, action), todos: todos(state.todos, action) } }
StorecombineReducers 接收一個(gè)對(duì)象,可以把所有頂級(jí)的 reducer 放到一個(gè)獨(dú)立的文件中,通過(guò) export 暴露出每個(gè) reducer 函數(shù),然后使用 import * as reducers 得到一個(gè)以它們名字作為 key 的 object:
import { combineReducers } from "redux" import * as reducers from "./reducers" const todoApp = combineReducers(reducers)
action 描述發(fā)生了什么,reducers 根據(jù) action 更新 state,Store就是把它們聯(lián)系到一起的對(duì)象。Store 有以下職責(zé):
維持應(yīng)用的 state;
提供getState()方法獲取 state;
提供dispatch(action)方法更新state;
通過(guò)subscribe(listener)注冊(cè)監(jiān)聽(tīng)器;
通過(guò)subscribe(listener)返回的函數(shù)注銷(xiāo)監(jiān)聽(tīng)器。
我們使用 combineReducers() 將多個(gè) reducer 合并成為一個(gè)。現(xiàn)在我們將其導(dǎo)入,并傳遞 createStore()。
import { createStore } from "redux" import todoApp from "./reducers" let store = createStore(todoApp)
createStore() 的第二個(gè)參數(shù)是可選的, 用于設(shè)置 state 初始狀態(tài)。這對(duì)開(kāi)發(fā)同構(gòu)應(yīng)用時(shí)非常有用,服務(wù)器端 redux 應(yīng)用的 state 結(jié)構(gòu)可以與客戶端保持一致, 那么客戶端可以將從網(wǎng)絡(luò)接收到的服務(wù)端 state 直接用于本地?cái)?shù)據(jù)初始化。
let store = createStore(todoApp, window.STATE_FROM_SERVER);數(shù)據(jù)流
Redux 應(yīng)用中數(shù)據(jù)的生命周期遵循下面 4 個(gè)步驟:
調(diào)用 store.dispatch(action)。
Redux store 調(diào)用傳入的 reducer 函數(shù)。
根 reducer 應(yīng)該把多個(gè)子 reducer 輸出合并成一個(gè)單一的 state 樹(shù)。
Redux store 保存了根 reducer 返回的完整 state 樹(shù)。
Router相關(guān)直接使用整合后的react-router-redux,后面抽時(shí)間再詳細(xì)講一下,具體使用的話模仿官方案例吧,官方文檔。
容器組件 和 展示組件Redux 的 React 綁定庫(kù)包含了 容器組件和展示組件相分離 的開(kāi)發(fā)思想。
明智的做法是只在最頂層組件(如路由操作)里使用 Redux。其余內(nèi)部組件僅僅是展示性的,所有數(shù)據(jù)都通過(guò) props 傳入。
系列目錄前端大統(tǒng)一時(shí)代即將來(lái)臨?
React項(xiàng)目實(shí)戰(zhàn):環(huán)境搭建
React項(xiàng)目實(shí)戰(zhàn):react-redux-router基本原理
React項(xiàng)目實(shí)戰(zhàn):登錄頁(yè)面(編輯中)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/90024.html
摘要:組件將元素作為結(jié)果返回。是把數(shù)據(jù)從項(xiàng)目傳到的有效載荷。有以下職責(zé)維持應(yīng)用的提供方法獲取提供方法更新通過(guò)注冊(cè)監(jiān)聽(tīng)器通過(guò)返回的函數(shù)注銷(xiāo)監(jiān)聽(tīng)器。系列目錄前端大統(tǒng)一時(shí)代即將來(lái)臨項(xiàng)目實(shí)戰(zhàn)環(huán)境搭建項(xiàng)目實(shí)戰(zhàn)基本原理項(xiàng)目實(shí)戰(zhàn)登錄頁(yè)面編輯中 React相關(guān) React 是一個(gè)采用聲明式,高效而且靈活的用來(lái)構(gòu)建用戶界面的框架。 JSX 本質(zhì)上來(lái)講,JSX 只是為React.createElement(co...
摘要:官方文檔中文翻譯構(gòu)建用戶界面的庫(kù)。官方文檔建議學(xué)習(xí)時(shí)以官方文檔為準(zhǔn),中文翻譯或者第三方作者的教程可以幫助你理清思路會(huì)用到的重要知識(shí)點(diǎn)我也會(huì)進(jìn)行簡(jiǎn)明的解釋,如遇到錯(cuò)誤或者不理解的內(nèi)容,歡迎實(shí)時(shí)指出。 前言 前面提到前端大統(tǒng)一的概念,如果感興趣,歡迎說(shuō)說(shuō)自己的看法,點(diǎn)擊前往。Web前端框架層出不窮,不可能面面俱到,這里給個(gè)小建議: 如果對(duì)Weex App感興趣,應(yīng)該選擇vue框架; 如果...
摘要:官方文檔中文翻譯構(gòu)建用戶界面的庫(kù)。官方文檔建議學(xué)習(xí)時(shí)以官方文檔為準(zhǔn),中文翻譯或者第三方作者的教程可以幫助你理清思路會(huì)用到的重要知識(shí)點(diǎn)我也會(huì)進(jìn)行簡(jiǎn)明的解釋,如遇到錯(cuò)誤或者不理解的內(nèi)容,歡迎實(shí)時(shí)指出。 前言 前面提到前端大統(tǒng)一的概念,如果感興趣,歡迎說(shuō)說(shuō)自己的看法,點(diǎn)擊前往。Web前端框架層出不窮,不可能面面俱到,這里給個(gè)小建議: 如果對(duì)Weex App感興趣,應(yīng)該選擇vue框架; 如果...
該demo使用的是webpack2.*來(lái)配置的,很多配置項(xiàng)都產(chǎn)生了變化,踩了不少坑.目前還在逐步完善中,webpack是一部一部配置來(lái)的。后端數(shù)據(jù)使用nodejs來(lái)開(kāi)發(fā)模擬。GitHub項(xiàng)目地址。 showImg(https://segmentfault.com/img/remote/1460000009665620); 歡迎大家提問(wèn)題。
摘要:項(xiàng)目地址項(xiàng)目預(yù)覽登錄流負(fù)責(zé)全局的登錄狀態(tài)管理。總體思想所有的組件都盡量是所有的狀態(tài)組件一般都是路由組件。所有的分發(fā)都交給了路由組件來(lái)完成。數(shù)據(jù)的獲取有兩種方式。一種是官方推薦的使用在訂閱數(shù)據(jù)源。 項(xiàng)目地址 https://github.com/HeskeyBaoz... 項(xiàng)目預(yù)覽 showImg(https://segmentfault.com/img/bVIQHX?w=1249&h=...
閱讀 3029·2021-11-18 10:07
閱讀 3778·2021-11-17 17:00
閱讀 2108·2021-11-15 18:01
閱讀 936·2021-10-11 10:58
閱讀 3387·2021-09-10 10:50
閱讀 3453·2021-08-13 15:05
閱讀 1232·2019-08-30 15:53
閱讀 2657·2019-08-29 13:01