項目框架
采用React.js作為項目的框架
采用redux作為數據管理的框架
采用antd作為項目的UI組件
采用echarts完成項目中折線圖的繪制
個人項目工作流程總結
拿到UI高保真圖片之后先對整個頁面進行模塊化分,大的模塊分為上部的折現圖部分,中間部分的網元的拓撲圖部分,下部分表格部分以及表格點擊后的彈出層部分。每個模塊有可以再次細分為模塊的頭部(頭部數據基本不變化),以及模塊的內容展示部分。
基本就這樣把整個頁面細分成不同的組件模塊,子組件又可以組成父組件,大的父組件完整組合成整個頁面。
- 起初做的時候並沒有采用redux來控制數據的傳輸,因為當時自己以前並沒有用過(當時聽說很復雜),並且通過react提供的數據傳遞的方式也用不到redux,並且開始做的時候組件之間數據傳遞都還比較簡單。直接采用Ajax請求通過在當前頁面請求到數據,在通過this.props來來傳遞數據,通過this.state來控制組件內數據的變化,通過回調函數來完成數據從子組件傳遞到父組件。后面在項目進展過程中項目組中的其他前端都采用了redux來實現數據的傳遞,然后就開始改在自己的代碼。天知道在一個基本昨晚的頁面中采用一個自己從來沒有過的技術並且要摒棄前面寫的代碼的思維慣性會有多困難。於是當時就陷入了無盡的痛苦之中。不性的是關於redux的教學視頻網上也沒找到。看了很多博客文章也是雲里霧里。實在沒辦法了,通過看項目組成員寫的其他頁面的,改造自己的頁面。終於把redux的數據跑通了。(過程純屬自我吐槽)
- echarts相對來說就比較容易接受了(雖然以前也沒用過),首先其是百度的開源產品,有中文的官網和完整的API配置文檔。並且其針對不同的圖形配置不同的option也來得簡單粗暴。所以很快也就能夠用來做項目中的折線圖。
- antdUI組件是以前用來作過一個小的項目的東西,也算比較熟悉。以前用的是1.X的版本,進行這個項目的時候已經進入了2.X的版本,並且在持續的更新。功能也越來越強大。
項目流程介紹
由於這個項目是一個運營商后台數據可視化平台,所以整體頁面風格也是簡單實用型。首先在antd中找到每一個頁面中需要的組件,復制出代碼,呈現在頁面上,然后再根據高保真的組件尺寸進行樣式改造。在react的每一個生命周期中完成相應的事件處理。
本次總結的重點:使用redux完成的那個組件之間的數據通訊
- 首先引入react-redux:
import {Provider} from "react-redux";
- 引入configureStore組件,里邊存儲着所有action中的狀態:
import configureStore from "./store/configureStore.js"; const store=configureStore();
- 用redux中解析出來的Provider包裹住主組件:
ReactDOM.render( <Provider store={store}><RootApp/></Provider>, document.getElementById("root") )
redux主要由三個部分組成,這個在很多的介紹redux的博客中都會講到,這里我也想復習一下,先按照自己的理解寫下來:這三部分分別是store(儲備),顧名思義就是用來存儲數據的倉庫,在用redux進行數據傳遞的時候,需要傳遞的數據都會存儲在store中。第二部分是reducers(還原劑,減速劑),在這部分中對數據進行一些操作,然后然后把數據再返回store中,然后通過store中的數據變化來更新組件。第三部分就是action,用來接收組件中事件,生成操作數據的方法。把action中的方法和store中的數據一起傳入reducer中進行處理。
(由於自己理解的不是很透徹,現將一些知名博客中的解釋進行引用)
首先,用戶發出 Action。 store.dispatch(action); 然后,Store 自動調用 Reducer,並且傳入兩個參數:當前 State 和收到的 Action。 Reducer 會返回新的 State 。 let nextState = todoApp(previousState, action); State 一旦有變化,Store 就會調用監聽函數。 // 設置監聽函數 store.subscribe(listener); listener可以通過store.getState()得到當前狀態。如果使用的是 React,這時可以觸發重新渲染 View。 function listerner() { let newState = store.getState(); component.setState(newState); }
具體介紹Redux中的每一塊的寫法
/** * 接收reducer里的state,存儲所有state */ import { createStore, applyMiddleware, combineReducers, compose } from "redux"; import thunkMiddleware from 'redux-thunk'; import createLogger from 'redux-logger'; import { /** * 從reducer中引入的處理后保存store數據的方法 */ } from "../reducers/reducer.js"; /** * @description:將多個拆分的reducer(一個reducer管理一個狀態)合並成一個新的reducer傳入store。 */ const newReducer = combineReducers({ /** * 從reducer中引入的處理后保存store數據的方法 */ }); const logger = createLogger(); const initialState = {}; export default function configureStore() { let store; if (module.hot) { store = createStore(newReducer, initialState, compose( applyMiddleware(thunkMiddleware, logger), window.devToolsExtension ? window.devToolsExtension() : f => f )); } else { store = createStore(newReducer, initialState, compose( applyMiddleware(thunkMiddleware), f => f )); } return store; }
/** * Reducer */ import { /** * 引入action中的狀態常量 */ GET_SUCCESS } from "../actions/action.js"; /** * @func:(getValueDate)獲取數據值; */ export function getValueDate(state={},action){ switch (action.type){ case GET_SUCCESS: return { data:Object.assign({},state,updateState(state,action)).data } default: return state } }
/** * action */ import Apis from "../utils/api.js";//Apis為數據請求的后台接口地址 import { callApi } from '../../utils/utils.js';//callApi為封裝的利用Ferch請求方法 import { GET_VALUE, GET_SUCCESS, GET_FAILURE } from "./action.js"; function getValueRequest(type) { return{ type:type } } function getValueRequestSuccess(type){ return function(data){ return{ type:type, data:data } } } function getValueRequestFailure(type){ return function(data){ return{ type:type } } } /*** * @func:提交請求的函數; */ export function getSelectValue(parm){ let url=Apis.GET_SELECT_VALUE_URL; return callApi( url, parm, getValueRequest(GET_VALUE), getValueRequestSuccess(GET_SUCCESS), getValueRequestFailure(GET_FAILURE) ); }
//部分內容未完成,后續補充。