React手寫一個正式版本的redux
阿新 • • 發佈:2019-02-10
import React from 'react' //播放器 const renderScreen = (newScreen, oldScreen = {}) => { if (newScreen === oldScreen) return; console.log("=============>renderScreen"); //獲取頁面元素 const sc = document.querySelector('#screen'); //對頁面元素進行修改 sc.innerHTML = `${newScreen.title}:${store.getState().isPlaying}`; }; const renderButton = (newButton, oldButton = {}) => { if (newButton === oldButton) return; console.log("=============>renderButton"); //獲取頁面元素 const btn = document.querySelector('#button'); //對頁面元素進行修改 btn.innerHTML = newButton.text; }; //1.全域性渲染方法 const renderApp = (newState, oldState = {}) => { if (newState === oldState) { return; } console.log("renderApp state-->", newState); //渲染螢幕 renderScreen(newState.screen, oldState.screen); //渲染按鈕 renderButton(newState.button, oldState.button); }; //2.對狀態的修改交給純函式去做 // 定義修改資料方法 const reducer = (state, action) => { //首先對操作型別進行判斷 switch (action.type) { case 'play_video': return { isPlaying: true, button: { text: '停止' }, screen: { title: action.title } }; case 'stop_video': return { isPlaying: false, button: { text: '播放' }, screen: { title: action.title } }; case 'play_next': return { ...state, screen: { title: action.title } }; default: return state; } }; //3.所以我們定義一個createStore來管理全域性狀態 // 直接暴露資料不安全,會帶來不可預知的錯誤 const createStore = (reducer) => { //區域性作用域 // 初始化資料 let state = { isPlaying: false, screen: { title: 'java is easy' }, button: { text: '播放' } }; //宣告監聽陣列 let listeners = []; //獲取資料方法 const getState = () => state; //來修改資料 const dispatch = (action) => { //1)修改狀態 state = reducer(state, action); //2)呼叫所有監聽 listeners.forEach(listener => listener()); }; //提供一個訂閱方法 const subscribe = (listener) => { listeners.push(listener) }; //暴露方法 return {getState, dispatch, subscribe}; }; //4.使用createStore函式來建立資料逇管理物件 const store = createStore(reducer); //宣告一個老狀態 let oldState = store.getState(); //當狀態發生修改時候 store.subscribe(() => { //獲取最新狀態 const newState = store.getState(); //重新渲染 renderApp(newState, oldState); //更新老狀態 oldState = newState; }); //5.全域性初始化 renderApp(store.getState()); //6.對按鈕進行監聽 document.querySelector("#button").addEventListener('click', () => { //判斷播放狀態 if (!store.getState().isPlaying) { store.dispatch({type: 'play_video', title: '發現不斷,精彩不停...'}); setTimeout(() => { store.dispatch({type: 'play_next', title: '每一次相遇都不是偶然'}); }, 2000); } else { store.dispatch({type: 'stop_video', title: '下班了再見'}); } });