国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Redux and Router

dreambei / 2160人閱讀

摘要:還有這個(gè)解決異步問題,極度不優(yōu)雅。是狀態(tài)管理的庫,是唯一控制頁面跳轉(zhuǎn)的庫。如果您計(jì)時(shí)旅行,它還會(huì)將新狀態(tài)傳遞給以再次更新組件樹。這使得從容器組件訪問它們變得容易。

Part01 What"s the problem

這段代碼意圖是把router傳遞props的路由信息再傳遞給redux。有這么幾個(gè)問題:

如果靠組件生命周期轉(zhuǎn)發(fā) 每個(gè)路由下面的頂級(jí)組件都要調(diào)這樣一個(gè)action

并且,如果路由有參數(shù)改變(很多時(shí)候頁面狀態(tài)的參數(shù)會(huì)在路由中體現(xiàn)),這段代碼是無法檢測(cè)的,還需要在componentWillReceiveProps里去處理邏輯。

還有這個(gè)setTimeout解決異步問題,極度不優(yōu)雅。

Can"t cooperate

redux 是狀態(tài)管理的庫,router 是(唯一)控制頁面跳轉(zhuǎn)的庫。兩者都很美好,但是不美好的是兩者無法協(xié)同工作。換句話說,當(dāng)路由變化以后,store 無法感知到。

redux是想把絕大多數(shù)應(yīng)用程序的狀態(tài)都保存在單一的store里,而當(dāng)前的路由狀態(tài)明顯是應(yīng)用程序狀態(tài)很重要的一部分,應(yīng)當(dāng)是要保存在store中的。

目前是,如果直接使用react router,就意味著所有路由相關(guān)的信息脫離了Redux store的控制,假借組件接受router信息轉(zhuǎn)發(fā)dispatch的方法屬于反模式,違背了redux的設(shè)計(jì)思想,也給我們應(yīng)用程序帶來了更多的不確定性。

Part02 What do we need

我們需要一個(gè)這樣的路由系統(tǒng),他技能利用React Router的聲明式特性,又能將路由信息整合進(jìn)Redux Store中。

react-router-redux

react-router-redux 是 redux 的一個(gè)中間件(中間件:JavaScript 代理模式的另一種實(shí)踐 針對(duì) dispatch 實(shí)現(xiàn)了方法的代理,在 dispatch action 的時(shí)候增加或者修改) ,主要作用是:
加強(qiáng)了React Router庫中history這個(gè)實(shí)例,以允許將history中接受到的變化反應(yīng)到state中去。

Part03 How to use
import React from "react"
import ReactDOM from "react-dom"
import { createStore, combineReducers } from "redux"
import { Provider } from "react-redux"
import { Router, Route, browserHistory } from "react-router"
import { syncHistoryWithStore, routerReducer } from "react-router-redux"

import reducers from "/reducers"

const store = createStore(
  combineReducers({
    ...reducers,
    routing: routerReducer
  })
)

const history = syncHistoryWithStore(browserHistory, store)

ReactDOM.render(
  
    
      
    
  ,
  document.getElementById(‘a(chǎn)pp")
)

使用簡(jiǎn)單直白的api syncHistoryWithStore來完成redux的綁定工作,我們只需要傳入react router中的history(前面提到的)以及redux中的store,就可以獲得一個(gè)增強(qiáng)后的history對(duì)象。
將這個(gè)history對(duì)象傳給react router中的Router組件作為props,就給應(yīng)用提供了觀察路由變化并改變store的能力。
現(xiàn)在,只要您按下瀏覽器按鈕或在應(yīng)用程序代碼中導(dǎo)航,導(dǎo)航就會(huì)首先通過Redux存儲(chǔ)區(qū)傳遞新位置,然后再傳遞到React Router以更新組件樹。如果您計(jì)時(shí)旅行,它還會(huì)將新狀態(tài)傳遞給React Router以再次更新組件樹。

如何訪問容器組件中的路由器狀態(tài)?

React Router?通過路徑組件的props提供路由信息。這使得從容器組件訪問它們變得容易。當(dāng)使用react-redux對(duì)connect()你的組件進(jìn)行陳述時(shí),你可以從第二個(gè)參數(shù)mapStateToProps訪問路由器的道具:

Part04 Code principle https://github.com/reactjs/react-router-redux
// index.js
/**
 * 作為外部 syncHistoryWithStore 
 * 綁定store.dispatch方法引起的state中路由狀態(tài)變更到影響瀏覽器location變更  
 * 綁定瀏覽器location變更觸發(fā)store.dispatch,更新state中路由狀態(tài)  
 * 返回當(dāng)前的histroy、綁定方法listen(dispatch方法觸發(fā)時(shí)執(zhí)行,以綁定前的路由狀態(tài)為參數(shù))、解綁函數(shù)unsubscribe  
 */
export syncHistoryWithStore from "./sync"

/**
 * routerReducer監(jiān)聽路由變更子reducer,通過redux的combineReducers復(fù)合多個(gè)reducer后使用
 */
export { LOCATION_CHANGE, routerReducer } from "./reducer"


/**
 * 構(gòu)建actionCreater,作為外部push、replace、go、goBack、goForward方法的接口,通常不直接使用 
 */
export {
  CALL_HISTORY_METHOD,
  push, replace, go, goBack, goForward,
  routerActions
} from "./actions"

/**
 * 構(gòu)建route中間件,用于分發(fā)action,觸發(fā)路徑跳轉(zhuǎn)等事件
 */
export routerMiddleware from "./middleware"
// sync.js

import { LOCATION_CHANGE } from "./reducer"

// 默認(rèn)用state.routing存取route變更狀態(tài)數(shù)據(jù)  
const defaultSelectLocationState = state => state.routing

/** 
 * 作為外部syncHistoryWithStore接口方法 
 * 綁定store.dispatch方法引起的state中路由狀態(tài)變更到影響瀏覽器location變更  
 * 綁定瀏覽器location變更觸發(fā)store.dispatch,更新state中路由狀態(tài)  
 * 返回當(dāng)前的histroy、綁定方法listen(dispatch方法觸發(fā)時(shí)執(zhí)行,以綁定前的路由狀態(tài)為參數(shù))、解綁函數(shù)unsubscribe  
 */
export default function syncHistoryWithStore(history, store, {
  // 約定redux.store.state中哪個(gè)屬性用于存取route變更狀態(tài)數(shù)據(jù)  
  selectLocationState = defaultSelectLocationState,
  // store中路由狀態(tài)變更是否引起瀏覽器location改變  
  adjustUrlOnReplay = true
} = {}) {
  // Ensure that the reducer is mounted on the store and functioning properly.
  // 確保redux.store.state中某個(gè)屬性綁定了route變更狀態(tài)  
  if (typeof selectLocationState(store.getState()) === "undefined") {
    throw new Error(
      "Expected the routing state to be available either as `state.routing` " +
      "or as the custom expression you can specify as `selectLocationState` " +
      "in the `syncHistoryWithStore()` options. " +
      "Ensure you have added the `routerReducer` to your store"s " +
      "reducers via `combineReducers` or whatever method you use to isolate " +
      "your reducers."
    )
  }

  let initialLocation // 初始化route狀態(tài)數(shù)據(jù)  
  let isTimeTraveling // 瀏覽器頁面location.url改變過程中標(biāo)識(shí),區(qū)別頁面鏈接及react-router-redux變更location兩種情況 
  let unsubscribeFromStore  // 移除store.listeners中,因路由狀態(tài)引起瀏覽器location變更函數(shù)  
  let unsubscribeFromHistory  // 移除location變更引起路由狀態(tài)更新函數(shù)  
  let currentLocation // 記錄上一個(gè)當(dāng)前路由狀態(tài)數(shù)據(jù)  

  // 獲取路由事件觸發(fā)后路由狀態(tài),或者useInitialIfEmpty為真值獲取初始化route狀態(tài),或者undefined 
  const getLocationInStore = (useInitialIfEmpty) => {
    const locationState = selectLocationState(store.getState())
    return locationState.locationBeforeTransitions ||
      (useInitialIfEmpty ? initialLocation : undefined)
  }

  // 初始化route狀態(tài)數(shù)據(jù) 
  initialLocation = getLocationInStore()

  // If the store is replayed, update the URL in the browser to match.
  // adjustUrlOnReplay為真值時(shí),store數(shù)據(jù)改變事件dispatch發(fā)生后,瀏覽器頁面更新location
  if (adjustUrlOnReplay) {
    // 由store中路由狀態(tài)改變情況,更新瀏覽器location  
    const handleStoreChange = () => {
      // 獲取路由事件觸發(fā)后路由狀態(tài),或者初始路由狀態(tài)  
      const locationInStore = getLocationInStore(true)
      if (currentLocation === locationInStore || initialLocation === locationInStore) {
        return
      }

      // 瀏覽器頁面location.url改變過程中標(biāo)識(shí),區(qū)別頁面鏈接及react-router-redux變更location兩種情況 
      isTimeTraveling = true
      // 記錄上一個(gè)當(dāng)前路由狀態(tài)數(shù)據(jù)  
      currentLocation = locationInStore

      // store數(shù)據(jù)改變后,瀏覽器頁面更新location
      history.transitionTo({
        ...locationInStore,
        action: "PUSH"
      })
      isTimeTraveling = false
    }

    // 綁定事件,完成功能為,dispatch方法觸發(fā)store中路由狀態(tài)改變時(shí),更新瀏覽器location
    unsubscribeFromStore = store.subscribe(handleStoreChange)

    // 初始化設(shè)置路由狀態(tài)時(shí)引起頁面location改變  
    handleStoreChange()
  }

  // 頁面鏈接變更瀏覽器location,觸發(fā)store.dispatch變更store中路由狀態(tài)  
  const handleLocationChange = (location) => {
    // react-router-redux引起瀏覽器location變更過程中,無效;頁面鏈接變更,有效  
    if (isTimeTraveling) {
      return
    }

    // Remember where we are
    currentLocation = location

    // Are we being called for the first time?
    if (!initialLocation) {
      // Remember as a fallback in case state is reset
      initialLocation = location

      // Respect persisted location, if any
      if (getLocationInStore()) {
        return
      }
    }

    // Tell the store to update by dispatching an action
    store.dispatch({
      type: LOCATION_CHANGE,
      payload: location
    })
  }
  // hashHistory、boswerHistory監(jiān)聽瀏覽器location變更,觸發(fā)store.dispatch變更store中路由狀態(tài)  
  unsubscribeFromHistory = history.listen(handleLocationChange)

  // History 3.x doesn"t call listen synchronously, so fire the initial location change ourselves
  // 初始化更新store中路由狀態(tài)  
  if (history.getCurrentLocation) {
    handleLocationChange(history.getCurrentLocation())
  }

  // The enhanced history uses store as source of truth
  return {
    ...history,
    // store中dispatch方法觸發(fā)時(shí),綁定執(zhí)行函數(shù)listener,以綁定前的路由狀態(tài)為參數(shù)  
    listen(listener) {
      // Copy of last location.
      // 綁定前的路由狀態(tài)  
      let lastPublishedLocation = getLocationInStore(true)

      // Keep track of whether we unsubscribed, as Redux store
      // only applies changes in subscriptions on next dispatch
      let unsubscribed = false  // 確保listener在解綁后不執(zhí)行  
      const unsubscribeFromStore = store.subscribe(() => {
        const currentLocation = getLocationInStore(true)
        if (currentLocation === lastPublishedLocation) {
          return
        }
        lastPublishedLocation = currentLocation
        if (!unsubscribed) {
          listener(lastPublishedLocation)
        }
      })

      // History 2.x listeners expect a synchronous call. Make the first call to the
      // listener after subscribing to the store, in case the listener causes a
      // location change (e.g. when it redirects)
      if (!history.getCurrentLocation) {
        listener(lastPublishedLocation)
      }

      // Let user unsubscribe later
      return () => {
        unsubscribed = true
        unsubscribeFromStore()
      }
    },

    // 解綁函數(shù),包括location到store的handleLocationChange、store到location的handleStoreChange
    unsubscribe() {
      if (adjustUrlOnReplay) {
        unsubscribeFromStore()
      }
      unsubscribeFromHistory()
    }
  }
}
// reducer.js 
/**
 * This action type will be dispatched when your history
 * receives a location change.
 */
export const LOCATION_CHANGE = "@@router/LOCATION_CHANGE"

const initialState = {
  locationBeforeTransitions: null
}

/**
 * 監(jiān)聽路由變更子reducer,通過redux的combineReducers復(fù)合多個(gè)reducer后使用,作為外部routerReducer接口  
 * 提示redux使用過程中,可通過子組件模塊中注入reducer,再使用combineReducers復(fù)合多個(gè)reducer  
 * 最后使用replaceReducer方法更新當(dāng)前store的reducer,意義是構(gòu)建reducer拆解到各個(gè)子模塊中  
 * */ 
export function routerReducer(state = initialState, { type, payload } = {}) {
  if (type === LOCATION_CHANGE) {
    return { ...state, locationBeforeTransitions: payload }
  }

  return state
}
// actions.js
export const CALL_HISTORY_METHOD = "@@router/CALL_HISTORY_METHOD"

function updateLocation(method) {
  return (...args) => ({
    type: CALL_HISTORY_METHOD,  // route事件標(biāo)識(shí),避免和用于定義的action沖突  
    payload: { method, args }   // method系hashHistroy、boswerHistroy對(duì)外接口方法名,args為參數(shù)  
  })
}

/**
 * 返回actionCreater,作為外部push、replace、go、goBack、goForward方法的接口,通常不直接使用  
 */
export const push = updateLocation("push")
export const replace = updateLocation("replace")
export const go = updateLocation("go")
export const goBack = updateLocation("goBack")
export const goForward = updateLocation("goForward")

export const routerActions = { push, replace, go, goBack, goForward }
完結(jié)

(此文由PPT摘抄完成)PPT鏈接

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/99797.html

相關(guān)文章

  • 服務(wù)端渲染的React手腳架。完美使用 React, Redux, and React-Router

    摘要:服務(wù)端渲染的手腳架這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于已經(jīng)提供代碼熱加載,使用預(yù)處理,單元測(cè)試,代碼覆蓋率報(bào)告,代碼分割等等更多。 Universal React Starter Kit 服務(wù)端渲染的React手腳架 這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于webpack已經(jīng)提供代碼熱加載,使用...

    zhouzhou 評(píng)論0 收藏0
  • 服務(wù)端渲染的React手腳架。完美使用 React, Redux, and React-Router

    摘要:服務(wù)端渲染的手腳架這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于已經(jīng)提供代碼熱加載,使用預(yù)處理,單元測(cè)試,代碼覆蓋率報(bào)告,代碼分割等等更多。 Universal React Starter Kit 服務(wù)端渲染的React手腳架 這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于webpack已經(jīng)提供代碼熱加載,使用...

    RayKr 評(píng)論0 收藏0
  • 服務(wù)端渲染的React手腳架。完美使用 React, Redux, and React-Router

    摘要:服務(wù)端渲染的手腳架這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于已經(jīng)提供代碼熱加載,使用預(yù)處理,單元測(cè)試,代碼覆蓋率報(bào)告,代碼分割等等更多。 Universal React Starter Kit 服務(wù)端渲染的React手腳架 這個(gè)啟動(dòng)包的設(shè)計(jì)是為了讓你使用一整套最新最酷的前端技術(shù),所有都是可配置,富特性,基于webpack已經(jīng)提供代碼熱加載,使用...

    DC_er 評(píng)論0 收藏0
  • React生態(tài),dva源碼閱讀

    摘要:下面會(huì)從淺到深,淡淡在閱讀源碼過程中自己的理解。分拆子頁面后,每一個(gè)子頁面對(duì)應(yīng)一個(gè)文件。總結(jié)上面就是最早版本的源碼,很簡(jiǎn)潔的使用了等其目的也很簡(jiǎn)單簡(jiǎn)化相關(guān)生態(tài)的繁瑣邏輯參考源碼地址 ??dva的思想還是很不錯(cuò)的,大大提升了開發(fā)效率,dva集成了Redux以及Redux的中間件Redux-saga,以及React-router等等。得益于Redux的狀態(tài)管理,以及Redux-saga中...

    bergwhite 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<