DvaJS構(gòu)建配置React項(xiàng)目與使用

一,介紹與需求分析

1.1,介紹

dva 首先是一個(gè)基于 redux 和 redux-saga 的數(shù)據(jù)流方案,然后為了簡(jiǎn)化開發(fā)體驗(yàn)废离,dva 還額外內(nèi)置了 react-router 和 fetch,所以dva是基于現(xiàn)有應(yīng)用架構(gòu) (redux + react-router + redux-saga 等)的一層輕量封裝顿天。是由阿里架構(gòu)師 sorrycc 帶領(lǐng) team 完成的一套前端框架。

1.2,需求

快速搭建基于react的項(xiàng)目(PC端,移動(dòng)端)蔑担。

二,DvaJS構(gòu)建項(xiàng)目

2.1,初始化項(xiàng)目

第一步:安裝node

第二步:安裝最新版本dva-cli

1 $ npm install dva-cli -g

2 $ dva -v

第三步:dva new 創(chuàng)建新應(yīng)用

1 $ dva new myapp

也可以在創(chuàng)建項(xiàng)目目錄myapp后牌废,用dva init初始化項(xiàng)目

1 $ dva init

第四步:運(yùn)行項(xiàng)目

1 $ cd myapp

2 $ npm start

瀏覽器會(huì)自動(dòng)打開一個(gè)窗口

2.2,項(xiàng)目架構(gòu)介紹

|-mock? ? ? ? ? ? //存放用于 mock 數(shù)據(jù)的文件

|-node_modules? ? ? ? ? ? //項(xiàng)目包

|-public? ? ? ? ? ? //一般用于存放靜態(tài)文件,打包時(shí)會(huì)被直接復(fù)制到輸出目錄(./dist)

|-src? ? ? ? ? ? ? //項(xiàng)目源代碼

? |? |-asserts? ? ? ? //用于存放靜態(tài)資源钟沛,打包時(shí)會(huì)經(jīng)過 webpack 處理

? |? |-caches? ? ? ? //緩存

? |? |-components? ? //組件 存放 React 組件畔规,一般是該項(xiàng)目公用的無狀態(tài)組件

? |? |-entries? ? ? ? //入口

? |? |-models? ? ? ? //數(shù)據(jù)模型 存放模型文件

? |? |-pages? ? ? ? ? //頁面視圖

? |? |-routes? ? ? ? //路由 存放需要 connect model 的路由組件

? |? |-services? ? ? //服務(wù) 存放服務(wù)文件,一般是網(wǎng)絡(luò)請(qǐng)求等

? |? |-test? ? ? ? ? //測(cè)試

? |? |-utils? ? ? ? ? //輔助工具 工具類庫

|-package.json? ? ? //包管理代碼

|-webpackrc.js? //開發(fā)配置

|-tsconfig.json? ? /// ts配置

|-webpack.config.js //webpack配置

|-.gitignore //Git忽略文件

在dva項(xiàng)目目錄中主要分3層恨统,models,services,components,其中models是最重要概念,這里放的是各種數(shù)據(jù)三妈,與數(shù)據(jù)交互的應(yīng)該都是在這里畜埋。services是請(qǐng)求后臺(tái)接口的方法。components是組件了畴蒲。

三,DvaJS的使用

3.1,DvaJS的五個(gè)Api

復(fù)制代碼

1 import dva from 'dva';

2 import {message} from 'antd';

3 import './index.css';

4

5 // 1. Initialize 創(chuàng)建 dva 應(yīng)用實(shí)例

6 const app = dva();

7

8 // 2. Plugins 裝載插件(可選)

9 app.use({

10? onError: function (error, action) {

11? ? message.error(error.message || '失敗', 5);

12? }

13 });

14

15 // 3. Model 注冊(cè)model

16? app.model(require('../models/example').default);

17

18 // 4. Router 配置路由

19 app.router(require('../routes/router').default);

20

21 // 5. Start 啟動(dòng)應(yīng)用

22 app.start('#root');

23

24 export default app._store; // eslint-disable-line 拋出

復(fù)制代碼

1,app = dva(Opts):創(chuàng)建應(yīng)用,返回 dva 實(shí)例蔫骂。(注:dva 支持多實(shí)例)?

在opts可以配置所有的hooks

復(fù)制代碼

1 const app = dva({

2? ? ? history,

3? ? ? initialState,

4? ? ? onError,

5? ? ? onHmr,

6 });

復(fù)制代碼

這里比較常用的是浩嫌,history的配置码耐,一般默認(rèn)的是hashHistory敦间,如果要配置 history 為 browserHistory,可以這樣:

1 import dva from 'dva';

2 import createHistory from 'history/createBrowserHistory';

3 const app = dva({

4? history: createHistory(),

5 });

initialState:指定初始數(shù)據(jù)剿骨,優(yōu)先級(jí)高于 model 中的 state,默認(rèn)是 {}贷掖,但是基本上都在modal里面設(shè)置相應(yīng)的state。

2,app.use(Hooks):配置 hooks 或者注冊(cè)插件。

1 app.use({

2? onError: function (error, action) {

3? ? message.error(error.message || '失敗', 5);

4? }

5 });

可以根據(jù)自己的需要來選擇注冊(cè)相應(yīng)的插件

3,app.model(ModelObject):這里是數(shù)據(jù)邏輯處理窟哺,數(shù)據(jù)流動(dòng)的地方。

復(fù)制代碼

1 export default {

2

3? namespace: 'example',//model 的命名空間旋奢,同時(shí)也是他在全局 state 上的屬性,只能用字符串筑煮,我們發(fā)送在發(fā)送 action 到相應(yīng)的 reducer 時(shí),就會(huì)需要用到 namespace

4

5? state: {},//表示 Model 的狀態(tài)數(shù)據(jù)秸应,通常表現(xiàn)為一個(gè) javascript 對(duì)象(當(dāng)然它可以是任何值)

6

7? subscriptions: {//語義是訂閱,用于訂閱一個(gè)數(shù)據(jù)源祸挪,然后根據(jù)條件 dispatch 需要的 action

8? ? setup({ dispatch, history }) {? // eslint-disable-line

9? ? },

10? },

11

12? effects: {//Effect 被稱為副作用增热,最常見的就是異步操作

13? ? *fetch({ payload }, { call, put }) {? // eslint-disable-line

14? ? ? yield put({ type: 'save' });

15? ? },

16? },

17

18? reducers: {//reducers 聚合積累的結(jié)果是當(dāng)前 model 的 state 對(duì)象

19? ? save(state, action) {

20? ? ? return { ...state, ...action.payload };

21? ? },

22? },

23

24 };

復(fù)制代碼

4,app.router(Function):注冊(cè)路由表,我們做路由跳轉(zhuǎn)的地方

復(fù)制代碼

1 import React from 'react';

2 import { routerRedux, Route ,Switch} from 'dva/router';

3 import { LocaleProvider } from 'antd';

4 import App from '../components/App/App';

5 import Flex from '../components/Header/index';

6 import Login from '../pages/Login/Login';

7 import Home from '../pages/Home/Home';

8 import zhCN from 'antd/lib/locale-provider/zh_CN';

9 const {ConnectedRouter} = routerRedux;

10

11 function RouterConfig({history}) {

12? return (

13? ? <ConnectedRouter history={history}>

14? ? ? <Switch>

15? ? ? ? <Route path="/login"? component={Login} />

16? ? ? ? <LocaleProvider locale={zhCN}>

17? ? ? ? <App>

18? ? ? ? ? <Flex>

19? ? ? ? ? ? <Switch>

20? ? ? ? ? ? <Route path="/"? exact component={Home} />

21? ? ? ? ? ? </Switch>

22? ? ? ? ? </Flex>

23? ? ? ? </App>

24? ? ? ? </LocaleProvider>

25? ? ? </Switch>

26? ? </ConnectedRouter>

27? );

28 }

29

30 export default RouterConfig;

復(fù)制代碼

5,app.start([HTMLElement], opts)

啟動(dòng)我們自己的應(yīng)用

3.2,DvaJS的十個(gè)概念

1,Model

model 是 dva 中最重要的概念吭从,Model 非 MVC 中的 M蝉绷,而是領(lǐng)域模型,用于把數(shù)據(jù)相關(guān)的邏輯聚合到一起讼载,幾乎所有的數(shù)據(jù)咨堤,邏輯都在這邊進(jìn)行處理分發(fā)

復(fù)制代碼

1 import Model from 'dva-model';

2 // import effect from 'dva-model/effect';

3 import queryString from 'query-string';

4 import pathToRegexp from 'path-to-regexp';

5 import {ManagementPage as namespace} from '../../utils/namespace';

6 import {

7? getPages,

8 } from '../../services/page';

9

10 export default Model({

11? namespace,

12? subscriptions: {

13? ? setup({dispatch, history}) {? // eslint-disable-line

14? ? ? history.listen(location => {

15? ? ? ? const {pathname, search} = location;

16? ? ? ? const query = queryString.parse(search);

17? ? ? ? const match = pathToRegexp(namespace + '/:action').exec(pathname);

18? ? ? ? if (match) {

19? ? ? ? ? ? dispatch({

20? ? ? ? ? ? ? type:'getPages',

21? ? ? ? ? ? payload:{

22? ? ? ? ? ? ? ? s:query.s || 10,

23? ? ? ? ? ? ? ? p:query.p || 1,

24? ? ? ? ? ? ? ? j_code:parseInt(query.j,10) || 1,

25? ? ? ? ? ? ? }

26? ? ? ? ? ? });

27? ? ? ? }

28

29? ? ? })

30? ? }

31? },

32? reducers: {

33? ? getPagesSuccess(state, action) {

34? ? ? const {list, total} = action.result;

35? ? ? return {...state, list, loading: false, total};

36? ? },

37? }

38 }, {

39? getPages,

40 })

復(fù)制代碼

2,namespace

model 的命名空間菇篡,同時(shí)也是他在全局 state 上的屬性驱还,只能用字符串议蟆,我們發(fā)送在發(fā)送 action 到相應(yīng)的 reducer 時(shí)戳粒,就會(huì)需要用到 namespace

3,State(狀態(tài))

初始值,我們?cè)?dva() 初始化的時(shí)候和在 modal 里面的 state 對(duì)其兩處進(jìn)行定義苔咪,其中 modal 中的優(yōu)先級(jí)低于傳給 dva() 的 opts.initialState

復(fù)制代碼

1 // dva()初始化

2 const app = dva({

3? initialState: { count: 1 },

4 });

5

6 // modal()定義事件

7 app.model({

8? namespace: 'count',

9? state: 0,

10 });

復(fù)制代碼

Model中state的優(yōu)先級(jí)比初始化的低,但是基本上項(xiàng)目中的 state 都是在這里定義的

4,Subscription

Subscriptions 是一種從 源 獲取數(shù)據(jù)的方法柳骄,它來自于 elm舔清。語義是訂閱,用于訂閱一個(gè)數(shù)據(jù)源曲初,然后根據(jù)條件 dispatch 需要的 action体谒。數(shù)據(jù)源可以是當(dāng)前的時(shí)間、服務(wù)器的 websocket 連接臼婆、keyboard 輸入抒痒、geolocation 變化、history 路由變化等等

復(fù)制代碼

1 subscriptions: { //觸發(fā)器颁褂。setup表示初始化即調(diào)用故响。

2? ? setup({dispatch, history}) {

3? ? ? history.listen(location => {//listen監(jiān)聽路由變化 調(diào)用不同的方法

4? ? ? ? if (location.pathname === '/login') {

5? ? ? ? ? //清除緩存

6? ? ? ? } else {

7? ? ? ? ? dispatch({

8? ? ? ? ? ? type: 'fetch'

9? ? ? ? ? });

10? ? ? ? }

11? ? ? });

12? ? },

13? },

復(fù)制代碼

5,Effects

用于處理異步操作和業(yè)務(wù)邏輯傀广,不直接修改 state,簡(jiǎn)單的來說彩届,就是獲取從服務(wù)端獲取數(shù)據(jù)伪冰,并且發(fā)起一個(gè) action 交給 reducer 的地方。其中它用到了redux-saga里面有幾個(gè)常用的函數(shù)惨缆。

put? 用來發(fā)起一條action

call 以異步的方式調(diào)用函數(shù)

select 從state中獲取相關(guān)的數(shù)據(jù)

take 獲取發(fā)送的數(shù)據(jù)

復(fù)制代碼

1 effects: {

2? ? *login(action, saga){

3? ? ? const data = yield saga.call(effect(login, 'loginSuccess', authCache), action, saga);//call 用戶調(diào)用異步邏輯 支持Promise

4? ? ? if (data && data.token) {

5? ? ? ? yield saga.put(routerRedux.replace('/home'));//put 用于觸發(fā)action 什么是action下面會(huì)講到

6? ? ? }

7? ? },

8? ? *logout(action, saga){

9? ? ? const state = yield saga.select(state => state);//select 從state里獲取數(shù)據(jù)

10? ? },

11?

12? },

復(fù)制代碼

復(fù)制代碼

1 reducers: {

2? ? add1(state) {

3? ? ? const newCurrent = state.current + 1;

4? ? ? return { ...state,

5? ? ? ? record: newCurrent > state.record ? newCurrent : state.record,

6? ? ? ? current: newCurrent,

7? ? ? };

8? ? },

9? ? minus(state) {

10? ? ? return { ...state, current: state.current - 1};

11? ? },

12? },

13? effects: {

14? ? *add(action, { call, put }) {

15? ? ? yield put({ type: 'add1' });

16? ? ? yield call(delayDeal, 1000);

17? ? ? yield put({ type: 'minus' });

18? ? },

19? },

復(fù)制代碼

如果effect與reducers中的add方法重合了糜值,這里會(huì)陷入一個(gè)死循環(huán),因?yàn)楫?dāng)組件發(fā)送一個(gè)dispatch的時(shí)候坯墨,model會(huì)首先去找effect里面的方法寂汇,當(dāng)又找到add的時(shí)候,就又會(huì)去請(qǐng)求effect里面的方法捣染。

這里的 delayDeal骄瓣,是我這邊寫的一個(gè)延時(shí)的函數(shù),我們?cè)?utils 里面編寫一個(gè) utils.js

復(fù)制代碼

1 /**

2? *超時(shí)函數(shù)處理

3? * @param timeout? :timeout超時(shí)的時(shí)間參數(shù)

4? * @returns {*} :返回樣式值

5? */

6 export function delayDeal(timeout) {

7? return new Promise((resolve) => {

8? ? setTimeout(resolve, timeout);

9? });

10 }

復(fù)制代碼

接著我們?cè)?models/example.js 導(dǎo)入這個(gè) utils.js

1 import { delayDeal} from '../utils/utils';

6,Reducer

以key/value 格式定義 reducer耍攘,用于處理同步操作榕栏,唯一可以修改 state 的地方。由 action 觸發(fā)蕾各。其實(shí)一個(gè)純函數(shù)扒磁。

1? reducers: {

2? ? loginSuccess(state, action){

3? ? ? return {...state, auth: action.result, loading: false};

4? ? },

5? }

7,Router

Router 表示路由配置信息,項(xiàng)目中的 router.js

8,RouteComponent

RouteComponent 表示 Router 里匹配路徑的 Component式曲,通常會(huì)綁定 model 的數(shù)據(jù)

9,Action:表示操作事件妨托,可以是同步,也可以是異步

action 的格式如下吝羞,它需要有一個(gè) type 兰伤,表示這個(gè) action 要觸發(fā)什么操作;payload則表示這個(gè) action 將要傳遞的數(shù)據(jù)

復(fù)制代碼

1 {

2? ? ? type: namespace + '/login',

3? ? ? payload: {

4? ? ? ? ? userName: payload.userName,

5? ? ? ? ? password: payload.password

6? ? ? ? }

7? }

復(fù)制代碼

構(gòu)建一個(gè)Action 創(chuàng)建函數(shù)钧排,如下:

復(fù)制代碼

1 function goLogin(payload) {

2 let loginInfo = {

3? ? ? ? ? ? type: namespace + '/login',

4? ? ? ? ? ? payload: {

5? ? ? ? ? ? ? userName: payload.userName,

6? ? ? ? ? ? ? password: payload.password

7? ? ? ? ? ? }

8? ? ? ? ? }

9? return loginInfo

10 }

11

12 //我們直接dispatch(goLogin()),就發(fā)送了一個(gè)action敦腔。

13 dispatch(goLogin())

復(fù)制代碼

10,dispatch

type dispatch = (a: Action) => Action

dispatching function 是一個(gè)用于觸發(fā) action 的函數(shù),action 是改變 State 的唯一途徑恨溜,但是它只描述了一個(gè)行為符衔,而 dipatch 可以看作是觸發(fā)這個(gè)行為的方式,而 Reducer 則是描述如何改變數(shù)據(jù)的糟袁。

在 dva 中柏腻,connect Model 的組件通過 props 可以訪問到 dispatch,可以調(diào)用 Model 中的 Reducer 或者 Effects系吭,常見的形式如:

1 dispatch({

2? ? type: namespace + '/login', // 如果在 model 外調(diào)用,需要添加 namespace,如果在model內(nèi)調(diào)用 無需添加 namespace

3? payload: {}, // 需要傳遞的信息

4 });

reducers 處理數(shù)據(jù)

effects? 接收數(shù)據(jù)

subscriptions 監(jiān)聽數(shù)據(jù)

3.3,使用antd

先安裝 antd 和 babel-plugin-import

1 npm install antd babel-plugin-import --save

2 # 或

3 yarn add antd babel-plugin-import

babel-plugin-import 也可以通過 -D 參數(shù)安裝到 devDependencies 中颗品,它用于實(shí)現(xiàn)按需加載肯尺。然后在 .webpackrc 中添加如下配置:

復(fù)制代碼

1 {

2? "extraBabelPlugins": [

3? ? ["import", {

4? ? ? "libraryName": "antd",

5? ? ? "libraryDirectory": "es",

6? ? ? "style": true

7? ? }]

8? ]

9 }

復(fù)制代碼

現(xiàn)在就可以按需引入 antd 的組件了沃缘,如 import { Button } from 'antd',Button 組件的樣式文件也會(huì)自動(dòng)幫你引入则吟。

3.4,配置.webpackrc

1,entry是入口文件配置

單頁類型:

1 entry: './src/entries/index.js',

多頁類型:

1 "entry": "src/entries/*.js"

2,extraBabelPlugins 定義額外的 babel plugin 列表槐臀,格式為數(shù)組。

3,env針對(duì)特定的環(huán)境進(jìn)行配置氓仲。dev 的環(huán)境變量是?development水慨,build 的環(huán)境變量是?production。

復(fù)制代碼

1 "extraBabelPlugins": ["transform-runtime"],

2 "env": {

3? development: {

4? ? ? extraBabelPlugins: ['dva-hmr'],

5? ? },

6? ? production: {

7? ? ? define: {

8? ? ? ? __CDN__: process.env.CDN ? '//cdn.dva.com/' : '/' }

9? ? }

10 }

復(fù)制代碼

開發(fā)環(huán)境下的 extraBabelPlugins 是?["transform-runtime", "dva-hmr"]敬扛,而生產(chǎn)環(huán)境下是?["transform-runtime"]

4,配置 webpack 的?externals?屬性

1 // 配置 @antv/data-set和 rollbar 不打入代碼

2 "externals": {

3? ? '@antv/data-set': 'DataSet',

4? ? rollbar: 'rollbar',

5 }

5,配置 webpack-dev-server 的 proxy 屬性晰洒。 如果要代理請(qǐng)求到其他服務(wù)器,可以這樣配:

復(fù)制代碼

1? proxy: {

2? ? "/api": {

3? ? ? // "target": "http://127.0.0.1/",

4? ? ? // "target": "http://127.0.0.1:9090/",

5? ? ? "target": "http://localhost:8080/",

6? ? ? "changeOrigin": true,

7? ? ? "pathRewrite": { "^/api" : "" }

8? ? }

9? },

復(fù)制代碼

6,disableDynamicImport

禁用 import() 按需加載啥箭,全部打包在一個(gè)文件里谍珊,通過 babel-plugin-dynamic-import-node-sync 實(shí)現(xiàn)。

7,publicPath

配置 webpack 的 output.publicPath 屬性急侥。

8,extraBabelIncludes

定義額外需要做 babel 轉(zhuǎn)換的文件匹配列表砌滞,格式為數(shù)組

9,outputPath

配置 webpack 的 output.path 屬性。

打包輸出的文件

1 config["outputPath"] = path.join(process.cwd(), './build/')

10,根據(jù)需求完整配置如下:

文件名稱是:.webpackrc.js,可根據(jù)實(shí)際情況添加如下代碼:

復(fù)制代碼

1 const path = require('path');

2

3 const config = {

4? entry: './src/entries/index.js',

5? extraBabelPlugins: [['import', { libraryName: 'antd', libraryDirectory: 'es', style: true }]],

6? env: {

7? ? development: {

8? ? ? extraBabelPlugins: ['dva-hmr'],

9? ? },

10? ? production: {

11? ? ? define: {

12? ? ? ? __CDN__: process.env.CDN ? '//cdn.dva.com/' : '/' }

13? ? }

14? },

15? externals: {

16? ? '@antv/data-set': 'DataSet',

17? ? rollbar: 'rollbar',

18? },

19? lessLoaderOptions: {

20? ? javascriptEnabled: true,

21? },

22? proxy: {

23? ? "/api": {

24? ? ? // "target": "http://127.0.0.1/",

25? ? ? // "target": "http://127.0.0.1:9090/",

26? ? ? "target": "http://localhost:8080/",

27? ? ? "changeOrigin": true,

28? ? }

29? },

30? es5ImcompatibleVersions:true,

31? disableDynamicImport: true,

32? publicPath: '/',

33? hash: false,

34? extraBabelIncludes:[

35? ? "node_modules"

36? ]

37 };

38 if (module.exports.env !== 'development') {

39? config["outputPath"] = path.join(process.cwd(), './build/')

40 }

41 export default config

復(fù)制代碼

更多 .webpackrc 的配置請(qǐng)參考 roadhog 配置坏怪。

3.5,使用antd-mobile

先安裝 antd-mobile 和 babel-plugin-import

1 npm install antd-mobile babel-plugin-import --save # 或

2 yarn add antd-mobile babel-plugin-import

babel-plugin-import 也可以通過 -D 參數(shù)安裝到 devDependencies 中贝润,它用于實(shí)現(xiàn)按需加載。然后在 .webpackrc 中添加如下配置:

1 {

2? "plugins": [

3? ? ["import", { libraryName: "antd-mobile", style: "css" }] // `style: true` 會(huì)加載 less 文件

4? ]

5 }

現(xiàn)在就可以按需引入antd-mobile 的組件了铝宵,如 import { DatePicker} from 'antd-mobile'打掘,DatePicker 組件的樣式文件也會(huì)自動(dòng)幫你引入。

四,整體架構(gòu)

我們根據(jù) url 訪問相關(guān)的 Route-Component捉超,在組件中我們通過 dispatch 發(fā)送 action 到 model 里面的 effect 或者直接 Reducer

當(dāng)我們將action發(fā)送給Effect胧卤,基本上是取服務(wù)器上面請(qǐng)求數(shù)據(jù)的,服務(wù)器返回?cái)?shù)據(jù)之后拼岳,effect 會(huì)發(fā)送相應(yīng)的 action 給 reducer枝誊,由唯一能改變 state 的 reducer 改變 state ,然后通過connect重新渲染組件惜纸。

當(dāng)我們將action發(fā)送給reducer叶撒,那直接由 reducer 改變 state,然后通過 connect 重新渲染組件耐版。如下圖所示:

數(shù)據(jù)流向

數(shù)據(jù)的改變發(fā)生通常是通過用戶交互行為或者瀏覽器行為(如路由跳轉(zhuǎn)等)觸發(fā)的祠够,當(dāng)此類行為會(huì)改變數(shù)據(jù)的時(shí)候可以通過 dispatch 發(fā)起一個(gè) action,如果是同步行為會(huì)直接通過 Reducers 改變 State 粪牲,如果是異步行為(副作用)會(huì)先觸發(fā) Effects 然后流向 Reducers 最終改變 State

重置models里的數(shù)據(jù):

1 dispatch({type:namespace+'/set',payload:{mdata:[]}});

? set是內(nèi)置的方法

Dva官方文檔? ? ? ? ? ? ? nginx代理部署Vue與React項(xiàng)目

五,問題記錄

5.1,路由相關(guān)的問題

1,使用match后的路由跳轉(zhuǎn)問題古瓤,版本routerV4

match是一個(gè)匹配路徑參數(shù)的對(duì)象,它有一個(gè)屬性params,里面的內(nèi)容就是路徑參數(shù)落君,除常用的params屬性外穿香,它還有url、path绎速、isExact屬性皮获。

問題描述:不能跳轉(zhuǎn)新頁面或匹配跳轉(zhuǎn)后,刷新時(shí)url所傳的值會(huì)被重置掉

不能跳轉(zhuǎn)的情況

復(fù)制代碼

1 const {ConnectedRouter} = routerRedux;

2

3 function RouterConfig({history}) {

4 const tests =({match}) =>(

5? ? <div>

6? ? ? <Route exact path={`${match.url}/:tab`} component={Test}/>

7? ? ? <Route exact path={match.url} component={Test}/>

8? ? </div>

9

10? );

11? return (

12? ? <ConnectedRouter history={history}>

13? ? ? <Switch>

14? ? ? ? <Route path="/login" component={Login}/>

15? ? ? ? <LocaleProvider locale={zhCN}>

16? ? ? ? ? <App>

17? ? ? ? ? ? <Flex>

18? ? ? ? ? ? ? <Switch>

19? ? ? ? ? ? ? ? <Route path="/test" component={tests }/>

20? ? ? ? ? ? ? ? <Route exact path="/test/bindTest" component={BindTest}/>

21? ? ? ? ? ?

22? ? ? ? ? ? ? </Switch>

23? ? ? ? ? ? </Flex>

24? ? ? ? ? </App>

25? ? ? ? </LocaleProvider>

26? ? ? </Switch>

27? ? </ConnectedRouter>

28? );

29 }

復(fù)制代碼

路由如上寫法,使用下面方式不能跳轉(zhuǎn),但是地址欄路徑變了

復(fù)制代碼

1 import { routerRedux} from 'dva/router';

2 ...

3?

4 this.props.dispatch(routerRedux.push({

5? ? ? pathname: '/test/bindTest',

6? ? ? search:queryString.stringify({

7? ? ? ? // ...query,

8? ? ? ? Code: code,

9? ? ? ? Name: name

10? ? ? })

11? ? }));

12

13 ...

復(fù)制代碼

能跳轉(zhuǎn),但是刷新所傳的參數(shù)被重置

復(fù)制代碼

1 const {ConnectedRouter} = routerRedux;

2

3 function RouterConfig({history}) {

4 const tests =({match}) =>(

5? ? <div>

6? ? ? <Route exact path={`${match.url}/bindTest`} component={BindTest}/>

7? ? ? <Route exact path={`${match.url}/:tab`} component={Test}/>

8? ? ? <Route exact path={match.url} component={Test}/>

9? ? </div>

10

11? );

12? return (

13? ? <ConnectedRouter history={history}>

14? ? ? <Switch>

15? ? ? ? <Route path="/login" component={Login}/>

16? ? ? ? <LocaleProvider locale={zhCN}>

17? ? ? ? ? <App>

18? ? ? ? ? ? <Flex>

19? ? ? ? ? ? ? <Switch>

20? ? ? ? ? ? ? ? <Route path="/test" component={tests }/>

21? ? ? ? ? ? ? </Switch>

22? ? ? ? ? ? </Flex>

23? ? ? ? ? </App>

24? ? ? ? </LocaleProvider>

25? ? ? </Switch>

26? ? </ConnectedRouter>

27? );

28 }

復(fù)制代碼

路由如上寫法,使用下面方式可以跳轉(zhuǎn),但是刷新時(shí)所傳的參數(shù)會(huì)被test里所傳的參數(shù)重置

復(fù)制代碼

1 ...

2

3 this.props.dispatch(routerRedux.push({

4? ? ? ? pathname: '/test/bindTest',

5? ? ? ? search:queryString.stringify({

6? ? ? ? ? // ...query,

7? ? ? ? ? Code: code,

8? ? ? ? ? Name: name

9? ? ? ? })

10 }));

11

12 ...

復(fù)制代碼

解決辦法如下:地址多加一級(jí),跳出以前的界面

路由配置

復(fù)制代碼

1 const {ConnectedRouter} = routerRedux;

2

3 function RouterConfig({history}) {

4 const tests =({match}) =>(

5? ? <div>

6? ? ? <Route exact path={`${match.url}/bind/test`} component={BindTest}/>

7? ? ? <Route exact path={`${match.url}/:tab`} component={Test}/>

8? ? ? <Route exact path={match.url} component={Test}/>

9? ? </div>

10

11? );

12? return (

13? ? <ConnectedRouter history={history}>

14? ? ? ? ? ? ? <Switch>

15? ? ? ? ? ? ? ? <Route path="/test" component={tests }/>

16? ? ? ? ? ? ? </Switch>

17? ? </ConnectedRouter>

18? );

19 }

復(fù)制代碼

調(diào)用

復(fù)制代碼

1 ...

2?

3 this.props.dispatch(routerRedux.push({

4? ? ? pathname: '/test/bind/test1',

5? ? ? search:queryString.stringify({

6? ? ? ? // ...query,

7? ? ? ? Code: code,

8? ? ? ? Name: name

9? ? ? })

10? ? }));

11

12 ...

復(fù)制代碼

5.2,箭頭函數(shù)this指向問題

箭頭函數(shù)的this定義:箭頭函數(shù)的this是在定義函數(shù)時(shí)綁定的,不是在執(zhí)行過程中綁定的纹冤。簡(jiǎn)單的說洒宝,函數(shù)在定義時(shí),this就繼承了定義函數(shù)的對(duì)象萌京。

深圳網(wǎng)站建設(shè)www.sz886.com

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末雁歌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子枫夺,更是在濱河造成了極大的恐慌将宪,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件橡庞,死亡現(xiàn)場(chǎng)離奇詭異较坛,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扒最,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門丑勤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吧趣,你說我怎么就攤上這事法竞。” “怎么了强挫?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵岔霸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我俯渤,道長(zhǎng)呆细,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任八匠,我火速辦了婚禮絮爷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梨树。我一直安慰自己坑夯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布抡四。 她就那樣靜靜地躺著柜蜈,像睡著了一般仗谆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跨释,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天胸私,我揣著相機(jī)與錄音,去河邊找鬼鳖谈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛阔涉,可吹牛的內(nèi)容都是我干的缆娃。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瑰排,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼贯要!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起椭住,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤崇渗,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后京郑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宅广,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年些举,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了跟狱。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡户魏,死狀恐怖驶臊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情叼丑,我是刑警寧澤关翎,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站鸠信,受9級(jí)特大地震影響纵寝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜症副,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一店雅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧贞铣,春花似錦闹啦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春琳袄,著一層夾襖步出監(jiān)牢的瞬間江场,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工窖逗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留址否,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓碎紊,卻偏偏與公主長(zhǎng)得像佑附,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仗考,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • dva.js 簡(jiǎn)介 dva 是阿里前端架構(gòu)師 sorrycc 帶 team 研發(fā)的一套輕量級(jí)前端框架音同,其目的是盡量...
    那顆星_fcaf閱讀 3,701評(píng)論 0 24
  • 初始化 安裝 dva-cli 用于初始化項(xiàng)目: 創(chuàng)建項(xiàng)目目錄,并進(jìn)入該目錄: 然后運(yùn)行 npm start 或 y...
    何以安于心閱讀 490評(píng)論 0 1
  • dva框架的使用詳解及Demo教程 在前段時(shí)間秃嗜,我們也學(xué)習(xí)講解過Redux框架的基本使用权均,但是有很多同學(xué)在交流群里...
    光強(qiáng)_上海閱讀 61,200評(píng)論 5 55
  • 有些人錯(cuò)過就是錯(cuò)過了叽赊,沒人會(huì)一直在原地等你。而且橡类,你也沒表露出對(duì)她喜歡的感情蛇尚,她又何來的會(huì)為你靜候。 程浩和徐靜蕾...
    星簇閱讀 504評(píng)論 0 3
  • 001 了解自己顾画,并不是一件很容易的事情取劫,把目光移到自己,多放一些關(guān)注在自己身上研侣。 002 把目光集中到“現(xiàn)在”這...
    菜菜子Yonan閱讀 354評(píng)論 0 1