如何使用24行JavaScript程式碼實現Redux
作者:Yazeed Bzadough
譯者:小維FE
原文:freecodecamp
為了保證文章的可讀性,本文采用意譯而非直譯。
90%的規約,10%的庫。
Redux是迄今為止建立的最重要的JavaScript庫之一,靈感來源於以前的藝術比如Flux和Elm,Redux通過引入一個包含三個簡單要點的可伸縮體系結構,使得JavaScript函數語言程式設計成為可能。如果你是初次接觸Redux,可以考慮先閱讀官方文件。
1. Redux大多是規約
考慮如下這個使用了Redux架構的簡單的計數器應用。如果你想跳過的話可以直接檢視Github Repo。
1.1 State儲存在一棵樹中
該應用程式的狀態看起來如下:
const initialState = { count: 0 };
1.2 Action宣告狀態更改
根據Redux規約,我們不直接修改(突變)狀態。
// 在Redux應用中不要做如下操作
state.count = 1;
相反,我們建立在應用中使用者可能用到的所有行為。
const actions = {
increment: { type: 'INCREMENT' },
decrement: { type: 'DECREMENT' }
};
1.3 Reducer解釋行為並更新狀態
在最後一個架構部分我們叫做Reduer,其作為一個純函式,它基於以前的狀態和行為返回狀態的新副本。
- 如果
increment
state.count
- 如果
decrement
被觸發,則減少state.count
const countReducer = (state = initialState, action) => { switch (action.type) { case actions.increment.type: return { count: state.count + 1 }; case actions.decrement.type: return { count: state.count - 1 }; default: return state; } };
1.4 目前為止還沒有Redux
你注意到了嗎?到目前為止我們甚至還沒有接觸到Redux庫,我們僅僅只是建立了一些物件和函式,這就是為什麼我稱其為"大多是規約",90%的Redux應用其實並不需要Redux。
2. 開始實現Redux
要使用這種架構,我們必須要將它放入到一個store當中,我們將僅僅實現一個函式:createStore
。使用方式如下:
import { createStore } from 'redux'
const store = createStore(countReducer);
store.subscribe(() => {
console.log(store.getState());
});
store.dispatch(actions.increment);
// logs { count: 1 }
store.dispatch(actions.increment);
// logs { count: 2 }
store.dispatch(actions.decrement);
// logs { count: 1 }
下面這是我們的初始化樣板程式碼,我們需要一個監聽器列表listeners和reducer提供的初始化狀態。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined, {});
}
無論何時某人訂閱了我們的store,那麼他將會被新增到listeners
陣列中。這是非常重要的,因為每次當某人在派發(dispatch)一個動作(action)的時候,所有的listeners
都需要在此次事件迴圈中被通知到。呼叫yourReducer
函式並傳入一個undefined
和一個空物件將會返回一個initialState
,這個值也就是我們在呼叫store.getState()
時的返回值。既然說到這裡了,我們就來建立這個方法。
2.1 store.getState()
這個函式用於從store中返回最新的狀態,當用戶每次點選一個按鈕的時候我們都需要最新的狀態來更新我們的檢視。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined, {});
return {
getState: () => currentState
};
}
2.2 store.dispatch()
這個函式使用一個action
作為其入參,並且將這個action
和currentState
反饋給yourReducer
來獲取一個新的狀態,並且dispatch
方法還會通知到每一個訂閱了當前store的監聽者。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined, {});
return {
getState: () => currentState,
dispatch: (action) => {
currentState = yourReducer(currentState, action);
listeners.forEach((listener) => {
listener();
});
}
};
};
2.3 store.subscribe(listener)
這個方法使得你在當store接收到一個action
的時候能夠被通知到,可以在這裡呼叫store.getState()
來獲取最新的狀態並更新UI。
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined, {});
return {
getState: () => currentState,
dispatch: (action) => {
currentState = yourReducer(currentState, action);
listeners.forEach((listener) => {
listener();
});
},
subscribe: (newListener) => {
listeners.push(newListener);
const unsubscribe = () => {
listeners = listeners.filter((l) => l !== newListener);
};
return unsubscribe;
}
};
};
同時subscribe
函式返回了另一個函式unsubscribe
,這個函式允許你當不再對store的更新感興趣的時候能夠取消訂閱。
3. 整理程式碼
現在我們新增按鈕的邏輯,來看看最後的原始碼:
// 簡化版createStore函式
const createStore = (yourReducer) => {
let listeners = [];
let currentState = yourReducer(undefined, {});
return {
getState: () => currentState,
dispatch: (action) => {
currentState = yourReducer(currentState, action);
listeners.forEach((listener) => {
listener();
});
},
subscribe: (newListener) => {
listeners.push(newListener);
const unsubscribe = () => {
listeners = listeners.filter((l) => l !== newListener);
};
return unsubscribe;
}
};
};
// Redux的架構組成部分
const initialState = { count: 0 };
const actions = {
increment: { type: 'INCREMENT' },
decrement: { type: 'DECREMENT' }
};
const countReducer = (state = initialState, action) => {
switch (action.type) {
case actions.increment.type:
return {
count: state.count + 1
};
case actions.decrement.type:
return {
count: state.count - 1
};
default:
return state;
}
};
const store = createStore(countReducer);
// DOM元素
const incrementButton = document.querySelector('.increment');
const decrementButton = document.querySelector('.decrement');
// 給按鈕新增點選事件
incrementButton.addEventListener('click', () => {
store.dispatch(actions.increment);
});
decrementButton.addEventListener('click', () => {
store.dispatch(actions.decrement);
});
// 初始化UI檢視
const counterDisplay = document.querySelector('h1');
counterDisplay.innerHTML = parseInt(initialState.count);
// 派發動作的時候跟新UI
store.subscribe(() => {
const state = store.getState();
counterDisplay.innerHTML = parseInt(state.count);
});
我們再次看看最後的檢視效果:
原文: https://www.freecodecamp.org/news/redux-in-24-lines-of-code/
4. 交流
本篇主要簡單瞭解下Redux的三個架構組成部分以及如何實現一個簡化版的Redux,對Redux能有進一步的瞭解,希望能和大家相互討論技術,一起交流學習。
文章已同步更新至Github部落格,若覺文章尚可,歡迎前往star!
你的一個點贊,值得讓我付出更多的努力!
逆境中成長,只有不斷地學習,才能成為更好的自己,與君共勉!
相關推薦
如何使用24行JavaScript程式碼實現Redux
作者:Yazeed Bzadough 譯者:小維FE 原文:freecodecamp 為了保證文章的可讀性,本文采用意譯而非直譯。 90%的規約,10%的庫。 Redux是迄今為止建立的最重要的JavaScript庫之一,靈感來源於以前的藝術比如Flux和Elm,Redux通過引入一個包含三個簡單要點的可
40行JavaScript程式碼實現的3D旋轉魔方動畫效果
JS1K是JavaScript程式設計競賽——參加競賽的規則很簡單,指令碼必須小於1K,競賽網站開始也只是為了娛樂,卻意外地收到了很多優秀的作品。 這是2016年JS1k上傳的作品,用幾十行程
30行Javascript程式碼實現圖片懶載入
小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 前言 頁面太多圖片?那麼請你花20分鐘去優化一下頁面的效能 講道理,當你為圖片的src賦值時,D
100行Javascript程式碼實現視訊通話
視訊聊天室 上一篇文章通過JavaScript呼叫AnyChat實現視訊聊天室 簡單地講述瞭如何通過AnyChat做視訊聊天室。通過學習,我自己也做了個簡單的小例子,幾十行JavaScript指令碼就能輕鬆實現視訊通話;也不用去下載指定的什麼瀏覽器,因為IE、firefo
利用itchat 10行python程式碼實現微信轟炸
''' 轉載:https://github.com/Gin79/WeChat-Bomb/blob/master/README.md ''' 說明 站在巨人的肩膀上 基於python,這個小程式是用python寫的 使用的是python第三方庫itchat,itc
10 行 Java 程式碼實現 LRU 快取
10 行 Java 程式碼實現 LRU 快取 (整理自網路) 最近最少使用快取的回收 為了實現快取回收,我們需要很容易做到: 查詢出最近最晚使用的項 給最近最少使用的項做一個標記 連結串列可以實現這兩個操作。檢測使用最近最少使用的項只需要返回連結串列的尾部。標記一項為最近最少使用的項只需
用20行JS程式碼實現貼上板功能
document.execCommand() 此方法就是實現剪貼簿的關鍵,它可以傳入cut,copy,paste三種引數。從最常用的document.execCommand('copy')開始介紹。 在使用之前,我們應該檢查瀏覽器是否支援copy命令:document.queryCommandS
30 行 Javascript 程式碼搞定智慧家居系統
本文首發於『阿里雲 IoT 開發者社群』,更多精彩物聯網內容歡迎前往瀏覽。 智慧家居可謂是今年物聯網的熱門領域,通過智慧單品和智慧音箱,人們已然把『智慧』兩個字變成了生活的理所應當。搭建雲上之家除了買買買,還能 DIY。依託阿里雲物聯網平臺,我們用 30 行程式碼來搞定一套智慧
神奇,幾行Python程式碼實現隨機生成生成優惠券
生活中我們到處搶優惠券,到處用到優惠券,彷彿一輸入類似“yxune1uaqc5”一串代號的優惠券,立刻感覺撿到大便宜。商家這些優惠券的編碼都是怎麼生成的呢? 學習Python中有不明白推薦加入交流群 &n
兩行 CSS 程式碼實現圖片任意顏色賦色技術
很久之前在張鑫旭大大的部落格看到過一篇 PNG格式小圖示的CSS任意顏色賦色技術,當時驚為天人,感慨還可以這樣玩,私底下也曾多次想過有沒有其他方法可以實現,又或者不僅僅侷限於 PNG 圖片。 mix-blend-mode 與 background-blend-mode mix-blend-mode 在我之
一個 11 行 Python 程式碼實現的神經網路
概要:直接上程式碼是最有效的學習方式。這篇教程通過由一段簡短的 python 程式碼實現的非常簡單的例項來講解 BP 反向傳播演算法。 程式碼如下: Python 1234567891011X=np.array([
表哥用80行Python程式碼實現“頭腦王者”,運營竅訣躺著教我賺錢!
最近感覺微信小程式比較火、頭腦王者,周圍很多人在玩“跳一跳”和“頭腦王者”之類的小遊戲。 我對小程式也產生了濃厚的興趣。一開始看到官方的小程式的介紹,也看了小程式的部分開發文件,本能以為微信小程式不過是一個瀏覽器框架,小程式也只是網頁而已。首先認為小程式通過了HTTP協yi傳輸了相應的JS、HT
基於Tkinter用50行Python程式碼實現簡易計算器
Tkinter一般是python自帶的,所以程式碼不需要其他元件,本程式是在python2.7版本實現的。 主要涉及了tkinter的使用,函式定義和呼叫,匿名函式的使用,類成員函式定義等python基礎知識,適合新手學習。 程式碼如下: from Tkinter
300行Python程式碼實現俄羅斯方塊,致敬逝去的童年
本文程式碼基於 python3.6 和 pygame1.9.4。 俄羅斯方塊是兒時最經典的遊戲之一,剛開始接觸 pygame 的時候就想寫一個俄羅斯方塊。但是想到旋轉,停靠,消除等操作,感覺好像很難啊,等真正寫完了發現,一共也就 300 行程式碼,並沒有什麼難的。 先來看一個遊戲截圖,有點醜
用少量程式碼實現redux核心部分及其演化歷史
作者:殷榮檜@騰訊 本文原始碼地址 本文Github地址,歡迎star 先來看一下,完成文章標題所說的,需要完成哪些任務: TODO LIST(計劃列表) 1.redux中reducer的實現 2.redux中action的實現 3.redux中store的實現 3.5 先不使用redux,直
100行C程式碼實現字元列印漢諾塔
#include <stdio.h> /*-------------------------------------------\ | 僅供於實現功能,看情況自己再新增延時函式等實現動畫效果 | \-------------------------
HTML5--javascript程式碼實現Tab切換
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>javascrip
IE瀏覽器下OCX控制元件的相容問題(續集)——Javascript程式碼實現
根據上一篇 http://blog.csdn.net/yangyuyu77584/article/details/39694387 博文方案,現給Javascript程式碼實現。 1.瀏覽器的判斷程式碼。(jQuery新版我還沒有使用,不知道是否已經修改了)這裡我自己補充
三十八、100行python程式碼實現機器學習自動分類
現在朋友圈、公眾號、微博資訊應接不暇,以微信公眾號舉例,看技術極客是怎麼自動篩出自己想看的文章的,100行機器學習程式碼就能自動幫你歸好類,要想找出想看的和不想看的,你再也不用刷朋友圈了 準備工作 1. 準備一張mysql資料庫表,至少包含這些列:id、title(文章標題)、content(文章內
200行Go程式碼實現一個區塊鏈之二——區塊生成與網路通訊
在上一篇文章中,我們向大家展示瞭如何通過精煉的Go程式碼實現一個簡單的區塊鏈。如何計算每個塊的 Hash 值,如何驗證塊資料,如何讓塊連結起來等等,但是所有這些都是跑在一個節點上的。文章釋出後,讀者反響熱烈,紛紛留言讓我快點填坑(網路部分),於是就誕生了這第二篇文章。這篇文章