Taro与小程序

Elux可以运行在任何JS环境中,所以也可以用来驱动小程序。

Taroopen in new window是一个使用 React/Vue 作为DSL语言,转译为各种小程序的底层框架,正好可以用来作为Elux在小程序领域的UI框架

开发脚手架

Taro官方提供了各种小程序的开发脚手架,将Elux作为一个普通的NPM包,安装并配置即可。

Cli工程向导中的Taro项目模版已经配置好,开箱即用。如果想手动配置,参见文末。

使用Elux

开发小程序的Elux工程与其它工程基本一样,只需要少量改动:

  1. 修改入口文件app.tsx
import {createApp} from '@elux/react-taro';
import {appConfig} from './Project';

function App(props: any) {
  const Provider = createApp(appConfig);
  return <Provider>{props.children}</Provider>;
}

export default App;
import {createApp} from '@elux/vue-taro';
import {appConfig} from './Project';

const App = createApp(appConfig);

export default App;
  1. 修改src/Project.ts
export const appConfig: AppConfig = setConfig({
    //因为小程序的路由与目录结构是强关联的,此处可以与Elux中的虚拟路由做映射
    NativePathnameMapping: {
      in(nativePathname) {//小程序Url转化为内部虚拟Url
        if (nativePathname === '/') {
          nativePathname = '/modules/article/pages/list';
        }
        return nativePathname.replace(/^\/modules\/(\w+)\/pages\//, '/$1/');
      },
      out(internalPathname) {//内部虚拟Url转化为小程序Url
        return internalPathname.replace(/^\/(\w+)\//, '/modules/$1/pages/');
      },
    },
})

// 小程序原生Url => elux虚拟Url
// /modules/article/pages/list => /article/list
  1. 增加相应的Page文件。因为Elux是基于微模块的架构,所以Page文件最好也放在对应的模块中。我们在每个微模块下建立pages目录,用来存放Page:
├── src
│    ├── modules
│    │      ├── article
│    │      │   ├── pages //增加pages目录
│    │      │   │     ├── list.tsx //增加小程序专用page文件
│    │      │   │     └── detail.tsx //增加小程序专用page文件
│    │      │   ├── views
│    │      │   ├── model.ts
│    │      │   └── index.ts
│    │      ├── my
│    │      └── stage
│    ├── Global.ts
│    ├── Project.ts
│    ├── app.tsx
│    └── app.config.ts

小程序专用page文件,其实千篇一律,只需要导出EluxPage即可:

import {EluxPage} from '@elux/react-taro';

//Taro提供的配置页面方法
definePageConfig({
    navigationBarTitleText: '文章列表',
});

export default EluxPage;
  1. 最后我们修改小程序配置文件src/app.config.ts
//该方法由Taro提供
export default defineAppConfig({
  pages: [
    'modules/article/pages/list',
    'modules/article/pages/detail',
    'modules/my/pages/userSummary',
    'modules/stage/pages/login',
  ],
  tabBar: {
    list: [
      {
        pagePath: 'modules/article/pages/list',
        text: '文章',
      },
      {
        pagePath: 'modules/my/pages/userSummary',
        text: '我的',
      },
    ],
  },
  window: {
    navigationStyle: 'custom',
  },
});

使用分包加载

使用Elux工程开发小程序支持小程序原生的分包加载,方法如下:

  1. 修改src/Project.ts

     import stage from '@/modules/stage';
     import article from '@/modules/article';
     import my from '@/modules/my';
     //要使用分包加载的微模块,只需引入类型
     import type {Shop} from '@/modules/shop';
    
     export const ModuleGetter = {
         stage: () => stage,
         article: () => article,
         my: () => my,
         //要使用分包加载的微模块,返回一个空对象即可
         shop: () => ({} as Shop),
     };
    
  2. 配置小程序分包加载src/app.config.ts

    //该方法由Taro提供
    export default defineAppConfig({
        subPackages: [
         {
           root: 'modules/shop',
           pages: ['pages/goodsList'],
         },
       ],
    })
    

使用Elux虚拟路由

Elux虚拟路由提供了4个路由跳转方法:(参见router)

  • push:在指定栈中新增一条历史记录,并跳转路由。
  • replace:在指定栈中替换当前历史记录,并跳转路由。
  • relaunch:清空指定栈中的历史记录,并跳转路由。
  • back:回退指定栈中的历史记录,并跳转路由。

它们可以联动小程序的原生路由:

  • push 联动navigateTo
  • replace 联动redirectTo
  • relaunch 如果是TabPage联动switchTab,否则联动reLaunch
  • back 联动navigateBack

默认情况下

  • 仅当路由targetwindow时,才会联动原生路由。
  • 当路由targetpage时,不通知原生路由,此时相当于运行在小程序中的单页。

路由拦截与守卫

Elux虚拟路由本身支持路由拦截与守卫,但必须是虚拟路由先发起的跳转,如果直接操作原生路由是无法拦截的。

手动安装Elux

Cli工程向导中的Taro项目模版基于Taro特定版本制作,开箱即用,但可能版本滞后。如果想使用官方最新版本,也可以自己在Taro项目中安装Elux,步骤如下:

  1. 使用taro的cli命令生成新项目(使用Typescript)

  2. 增加elux相关依赖,修改./package.json:

    {
      "peerDependencies": {
        "query-string": "*" //taro中自带
      },
      "dependencies": {
        //...
        "@elux/react-taro": "^2.0.0",
        "path-to-regexp": "^3.0.0" //taro中只能使用v3版本
      },
      "devDependencies": {
        //...
        "@elux/cli-utils": "^2.0.0"
      },
      "resolutions": {
        "@types/react": "^17.0.0" //安装多版本type可能导致ts报错
      }
    }
    
    
  3. 修改./babel.config.js 为:

     module.exports = {
       presets: [
         [
           'taro',
           {
             framework: 'react',
             ts: true,
             loose: false,
             decoratorsBeforeExport: true,
             decoratorsLegacy: false,
           },
         ],
       ],
     };
    
  4. 修改./config/index.js:

     const path = require('path');
     const srcPath = path.resolve(__dirname, '..', 'src');
     const {getLocalIP, getCssScopedName} = require('@elux/cli-utils');
    
     const config = {
       //...
       sourceRoot: 'src',
       outputRoot: 'dist',
       alias: {
         '@': srcPath,
       },
       plugins: ['@tarojs/plugin-html'],
       defineConstants: {
         'process.env.PROJ_ENV': JSON.stringify({
           ApiPrefix: `http://${getLocalIP()}:3003/`,
           StaticPrefix: `http://${getLocalIP()}:3003/`,
         }),
       },
       //...
       mini: {
         //...
         postcss: {
           //...
           cssModules: {
             enable: true,
             config: {
               namingPattern: 'module',
               generateScopedName(localName, mfileName) {
                 return getCssScopedName(srcPath, localName, mfileName);
               },
               localIdentContext: srcPath,
             },
           },
         },
       },
       h5: {
         //...
         router: {
           mode: 'browser',
         },
         postcss: {
           //...
           cssModules: {
             enable: true,
             config: {
               namingPattern: 'module',
               generateScopedName(localName, mfileName) {
                 return getCssScopedName(srcPath, localName, mfileName);
               },
               localIdentContext: srcPath,
             },
           },
         },
       }
     };
    








     
     
     
     
     
     
     
     
     
     





     
     
     
     
     
     
     
     
     
     




     
     
     


     
     
     
     
     
     
     
     
     
     



  5. 对于react项目,dev环境下可以关闭overlay,修改./config/dev.js:

     module.exports = {
       env: {
         NODE_ENV: '"development"',
       },
       defineConstants: {},
       mini: {},
       h5: {
         webpackChain(chain) {
           chain.plugin('fastRefreshPlugin').tap(() => [{overlay: false}]);
         },
       },
     };
    
  6. 如果你想使用Elux的代码风格,可以安装:

    • @elux/eslint-plugin
    • @elux/stylelint-config