likes
comments
collection
share

打造开箱即用的 react 移动端框架(二)

作者站长头像
站长
· 阅读数 55

先前那篇文章已经讲了有关 React 移动的配置,接下来讲讲 dva 和 react-keeper 如何配置到移动端框架

该脚手架基于 create react app 创建,方便快速搭建 react 移动端项目

上篇文章地址:# 打造开箱即用的 react 移动端框架

gitHub: react-mobile

在线地址:react-mobile-Domesy

配置dva

首先,我们只需要 dva-core dva-loadingreact-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-reduxProvider引用下就完成了

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
评论
请登录