首先是配置$ngRedux 服務(wù)
app.config(/*@ngInject*/$ngReduxProvider => {
let middleware = ['ngUiRouterMiddleware']
const reducers = {
router, //靜態(tài)寫法
lang: langReducer,
session: sessionReducer,
[actionTagManagement.name]: actionTagManagement.reducer //動態(tài)寫法
}
$ngReduxProvider.createStoreWith(reducers, middleware)
項(xiàng)目中的探索
目的效果就是幾個簡單的折疊展開的效果。
按照angular的做法很簡單勉耀,通過ng-show
能夠快速完成指煎,現(xiàn)在思考用redux的方式。
最初的代碼:
import html from './index.html'
import './index.scss'
let prefix = 'actionApi_' //需要prefix來確保action的全局唯一性
const OPT_STATUS = prefix + 'OPT_STATUS'
const OPT_SAMPLE = prefix + 'OPT_SAMPLE'
const OPT_LOG = prefix + 'OPT_LOG'
const defaultState = {
showStatus: true,
showLog: false,
showSample: false
}
export function reducer(state = defaultState, action) {
switch (action.type){
case OPT_STATUS: {
return Object.assign({}, state, {
showStatus: action.data
})
}
case OPT_SAMPLE: {
return Object.assign({}, state, {
showSample: action.data
})
}
case OPT_LOG: {
return Object.assign({}, state, {
showLog: action.data
})
}
default: {
return state
}
}
}
export const name = 'action.api'
export const state = {
url: '/api',
template: html,
controllerAs: '$ctrl',
controller: /*@ngInject*/($scope, $ngRedux) => {
let unSubscribe = $ngRedux.connect((state) => {
return {
showStatus: state[name].showStatus,
showSample: state[name].showSample,
showLog: state[name].showLog
}
}, Object.assign({}))($scope)
$scope.$on('$destroy', unSubscribe) //銷毀監(jiān)聽器
$scope.collapseStatus = (data) => {
$ngRedux.dispatch(function(data){
return {
type: OPT_STATUS,
data
}
}(!data))
}
//function 為action 生成函數(shù)便斥,這里定義函數(shù)后立即執(zhí)行至壤,實(shí)際上生成了一個action
$scope.collapseSample = (data) => {
$ngRedux.dispatch(function(data){
return {
type: OPT_SAMPLE,
data
}
}(!data))
}
$scope.collapseLog = (data) => {
$ngRedux.dispatch(function(data){
return {
type: OPT_LOG,
data
}
}(!data))
}
}
}
html 中:
<h2 ng-click="collapseSample(showSample)">
<a href=""><span class="glyphicon glyphicon-menu-down doc-arrow" ng-class="{'doc-arrow-hide': showSample == false}"></span></a>
<span class="doc-h2-pointer">獲取Sample數(shù)據(jù)</span>
</h2>
<div class="doc-hide-content" ng-show="showSample">
......
</div>
目的已經(jīng)完成了。寫法上很像angular枢纠。
$ngRedux.connect()函數(shù)的第一個參數(shù)實(shí)際上是一個函數(shù)像街,它返回一個對象。這里的state即全局的state晋渺,我們得到我們需要的本地state镰绎,并和angular中的變量建立一種綁定關(guān)系。
第二個參數(shù)是一個對象些举,表示我們進(jìn)行的一些操作 跟狱,redux是通過觸發(fā)action來更改狀態(tài)俭厚。我們的操作實(shí)際上也就是返回一些action户魏,交由reducer來更改state,從而達(dá)到改變視圖的目的
代碼看起來有點(diǎn)臃腫。讓我們進(jìn)行一下優(yōu)化:
let unSubscribe = $ngRedux.connect((state) => {
Object.assign({}, state[name])
}, Object.assign({}, {
collapseStatus: (data) => {
return {
type: OPT_STATUS,
data: !data
}
},
collapseSample: (data) => {
return {
type: OPT_SAMPLE,
data: !data
}
},
collapseLog: (data) => {
return {
type: OPT_LOG,
data: !data
}
}
}))($scope)
$scope.$on('$destroy', unSubscribe) //銷毀監(jiān)聽器
看起來還是有點(diǎn)別扭叼丑,前面的代碼中我們實(shí)際上聲明了三種action关翎,分別對應(yīng)于三個欄目的折疊情況。那么問題來了鸠信,當(dāng)一個頁面需要折疊的地方很多怎么辦纵寝?難道一直增加action嗎?仔細(xì)想一下星立,這幾個action本身就非常相似爽茴。考慮繼續(xù)縮減代碼绰垂,只提供一個action生成函數(shù)室奏。
這時候,為了描述每個欄目的折疊狀態(tài)劲装,我們的action生成函數(shù)需要兩個參數(shù)胧沫,一個描述是哪個欄目,一個描述折疊狀態(tài)(是展開還是折疊)
Object.assign({}, {collapse: (option, selected) => {
let data = {
[option]: !selected
}
return {
type: OPT_COLLAPSE,
data
}
}}))($scope)
同樣的占业,reducer函數(shù)里面也可以縮減绒怨,像這樣:
export function reducer(state = defaultState, action) {
switch (action.type){
case OPT_COLLAPSE: {
return Object.assign({}, state, action.data)
}
default: {
return state
}
}
}
相應(yīng)的,更改html:
<h2 ng-click="collapse('showSample', showSample)">
<a href=""><span class="glyphicon glyphicon-menu-down doc-arrow" ng-class="{'doc-arrow-hide': showSample == false}"></span></a>
<span class="doc-h2-pointer">獲取Sample數(shù)據(jù)</span>
</h2>
大功告成谦疾,完整js代碼如下:
import html from './index.html'
import './index.scss'
let prefix = 'actionApi_'
const OPT_COLLAPSE = prefix + 'OPT_COLLAPSE'
const defaultState = {
showStatus: true,
showLog: false,
showSample: false
}
export function reducer(state = defaultState, action) {
switch (action.type){
case OPT_COLLAPSE: {
return Object.assign({}, state, action.data)
}
default: {
return state
}
}
}
export const name = 'action.api'
export const state = {
url: '/api',
template: html,
controllerAs: '$ctrl',
controller: /*@ngInject*/($scope, $ngRedux, langActions, sessionActions) => {
let unSubscribe = $ngRedux.connect((state) => {
return Object.assign({}, state[name])
}, Object.assign({}, {collapse: (option, selected) => {
let data = {
[option]: !selected
}
return {
type: OPT_COLLAPSE,
data
}
}}))($scope)
$scope.$on('$destroy', unSubscribe)
}
}
寫在后面
前文曾經(jīng)說過南蹂,這個效果其實(shí)單純用angular很容易就能實(shí)現(xiàn),這里用redux的方式有點(diǎn)殺雞用牛刀的感覺念恍。
之所以這么大費(fèi)周章碎紊,一方面當(dāng)然是為了學(xué)習(xí)新技術(shù),對action生成函數(shù)樊诺,reducer結(jié)構(gòu)優(yōu)化的整個過程相當(dāng)有意思仗考;另一方面也是出于項(xiàng)目需要,雙向綁定雖然用起來非常爽词爬,但是當(dāng)項(xiàng)目逐漸龐大時,"視圖->模型->視圖"的變化會越來越復(fù)雜秃嗜,直到你最后搞不清楚這些變化的源頭