打造开箱即用的 react 移动端框架(二)
先前那篇文章已经讲了有关 React 移动的配置,接下来讲讲 dva 和 react-keeper 如何配置到移动端框架
该脚手架基于 create react app
创建,方便快速搭建 react 移动端项目
上篇文章地址:# 打造开箱即用的 react 移动端框架
gitHub: react-mobile
在线地址:react-mobile-Domesy
配置dva
首先,我们只需要 dva-core dva-loading
和react-redux
配合使用即可
执行命令:
yarn add react-redux
yarn add dva-core dva-loading
创建 dva.js
这里只说一下大体思路,我们需要创建两个方法,一个是 createApp, 一个是 getDispatch
createApp 的作用就是将 数据注入到 model,然后设置 store
getDispath 的作用就是,将 dispatch 导出,让其有操作的方法
我们直接上代码:
import { create } from 'dva-core'
import createLoading from 'dva-loading'
let app
let store
let dispatch
let registered
function createApp(opt) {
opt.onAction = []
app = create(opt)
app.use(createLoading({}))
// 注入model
if (!registered) {
opt.models.forEach((model) => app.model(model))
}
registered = true
app.start()
// 设置store
store = app._store
app.getStore = () => store
app.use({
onError(err) {
console.log(err)
},
})
// 设置dispatch
dispatch = store.dispatch
app.dispatch = dispatch
return app
}
export default {
createApp,
getDispatch() {
return app.dispatch
},
}
创建models
之后我们单独在src
下单独创建 model
然后将其导出就ok了
import app from './app'
export default [
app,
]
集中配置
在之后,我们只需要在 App.tsx
中使用react-redux
的Provider
引用下就完成了
import React from 'react';
import { Provider } from 'react-redux'
import models from './models'
import dva from './utils/dva'
const app = dva.createApp({
models,
})
const store = app.getStore()
const App: React.FC = () => {
return (
<Provider store={store}>
...
</Provider>
);
};
export default App
配置持久化
当我们做完上部操作后,dva就已经配置好了,但此时会有一个问题,那就是页面刷新会使dva
中的数据初始化,这里建议移动端做持久化配置
插件: dva-model-persisit
引入时注意
本地存储 dva-model-persist/lib/storage
会话存储 dva-model-persist/lib/storage/session
建议使用 会话存储
并且 需要在 app.start()之前进行配置
mport { persistEnhancer } from 'dva-model-persist';
import storage from 'dva-model-persist/lib/storage/session';
function createApp(opt) {
...
app.use({
extraEnhancers: [
persistEnhancer({
key: 'model',
storage
})
],
})
...
return app
}
配置好后,重新启动下项目就行了
如果有小伙伴对 dva 不太会使用,建议看看这篇文章:Dva 实战演练
路由 React-Keeper
关于 react-keeper 有这篇文章: 比React-Router更适合你的单页面路由器
这里就不多废话了,直接配置就好
参数配置
- index : 入口组件
- miss : 地址不匹配时渲染的组件
- cache : 缓存标记
- redirect : 重定向地址 (当组件满足渲染条件时才会执行)
- path : 匹配地址规则
- component :要匹配的组件
- loadComponent : 动态加载组件
- enterFilter : 挂载过滤器
- leaveFilter : 卸载过滤器
- offDirtyCheck : 关闭脏检查。React-Keep会默认启用脏检查,以避免地址变更时不必要的渲染
<HashRouter>
<div>
<Route index component={Home} path='/'/>
<Route cache component={Host} path='/host' />
<Route miss path='/aboutus' component={AboutUs}/>
<Route path='/other' redirect='/redirect'/>
</div>
</HashRouter>
简单配置
我们希望有单独一个路由文件,然后进行配置,所以结构上为 数组,我们直接穿件文件 src/router
大致结构长这样
import _404Page from '@/pages/_404';
import Index from '@/pages/Index';
const routes = [
{
path: '/', // 路径地址
index: true, //第一个页面 index 为 true
title: 'react-mobile-Domesy', // 页面标题
component: Index, // 引入的组件
},
{
path: '/Content',
component: Content
},
...
{ // 可以配置些其他公共页面,如404页面
path: '/_404',
miss: true,
component: _404Page
},
]
之后我们需要,把他扔到 App.tsx
文件中,并单独创个 Router
组件来接收
import React from 'react';
import { Provider } from 'react-redux'
import './App.less';
import Router from './utils/Router';
import models from './models'
import dva from './utils/dva'
import routes from './router';
const app = dva.createApp({
models,
})
const store = app.getStore()
const App: React.FC = () => {
return (
<Provider store={store}>
<div className="App">
<Router routes={routes} />
</div>
</Provider>
);
};
export default App;
最后,我们只需要将 Router 这个组件写好,将接收到的数组遍历下就行了
import React, { Component } from 'react';
import { Modal } from '@/utils';
import { HashRouter as Router, Route } from 'react-keeper';
class Index extends Component {
constructor(props){
super(props);
this.state = {
routes: []
}
}
render(){
const { routes } = this.props;
return (
<Router>
<div>
{
routes.map((item, index) => (
<Route
...,
component={item.component} // 有问题
key={index}
/>
))
}
</div>
</Router>
)
}
}
export default Index
这里有一个致命的缺陷,component 不支持 Hook,也就是不支持函数式写法,必须 class组件或者无状态的函数式组件,但后面包裹的第二层可以使用Hook
其实除了这一个问题以外,我们希望 react-keeper
还可以动态加载,既然要动态加载就需要使用到loadComponent
这个参数了~
为了解决上述两个问题,我想了一个方法(不一定是最好的解决方法),写一个公共页面,把 item.component 当参数传入下去,这就就可以使用Hooks的同时,我们也可以通过这个公共页面做一些有关项目的整体操作
在 src/pages
下创建 Home.jsx
import React, { Component } from 'react'
class Home extends Component {
render() {
const Component = this.props.children
return (
<>
<Component />
</>
)
}
}
export default Home
这样就ok了,同时我们在这个页面可以创建一些公共的组件,比如说水印,评价模块,等~
差点忘了, item.component
需要通过 children
这个属性传递
最后,在附上配置完后 Router
模块
import React, { Component } from 'react';
import { Modal } from '@/utils';
import { HashRouter as Router, Route } from 'react-keeper';
import Home from '@/pages/Home';
/**
* @module 路由模块
*
* @param routes 数组,包含所需要的每项
* @param exact 是否完全匹配(默认完全匹配)
* cache属性可以添加属性值,React-Keeper支持的属性值有root(default)、parent。
* @param catch 页面缓存 支持两种形式 一种是root(默认),这种为永久缓存,只要根组件不解绑,页面将永久缓存,另一种是parent为父组件缓存,在父组件不解绑的情况下会维持缓存状态
* @param path 页面路径
* @param title 页面标题
* @param component 组件
*/
class Index extends Component {
constructor(props){
super(props);
this.state = {
routes: []
}
}
componentDidMount = () => {
const { routes } = this.props;
if(Object.keys(routes).length === 0){
Modal.alert('暂未配置路由, 请去配置')
return;
}
}
render(){
const { routes } = this.props;
return (
<Router>
<div>
{
routes.map((item, index) => (
<Route
exact={item.exact ? false : true}
index={item.index ? true : false}
miss={item.miss ? true : false}
path={item.path}
cache={item.cache ? item.cache === "parent" ? "parent" : "root" : false}
children={item.component}
loadComponent = {(callback) => {
item.title ? document.title = item.title : '';
callback(Home)
}}
key={index}/>
))
}
</div>
</Router>
)
}
}
export default Index
最后
dva 和 react-keeper 就配置成功了,这样一个开箱即用的 React 移动端框架就配置完成了~
本文仅提供参考,若有不对的地方,欢迎在评论区留下您宝贵的意见
转载自:https://juejin.cn/post/7054072972968984613