programmer-yang / blog

Blog
19 stars 0 forks source link

关于dva1.x升级到2.x #1

Open programmer-yang opened 6 years ago

programmer-yang commented 6 years ago

dva 1.x => 2.x

记录自己在升级dva到2.x中遇到的问题,如果发现写的不对的地方请不要笑,及时沟通,新手司机上路 ^_^

参考资料

问题一:location.query

由于history版本变动,location不在包含有query对象,需要手动处理

yarn add query-string
import queryString from 'query-string';
history.listen((location) => {
const query = queryString.parse(location.search);
// console.log(query);
});

问题二 嵌套路由

R4里修改了对于嵌套路由的实现方式

// old
<Router history={history}>
  <Route path="/home" component={Container}>
    <Route path="/home/page1" component={Page1} />
    <Route path="/home/page2" component={Page2} />
  </Route>
</Router>

// new
<Router history={history}>
  <Route path="/home">
    <Container>
      <Route path="/home/page1" component={Page1} />
      <Route path="/home/page2" component={Page2} />
    </Container>
  </Route>
</Router>

// or
<Router history={history}>
  <Route path="/home" render={(props) => {
    return (
      <Container {...props}>
        <Route path="/home/page1" component={Page1} />
        <Route path="/home/page2" component={Page2} />
      </Container>
    );
  }}>
  </Route>
</Router>

最后一种写法主要用于Container组件中需要用到history location match的情况

R4取消了关于on****钩子函数,相关实现可以在Container容器组件的生命周期里来做

关于Redirect

R4 删除了IndexRedirect,需要重定向的时候使用Redirect Redirectto属性现在和Route的path属性一样,适配所有能适配上的路径

// error
<Switch>
<Redirect from="/home" to="/home/page1" />
<Route path="/home/page1" component={Page1} />
<Route path="/home/page2" component={Page2} />
</Switch>

这样的写法会报错,因为form的值会适配到/hom/page1 /home/page2这样的所有子路径,就会出现理论上的递归跳转(会报错,不会递归,只是形容一下) 给Redirect加上exact属性就好了

<Switch>
<Redirect exact from="/home" to="/home/page1" />
<Route path="/home/page1" component={Page1} />
<Route path="/home/page2" component={Page2} />
</Switch>

关于Link R4的Link拆分成了两个:Link NavLink 简单的跳转使用Link 特殊的跳转(有选中样式需求:activeClassName)使用NavLink 参考 有使用到QueueAnimLink添加动画的地方要修改为NavLink

问题三 dispatch effect 回调

在dva2.x中新增了effect返回promise的特性,现在写回调逻辑越来yue方便了

dispatch({ type: 'home/xxx' })
  .then(({ data = {} }) => {
    console.log(data);
  })
  .catch((e) => {
    // error
    console.log(e);
  });

问题四 关于使用browserHistory

在之前的版本中,我们去掉path中的#的方式是

import {browserHistory} from 'dva/router';
const app = dva({
history: browserHistory,
});

在2.x版本中需要修改为:

yarn add history
import createHistory from 'history/createBrowserHistory';
const history = createHistory();
const app = dva({
  history,
});

这里到将来可能还会有一些修改,但目前这么使用是可行的

其他相关问题

关于webpack插件html-webpack-plugin

背景:

dva之前的版本不支持文件hash,现在dva已经支持了这个功能 链接 使用方式是在.roadhog中添加hash:true的配置,默认约定在src下有一个index.ejs的模板

问题

Uncaught TypeError: Cannot read property '__reactInternalInstance$ufa3tpnn4i' of null
    at Object.getClosestInstanceFromNode (8:113)
    at findParent (
<script src="./index.js"></script>
<script type="text/javascript" src="/index.js?a6d74e09fa325aa523a2"></script>

解决方式

问题就是引入了两次index.js 方法一:删除模板中的index.js的引用 方法二:

module.exports = (webpackConfig) => {
  const htmlWebpackPlugin = new HtmlWebpackPlugin({
    filename: 'index.html',
    template: `!!html!./src/${process.env.LOCAL_DIR}/index.html`,
    hash: true,
    inject: false,
    minify: {
      collapseBooleanAttributes: true,
    },
  });
  webpackConfig.plugins.push(htmlWebpackPlugin);
  return webpackConfig;
};

webpack.config.js的关于html-webpack-plugin的配置内容里添加inject: false 参考

inject: false,会使注入失效,如果需要hash请使用方法一

waynerQiu commented 6 years ago

棒棒棒哒

lhqa-stars commented 6 years ago

写得很好,6666

programmer-yang commented 6 years ago

能帮到大家才是最好的

DoubleMingZMM commented 6 years ago

image 这边有个问题,升级到2.0的时候,发现报了这个错以及提示 Cannot find module "./router",请问这个要怎么解决。

programmer-yang commented 6 years ago

@DoubleMingZMM 不好意思,今天才看到你的问题,请问现在问题解决了吗? dva2.x默认使用了router4,找不到可能是因为解析不了原来的写法,尝试在router.jsx里写一个router4最基础的路由看看能找到不

youyuxun commented 6 years ago

请教一下,有办法统一处理location.query的方法吗,类似全局钩子的?

programmer-yang commented 6 years ago

@youyuxun 其实手动处理起来还是蛮简单的 如果想统一处理的话可以考虑在最上层的容器组件里处理掉,然后传递到子组件中去 比如:

<BrowserRouter>
  <Container /> // 在这个容器里统一处理
</BrowserRouter>
import React, { Component } from 'react'
import queryString from 'query-string'

class Container extends Component {
  componentWillMount() {
    const { location } = this.props
    // 在这里处理
    const queryData = queryString.parse(location.search)
    this.setState({ queryData })
  }
  render() {
    const { queryData } = this.state
    return (
      <div>
        <Route path="/about" render={() => <About {...{ queryData }} />} />
      </div>
    )
  }
}

export default Container

还有很多种别的写法,参考下吧 ^_^

tsejx commented 6 years ago

更正:问题二 嵌套路由 locatgion => location

programmer-yang commented 6 years ago

@tsejx 谢谢,已经修改

songqiaoyi commented 6 years ago

路由嵌套非常给力

programmer-yang commented 6 years ago

@songqiaoyi router4版本把route修改成组件后变的很自由了,可以随意拼装,跟积木一样,哈哈

pengshaosu commented 5 years ago

location.query 我的项目升级到@dva2.x版本了,为何location.query依然能够使用,并未出现你们说的location不包含query?

wang-yi-bit64 commented 8 months ago

mark感谢分享