【前端】移动端工程结构最佳实践(v4/v5)

阅读之前

你应该:

  • 了解node与npm相关内容
  • 了解lerna包管理工具的相关内容
  • 了解git仓库的相关内容
  • 了解rollup的相关内容

工程结构包示例

Vue项目结构包下载-v4.7.x
Vue项目结构包下载-v5.2.x

工程结构详解

工程结构
├── packages
│   ├── kunlun-mobile-boot
│   │   ├── package.json
│   │   ├── public
│   │   │   ├── favicon.ico
│   │   │   └── index.html
│   │   ├── src
│   │   │   ├── main.ts
│   │   │   └── shim-vue.d.ts
│   │   ├── tsconfig.json
│   │   └── vue.config.js
│   ├── kunlun-module-mobile-demo
│   │   ├── scripts
│   │   │   ├── postpublish.js
│   │   │   └── prepublish-only.js
│   │   ├── src
│   │   │   ├── index.ts
│   │   │   └── shim-vue.d.ts
│   │   ├── index.ts
│   │   ├── package.json
│   │   ├── rollup.config.js
│   │   └── tsconfig.json
│   └── kunlun-modules-mobile-demo
│       ├── scripts
│       │   ├── build.config.js
│       │   ├── postpublish.js
│       │   └── prepublish-only.js
│       ├── packages
│       │   ├── module-demo1
│       │   │   ├── index.ts
│       │   │   ├── package.json
│       │   │   ├── rollup.config.js
│       │   │   └── src
│       │   │       ├── index.ts
│       │   │       └── shim-vue.d.ts
│       │   ├── module-demo2
│       │   │   ├── index.ts
│       │   │   ├── package.json
│       │   │   ├── rollup.config.js
│       │   │   └── src
│       │   │       ├── index.ts
│       │   │       └── shim-vue.d.ts
│       │   └── module-dependencies
│       │       ├── index.ts
│       │       ├── package.json
│       │       └── src
│       │           └── dependencies.ts
│       ├── lerna.json
│       ├── tsconfig.json
│       └── package.json
├── lerna.json
└── package.json

壳工程

├── packages
│   └── ......
├── lerna.json
└── package.json

壳工程仅用于将多个包进行统一安装,并通过lerna包管理工具进行相关的软链接操作。

壳工程包含了除了node和npm外其他相关的安装依赖,如lerna、rimraf等。这样可以避免由于开发环境差异带来的一系列问题。

我们建议所有开发人员均使用相同的壳工程进行开发,因此,我们有必要将其提交并推送到git远程仓库进行共享。

在壳工程目录下执行npm install命令即可完成一系列安装操作。

需要注意的是,lerna.json中定义了所有需要统一安装的子工程路径,安装前需要确认是否满足当前需要,但这些修改都应该只在本地完成,而不应该推送到git远程仓库。

安装完成后,所有公共依赖均会安装在壳工程的node_modules目录下,每个子工程的node_modules中仅包含软链接目录。并且在壳工程的node_modules目录下不会出现本地已经存在的工程依赖。

单工程包管理

├── packages
│   └── kunlun-module-mobile-demo
│       ├── scripts
│       │   ├── postpublish.js
│       │   └── prepublish-only.js
│       ├── src
│       │   ├── index.ts
│       │   └── shim-vue.d.ts
│       ├── index.ts
│       ├── package.json
│       ├── rollup.config.js
│       └── tsconfig.json
├── lerna.json
└── package.json

作为一个独立的工程,它可以是一个项目的总工程,也可以是多个项目共同使用的子工程。这也是最常见的工程包结构。

通常情况下,kunlun-module-mobile-demo工程会使用一个独立的git仓库进行管理。

通过kunlun-module-mobile-demo打包生成的@kunlun/module-mobile-demo包,将可以被发布到npm仓库或其他地方,供其他工程或项目使用。

在启动工程中的package.json中添加"@kunlun/module-mobile-demo": "~1.0.0"相关依赖进行引入。并在入口文件main.ts中导入相关的js和css相关内容。

如示例中所示:

// 按需引入
import '@kunlun/module-mobile-demo/dist/kunlun-module-mobile-demo.css';

import '@kunlun/module-mobile-demo';

需要注意的是,在本地开发中,css文件相关内容应该是被临时注释的,因为通过import '@kunlun/module-mobile-demo';已经将相关内容引入,无需使用打包好的css文件。

多工程包管理

├── packages
│   └── kunlun-modules-mobile-demo
│       ├── scripts
│       │   ├── build.config.js
│       │   ├── postpublish.js
│       │   └── prepublish-only.js
│       ├── packages
│       │   ├── module-mobile-demo1
│       │   │   ├── index.ts
│       │   │   ├── package.json
│       │   │   ├── rollup.config.js
│       │   │   └── src
│       │   │       ├── index.ts
│       │   │       └── shim-vue.d.ts
│       │   ├── module-mobile-demo2
│       │   │   ├── index.ts
│       │   │   ├── package.json
│       │   │   ├── rollup.config.js
│       │   │   └── src
│       │   │       ├── index.ts
│       │   │       └── shim-vue.d.ts
│       │   └── module-mobile-dependencies
│       │       ├── index.ts
│       │       ├── package.json
│       │       └── src
│       │           └── dependencies.ts
│       ├── lerna.json
│       ├── tsconfig.json
│       └── package.json
├── lerna.json
└── package.json

与单工程包管理类似,多工程包管理方案为了解决整体结构复杂,并且功能需要做最小化拆分的场景。在多工程包中提供的module-dependencies作为整个工程包的总入口向外提供功能。

如示例中所示:

// 视情况按需引入
// import '@kunlun/module-mobile-demo/dist/kunlun-module-mobile-demo1.css';
// import '@kunlun/module-mobile-demo/dist/kunlun-module-mobile-demo2.css';

import '@kunlun/modules-mobile-dependencies';

与单工程包唯一的区别在于启动工程的导入方式有所不同,仅需通过import '@kunlun/modules-mobile-dependencies';导入所有功能即可。在总入口处将对所有子工程包进行统一的导出并且包含了对应的css相关内容。

特别的是,如果多个工程间的css样式出现冲突,但又需要依赖js文件时,css相关内容将不能在总入口处进行导入,需要放在对应的启动工程中进行导入处理。原则上,我们应该避免这种情况的发生。

启动工程

├── packages
│   └── kunlun-mobile-boot
│       ├── package.json
│       ├── public
│       │   ├── favicon.ico
│       │   └── index.html
│       ├── src
│       │   ├── main.ts
│       │   └── shim-vue.d.ts
│       ├── tsconfig.json
│       └── vue.config.js
├── lerna.json
└── package.json

作为vue项目的启动工程,它应该仅用于工程组合,即选择性的使用某几个工程进行启动。

rollup脚本简述

通过package.json构建所需工程名称

const buildName = (name) => {
  const libraryName = name.replace('@', '').replace('/', '-');
  const pathName = libraryName.substring(packagePrefix.length);
  const camelCaseName = libraryName.replace(/-(\w)/g, (all, letter) => letter.toUpperCase());
  return { libraryName, pathName, camelCaseName };
};

使用方法:

import pkg from './package.json';

const res = buildName(pkg.name);
const libraryName = res.libraryName;

转换结果:@kunlun/module-mobile-demo -> kunlun-module-mobile-demo.esm.js

多工程包构建脚本的使用

方法签名
function rollupConfig(name = '', external = [], hasSCSS = true, extendPlugins)
示例脚本
import pkg from './package.json';
import rollupConfig from '../../scripts/build.config.js';

export default rollupConfig(pkg.name, [
  'vue',
  'lodash-es',
  'vant',
  '@ant-design/icons-vue',
  '@kunlun/mobile-dependencies',
  '@kunlun/vue-ui-mobile-vant'
], false);
  • pkg.name:通过当前路径的package.json获取name属性。
  • external:打包时排除当前工程中导入的第三方包,原则上需要全部排除,否则会出现内存变量不一致的问题。
  • hasSCSS:是否进行scss编译。当使用scss时,必须开启。
  • extendPlugins:扩展插件。

Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/49.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

Like (0)
nation's avatarnation数式员工
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • 如何实现页面间的跳转

    介绍 在日常的业务中,我们经常需要在多个模型的页面之间跳转,例如从商品的行可以直接点击链接跳转到类目详情,还有查看该订单发起的售后单列表,这里将给大家展示如何在oinone中如何实现这些功能。 方法一、通过界面设计器的无代码能力配置 表格行跳转到表单页/详情页 拖入一个跳转动作到表格行,保存动作后,在左侧的动作属性面板底部有个请求配置,里面的上下文属性就是配置跳转参数的地方,点击添加按钮可以增加一行参数 点击添加按钮后,可以看到新增了一行,行内有2个输入框,左侧输入框为目标视图模型的字段,右侧输入框为当前视图模型的表达式 注意 表达式中activeRecord关键字代表当前行的数据对象 “上下文”相关知识点 当前页面的模型和跳转后的页面模型相同的情况下,会字段带上当前行数据的id作为路由参数 上下文是从当前页面跳转到下个页面带的自定义参数 上下文会作为跳转后的页面数据加载函数的入参,后端的该函数需要根据该条件查询到数据返回给前端,典型的例子就是编辑页,根据id查询对象的其他字段信息返回 跳转后页面的数据加载函数可以在动作场景的时候选择加载函数,也可以在页面的加载函数处设置 方法二、通过低代码方式在自定义代码中调用 oinone提供了内置函数executeViewAction实现该功能 import { DefaultComparisonOperator, executeViewAction, QueryExpression, RuntimeViewAction, ViewActionTarget, ViewType } from '@kunlun/dependencies'; export class JumpActionWidget { protected goToObjectView() { executeViewAction( { viewType: ViewType.Form, moduleName: 'resource', model: 'resource.ResourceCountry', name: 'redirectUpdatePage', target: ViewActionTarget.Router } as RuntimeViewAction, undefined, undefined, { // 此处为id参数,目前只有表单和详情页需要 id: '12223', // 此处为上下文参数,context内对象的key是目标页面需要传递的默认值 context: JSON.stringify({code: 'xxx'}), // 此处为跳转后左侧菜单展开选中的配置 menu: JSON.stringify({"selectedKeys":["国家"],"openKeys":["地址库","地区"]}) } ); } protected goToListView() { const searchConditions: QueryExpression[] = []; searchConditions.push({ leftValue: ['countryCode'], // 查询条件的字段 operator: DefaultComparisonOperator.EQUAL, right: 'CN' // 字段的值 }); executeViewAction( { viewType: ViewType.Table, moduleName: 'resource', model: 'resource.ResourceCity', name: 'resource#市', target: ViewActionTarget.OpenWindow } as RuntimeViewAction, undefined, undefined, { // searchConditions相当于domain,不会随页面搜索项重置动作一起被清空 searchConditions: encodeURIComponent(JSON.stringify(searchConditions)), // searchBody的字段会填充搜索区域的字段组件,会随页面搜索项重置动作一起被清空 searchBody: JSON.stringify({code: 'CN'}), menu: JSON.stringify({"selectedKeys":["国家"],"openKeys":["地址库","地区"]}) } ); } } 扩展知识点 为什么executeViewAction跳转到的新页面不是入参的moduleName属性对应的模块? 答:跳转后所在的模块优先级为: 第一个入参的resModuleName属性对应的模块 执行executeViewAction时所在的模块 第一个入参的moduleName属性对应的模块 如何快速获取选中菜单的值? 答:先通过页面菜单手动打开页面,然后在浏览器自带调试工具的控制台执行decodeURIComponent(location.href),其中的menu参数就是我们需要的值

    2024年5月13日
    4.2K00
  • 左树右表默认选择第一行

    import { BaseElementWidget, Widget, SPI, ViewType, TableSearchTreeWidget } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'tree', model: '改成当前视图的模型' }) ) export class CustomTableSearchTreeWidget extends TableSearchTreeWidget { protected hasExe = false; @Widget.Watch('rootNode.children.length') protected watchRootNode(len) { if (len && !this.hasExe) { this.hasExe = true; const firstChild = this.rootNode?.children?.[0]; if (firstChild) { this.onNodeSelected(firstChild); this.selectedKeys = [firstChild.key]; } } } }

    2024年11月26日
    1.5K00
  • 表格主题配置(v4)

    TableThemeConfig /** * 表格主题配置 */ export interface TableThemeConfig { border: boolean | string; stripe: boolean; isCurrent: boolean; isHover: boolean; /** * 表格列主题配置 */ column: Partial<TableColumnThemeConfig>; } /** * 表格列主题配置 */ export interface TableColumnThemeConfig { /** * <h3>最小宽度</h3> * <ul> * <li>boolean: enabled column width auto compute</li> * <li>number: using css width (default: px)</li> * <li>string: using css width</li> * <li> * object: auto compute width for label by default function * <ul> * <li>min: min min width (default: 120)</li> * <li>max: max min width (default: 432)</li> * <li>chineseWidth: chinese width (default: 14 -> fontSize: 14px)</li> * <li>otherWidth: non chinese width (default: 9 -> fontSize: 14px)</li> * <li>sortableFixWidth: sortable handle width (default: 40)</li> * <li>nonSortableFixWidth: non sortable fix width (default: 22)</li> * </ul> * </li> * <li>function: auto compute width for label by function</li> * </ul> */ minWidth: boolean | number | string | Partial<TableColumnMinWidthComputeConfig> | TableColumnMinWidthComputeFunction; /** * 操作列 */ operation: { /** * 宽度 (default: 165) */ width?: number | string; /** * 最小宽度 (default: 120) */ minWidth?: number | string; }; } export interface TableColumnMinWidthComputeConfig { min: number;…

    2023年11月6日
    2.0K00
  • oio-button 按钮

    主按钮:用于主行动点,一个操作区域只能有一个主按钮。 默认按钮:用于没有主次之分的一组行动点。 虚线按钮:常用于添加操作。 文本按钮:用于最次级的行动点。 链接按钮:一般用于链接,即导航至某位置。 以及四种状态属性与上面配合使用。 危险:删除/移动/修改权限等危险操作,一般需要二次确认。 禁用:行动点不可用的时候,一般需要文案解释。 加载中:用于异步操作等待反馈的时候,也可以避免多次提交。 API 按钮的属性说明如下: 属性 说明 类型 默认值 版本 block 将按钮宽度调整为其父宽度的选项 boolean false disabled 按钮失效状态 boolean false icon 设置按钮的图标类型 v-slot – loading 设置按钮载入状态 boolean | { delay: number } false type 设置按钮类型 primary | ghost | dashed | link | text | default default 事件 事件名称 说明 回调参数 版本 click 点击按钮时的回调 (event) => void 支持原生 button 的其他所有属性。

    2023年12月18日
    98500
  • 文件上传组件前端校验超128长度大小,不清楚怎么配置

    原因是拼上后端返回的文件全路径后超出了字段的存储长度,后端通过注解@Field.String(size=1024)修改字段的存储长度后重新运行一遍服务。

    2023年11月1日
    2.3K00

Leave a Reply

Please Login to Comment