摘要:在我看來它們的關(guān)系不會(huì)比共用開頭更深了,所以我就重新開了一個(gè)頭,但其實(shí)是基于前面寫的資源中文文檔英文文檔官方視頻學(xué)習(xí)歷程當(dāng)初為了學(xué)習(xí),看了許多的材料,中途曾經(jīng)放棄兩次,但是最后還是勇敢的拿起了它,現(xiàn)在終于勉強(qiáng)弄懂。
0x000 概述
這一章開始講redux,其實(shí)是承接前面的react,但其實(shí)作為一個(gè)框架來說,redux和react并沒有太多的關(guān)系,本身是獨(dú)立存在的。在我看來它們的關(guān)系不會(huì)比共用re開頭更深了,所以我就重新開了一個(gè)頭,但其實(shí)是基于前面寫的...
0x001 redux資源中文文檔
英文文檔
官方視頻
0x002 學(xué)習(xí)歷程當(dāng)初為了學(xué)習(xí)redux,看了許多的材料,中途曾經(jīng)放棄兩次,但是最后還是勇敢的拿起了它,現(xiàn)在終于勉強(qiáng)弄懂。
第一次是大家都說redux牛逼,所以就打算學(xué)習(xí)一下,看了許多遍了redux中文文檔,也看了英文文檔--因?yàn)橛行?b>demo總是跑的不成功,怕是中文更新不及時(shí)的原因。但最后還是不了了之,因?yàn)椴恢烙盟鼇砀缮?,反倒弄出了一堆?b>reducer、action之類的東西。
第二次是在做畢業(yè)設(shè)計(jì)的時(shí)候,做了一個(gè)類似看板一樣的api自動(dòng)測試及性能統(tǒng)計(jì)分析項(xiàng)目--類似postman,在這里遇到了一些超級棘手的問題,其中的最大的問題就是組件間通信和統(tǒng)一的狀態(tài)管理。因?yàn)槭怯幸粋€(gè)超級復(fù)雜的組件操作方式和組件嵌套,在做組件間通信的時(shí)候,為了保持狀態(tài)的一致性,不斷的將事件和屬性一層一層往下傳、或者往上傳。真是糟糕的回憶啊....... 當(dāng)時(shí)用的是Angular2。而我為了解決這個(gè)問題,寫了一套基于訂閱-發(fā)布模式的事件通知框架,原本想解決這些問題,結(jié)果,確實(shí)解決了組件間通訊和統(tǒng)一狀態(tài)管理的問題,但是最終帶來的確實(shí)更加復(fù)雜的事件管理和更加無無序的組件關(guān)系....
后來使用vue+vuex做了一些項(xiàng)目,反倒是突然領(lǐng)悟的redux的思想,就開始了第三次的學(xué)習(xí),直到現(xiàn)在,我覺稍微緩解了我在前端項(xiàng)目所受到的傷害,redux的文檔有點(diǎn)像上帝視角,他好像在說,我知道你應(yīng)該知道的,所以我這么說你應(yīng)該懂得,其實(shí)我不懂。所以我要從凡人視角說說redux,扒開他的神袍,看看他的胸毛......
0x003 再說一些廢話在前面react的文章中,我一直在重復(fù)react中都是js,就是為了把思想引回react的本質(zhì),react是基于js寫的一個(gè)框架而已,只是一個(gè)框架,并不是一門獨(dú)立的語言。很多人總是用了jQuery就忘了原生,用了React就忘了jQuery和原生。而來了redux,就必須和react綁定。這是一個(gè)極大的思想誤區(qū),從個(gè)體上來說,vue是獨(dú)立的、自由的,react也是獨(dú)立的、自由的,redux也是獨(dú)立的、自由的。
的確有redux在react中的最佳實(shí)踐,卻絕對沒有redux的唯一實(shí)踐這種說法,在js的世界中,各大框架各放異彩,他們既可以兼容并濟(jì),也可以相互排斥,不過就是js中的一員罷了。每個(gè)框架就像每個(gè)人一樣,有自己的特點(diǎn),react可以構(gòu)建ui,redux能夠管理狀態(tài),axios在行網(wǎng)絡(luò),angular啥都行!你可以在vue中使用redux,也可以在vue中使用jQuery,甚至也可在你自己的項(xiàng)目中同時(shí)使用vue和react,語言也好,框架也罷,都是為了向偉大航線進(jìn)發(fā)而服務(wù)的。
一句話總結(jié):自由,然后秩序,接著是世間萬物。
0x004 訂閱-發(fā)布模式redux本質(zhì)上也是基于訂閱-發(fā)布模式的產(chǎn)物(我記得沒錯(cuò)的話,如果記錯(cuò)了,之后回來改),和我寫的那個(gè)小框架一樣.....,所以在使用redux之前,先來研究一下這個(gè)模式,看看我之前寫的那個(gè)小東西:
let eventMap = {} class MyEvent { /** * 發(fā)布一個(gè)事件并附帶一份數(shù)據(jù) * * @param name 發(fā)布的事件名 * @param data 附帶的數(shù)據(jù) */ static pub(name, data) { if (!eventMap.hasOwnProperty(name)) return let callbacks = eventMap[name] if (callbacks.length === 0) return callbacks.forEach((callback) => { callback(data) }) } /** * 訂閱一個(gè)事件并附帶一個(gè)回調(diào) * 說明這個(gè)事件發(fā)生的時(shí)候所要做的事情 * * @param name 訂閱的事件名稱 * @param callback 回調(diào) * @returns {function(): *} 返回一個(gè)函數(shù), 執(zhí)行這個(gè)函數(shù)將會(huì)取消訂閱 */ static sub(name, callback) { let callbacks = [] if (eventMap.hasOwnProperty(name)) { callbacks = eventMap[name] } callbacks.push(callback) eventMap[name] = callbacks return () => callbacks.shift(callback) } } export default MyEvent
這個(gè)庫一共只有兩個(gè)接口:
pub(name:String,data:data):void:發(fā)布一個(gè)事件,這個(gè)事件附帶一些數(shù)據(jù),當(dāng)這個(gè)事件發(fā)布的時(shí)候,所有訂閱這個(gè)事件的都將會(huì)收到通知,并執(zhí)行訂閱這個(gè)事件的時(shí)候定義的操作,即回調(diào)函數(shù)。
sub(name:String,callback:Function):Fuction:訂閱一個(gè)事件,當(dāng)這個(gè)事件發(fā)生的時(shí)候,即調(diào)用pub的時(shí)候,該callback就會(huì)執(zhí)行,并且在callback中可以收到這個(gè)事件發(fā)生的時(shí)候的附帶數(shù)據(jù)。該函數(shù)還返回一個(gè)新的函數(shù),調(diào)用這個(gè)函數(shù)可以取消訂閱該事件
案例:
import MyEvent from "../../0x012-component-communication/src/MyEvent" // 定義一個(gè)變量 let num = 1 // 定義一個(gè)事件名 const EVENT_INCREMENT = "EVENT_INCREMENT" // 訂閱這個(gè)事件,并將取消訂閱的函數(shù)保存起來 let unSub = MyEvent.sub(EVENT_INCREMENT, (data) => { console.log(data) }) // 當(dāng) num 發(fā)生變化的時(shí)候,發(fā)布這個(gè)時(shí)間 num += 1 MyEvent.pub(EVENT_INCREMENT, {num: num}) // 當(dāng) num 發(fā)生變化的時(shí)候,發(fā)布這個(gè)時(shí)間 num += 1 MyEvent.pub(EVENT_INCREMENT, {num: num}) // 取消訂閱 unSub() // 當(dāng) num 發(fā)生變化的時(shí)候,發(fā)布這個(gè)時(shí)間 num += 1 MyEvent.pub(EVENT_INCREMENT, {num: num}) // 當(dāng) num 發(fā)生變化的時(shí)候,發(fā)布這個(gè)時(shí)間 num += 1 MyEvent.pub(EVENT_INCREMENT, {num: num}) console.log({num})
查看瀏覽器,可以看到,我們收到了兩次通知,因?yàn)槲覀冊谥型救∠擞嗛?br>
原理就是保存了MyEvent中的eventMap保存了一個(gè)Map,該Map是一個(gè)String=>Array
name | callbacks EVENT_INCRECEMENT | (data)=>{...} - | (data)=>{...} - | (data)=>{...} EVENT_DECRECEMENT | (data)=>{...} - | (data)=>{...}
當(dāng)我們調(diào)用pub的時(shí)候,就或?qū)ふ业竭@個(gè)事件名,并循環(huán)將該事件名下掛載的callback隊(duì)列執(zhí)行。
當(dāng)我們調(diào)用unsub的時(shí)候,則會(huì)將這個(gè)callback從隊(duì)列中移除,這樣就不會(huì)執(zhí)行了。
redux的原理和這個(gè)簡陋的框架類似,就是比這精巧多了,不過本質(zhì)還是一樣的,我們可以訂閱某個(gè)值的變化,然后在某個(gè)值變化并收到這個(gè)通知的時(shí)候作出我們自己的邏輯。
接下來我們會(huì)使用redux,然后通過redux來改造這個(gè)我們的ledux,打造成至少表面上類似的......
0x005 redux栗子import {createStore} from "redux" // 定義一個(gè) reducer function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 case "DECREMENT": return state - 1 default: return state } } // 定義一個(gè)store,持有全局的 state let store = createStore(counter) // 訂閱,并輸出 state store.subscribe(() => console.log(store.getState()) ) // 發(fā)布一個(gè)事件 store.dispatch({type: "INCREMENT"}) store.dispatch({type: "INCREMENT"}) store.dispatch({type: "DECREMENT"})
查看瀏覽器
可以看到,其實(shí)模式差不多:
定義數(shù)據(jù):
redux:reducer 部分
MyEvent:let num部分
訂閱:
redux:subscribe 部分
MyEvent:sub部分
發(fā)布:
redux:dispatch 部分
MyEvent:pub部分
但是其實(shí)內(nèi)部差別又非常大,在MyEvent中,都是很隨意的,我可以隨便定義事件,隨便修改數(shù)據(jù),隨便發(fā)布事件,所以我寫的東西叫做事件通知,而不是狀態(tài)管理。redux是用來做狀態(tài)管理的,可以說是在事件通知之中再一次做了封裝。
在MyEvent中數(shù)據(jù)是可以隨意修改的,但是在redux中,數(shù)據(jù)的修改只能通過dispatch提交一個(gè)修改請求,而在reducer中處理這個(gè)請求。
0x006 ledux實(shí)現(xiàn):編寫redux
class Ledux { static createStore(reduer) { return new Store(reduer) } } class Store { constructor(reducer) { this.state = reducer(null, {}) this.callbacks = [] this.reducer = reducer } subscribe(callback) { this.callbacks.push(callback) } getState() { return this.state } dispatch(action) { this.state = this.reducer(this.state, action) this.callbacks.forEach(callback => callback()) } } export default Ledux
使用Ledix
import Ledux from "./ledux"; function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 case "DECREMENT": return state - 1 default: return state } } let store=Ledux.createStore(counter) store.subscribe(()=>{ console.log(store.getState()) }) store.dispatch({type: "INCREMENT"}) store.dispatch({type: "INCREMENT"}) store.dispatch({type: "DECREMENT"})
查看瀏覽器
可以看到,效果是一樣的,而過程除了我喜歡用class封裝以外也沒有太大的區(qū)別,就這樣實(shí)現(xiàn)了ledux了,當(dāng)然隨著對redux的api的深入學(xué)習(xí),這個(gè)框架也可以不斷的深入發(fā)展。
0x007 資源源碼
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/97294.html
摘要:的全稱是統(tǒng)一資源定位符英文,可以這么說,是一種標(biāo)準(zhǔn),而網(wǎng)址則是符合標(biāo)準(zhǔn)的一種實(shí)現(xiàn)而已。渲染器,將組件渲染到頁面上。 0x000 概述 從這一章開始就進(jìn)入路由章節(jié)了,并不直接從如何使用react-route來講,而是從路由的概念和實(shí)現(xiàn)來講,達(dá)到知道路由的本質(zhì),而不是只知道如何使用react-route庫的目的,畢竟react-route只是一個(gè)庫,是路由的一個(gè)實(shí)現(xiàn)而已,而不是路由本身。 ...
摘要:展示組件與容器組件的綁定庫的基本開發(fā)思想是展示組件與容器組件相分離。技術(shù)上講,容器組件就是使用從樹中讀取部分?jǐn)?shù)據(jù),并通過來把這些數(shù)據(jù)提供給要渲染的組件。 說明:閱讀本篇文章需要對Redux有一定的了解,對Redux不了解的同學(xué)可先看看這篇文章Redux技術(shù)架構(gòu)簡介(一) 1. React中引入react-redux 為了讓Redux和React更好的配合,F(xiàn)acebook專門開發(fā)了一個(gè)...
摘要:異步實(shí)現(xiàn)設(shè)計(jì)需要增加三種通知異步請求發(fā)起的異步請求成功的異步請求失敗的示例代碼如下返回參數(shù)完全可以自定義。這種分別在請求開始前,請求成功后,請求失敗后發(fā)送。表示數(shù)據(jù)的有效性,他的作用是在異步請求發(fā)送失敗后,告訴當(dāng)前的數(shù)據(jù)是過時(shí)的數(shù)據(jù)。 說明:對Redux不了解的同學(xué)可先看看這篇文章Redux技術(shù)架構(gòu)簡介(一) 前言 這里說的Redux異步實(shí)現(xiàn),是專指Redux中的異步Action實(shí)現(xiàn),...
摘要:描述這個(gè)插件可以讓我們的代碼更加的簡潔和美觀。安裝使用提供了兩個(gè)重要的接口使用了這個(gè)插件,的和就可以忘記來,它們就用不著了?,F(xiàn)在有美女個(gè)。 可先查看我的redux簡單入門 react-redux簡介 react-redux是使用redux開發(fā)react時(shí)使用的一個(gè)插件,另外插一句,redux不是react的產(chǎn)品,vue和angular中也可以使用redux;下面簡單講解,如何使用rea...
摘要:因?yàn)楣ぷ髦幸恢痹谑褂?,也一直以來想總結(jié)一下自己關(guān)于的一些知識經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來,做成一本開源免費(fèi)專業(yè)簡單的入門級別的小書,提供給社區(qū)。本書的后續(xù)可能會(huì)做成視頻版本,敬請期待。本作品采用署名禁止演繹國際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...
閱讀 1986·2021-08-19 11:12
閱讀 1532·2021-07-25 21:37
閱讀 1065·2019-08-30 14:07
閱讀 1428·2019-08-30 13:12
閱讀 745·2019-08-30 11:00
閱讀 3620·2019-08-29 16:28
閱讀 1081·2019-08-29 15:33
閱讀 3047·2019-08-26 13:40