一,介紹與需求分析
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