IMFE IMFE
首页
  • Web前端技术路线
  • Android技术路线
  • IOS技术路线
  • PC技术路线
  • 公共规范

    • git管理规范
    • 代码评审规范
  • web前端规范

    • HTML开发规范
    • CSS开发规范
    • JS开发规范
    • ES6编码规范
    • 内容格式与编码规范
    • 项目目录结构规范
    • Vue编码风格规范
    • BEM规范
    • npm包发布规范
    • semver语义化版本规范
    • 移动端web设计规范开发手册
  • 移动端规范

    • 移动端web设计规范开发手册
    • imfe-mui组件开发手册
  • PC端规范

    • 待完善1
  • vscode
  • npm
  • pnpm
  • nvm
  • nrm
  • gitbash
  • postman
框架和组件
技术文章
社区
贡献
关于我们
Gitlab (opens new window)
首页
  • Web前端技术路线
  • Android技术路线
  • IOS技术路线
  • PC技术路线
  • 公共规范

    • git管理规范
    • 代码评审规范
  • web前端规范

    • HTML开发规范
    • CSS开发规范
    • JS开发规范
    • ES6编码规范
    • 内容格式与编码规范
    • 项目目录结构规范
    • Vue编码风格规范
    • BEM规范
    • npm包发布规范
    • semver语义化版本规范
    • 移动端web设计规范开发手册
  • 移动端规范

    • 移动端web设计规范开发手册
    • imfe-mui组件开发手册
  • PC端规范

    • 待完善1
  • vscode
  • npm
  • pnpm
  • nvm
  • nrm
  • gitbash
  • postman
框架和组件
技术文章
社区
贡献
关于我们
Gitlab (opens new window)
  • 公共规范

    • 代码评审规范
    • git管理规范
  • web前端开发规范

    • HTML开发规范
    • CSS开发规范
    • JS开发规范
    • ES6编码规范
    • 内容格式与编码规范
    • 项目目录结构规范
    • Vue编码风格规范
    • BEM规范
    • npm包发布规范
    • semver语义化版本规范
  • 移动端开发规范

    • 移动端web设计规范开发手册
    • imfe-mui组件开发手册
      • imfe-mui组件贡献规范
        • 介绍
        • 环境安装
        • 安装 Python
        • 下载源码
        • 安装依赖
        • 启动开发服务器
        • 源码目录介绍
        • vant.config.js
        • src中添加组件
        • 打包并发布
  • PC端开发规范

    • 待完善
  • 开发规范
  • 移动端开发规范
桂雅骏
2022-10-24
目录

imfe-mui组件开发手册

# imfe-mui组件贡献规范

[TOC]

# 介绍

本手册主要介绍基于Vant2.x版本中增加业务组件的开发流程

# 环境安装

在开始开发前,准备开发环境

# 安装 Python

https://www.python.org/

# 下载源码

https://git.iflytek.com/ZHYL_IMFE/ui/imfe-mui 分支: 2.x

# 安装依赖

npm run install
#或者
yarn
1
2
3

# 启动开发服务器

npm run dev
1

# 源码目录介绍

基于 Vant Cli 搭建的组件库的基本目录结构如下所示:

project
├─ src                # 组件源代码
│   ├─ button        # button 组件源代码
│   └─ dialog        # dialog 组件源代码
│
├─ docs               # 静态文档目录
│   ├─ home.md       # 文档首页
│   └─ changelog.md  # 更新日志
│
├─ babel.config.js    # Babel 配置文件
├─ vant.config.js     # Vant Cli 配置文件
├─ pacakge.json
└─ README.md
1
2
3
4
5
6
7
8
9
10
11
12
13

开发组件需要关心的是 vant.config.js 和 src 目录

# vant.config.js

site.locales 中配置的是文档中菜单目录,分为中文和英文两个部分,下面以中文为示例

nav 数组中存放是菜单树结构,在对应的位置添加需要开发的组件配置即可 例如:需要在 业务组件 中添加 title 标题 组件,配置路径如下

path 表示组件路径,对应 src 目录中的组件文件夹

title 表示文档中组件菜单的名称

// vant.config.js
module.exports = {

  ...

  site: {
    ...
    locales: {
      'zh-CN': {
        ...
        nav: [
          ...
          {
            title: '业务组件',
            items: [
              {
                path: 'title',
                title: 'title 标题'
              },
              ...
            ],
          }
        ]
      ...
    },
  },
};

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# src中添加组件

单个组件的目录如下:

button
├─ demo             # 示例目录
│   └─ index.vue   # 组件示例
├─ index.vue        # 组件源码
└─ README.md        # 组件文档
1
2
3
4
5

使用 .vue 文件编写组件时,编译后会生成对应的 JS 和 CSS 文件,且 JS 文件中会自动引入 CSS 文件。

如果需要将 JS 和 CSS 解耦,实现主题定制等功能,在编写代码时就要使用独立的 JS 和 CSS 文件,如下所示:

button
├─ demo             # 组件示例
│   └─ index.vue   # 组件示例入口
├─ index.js         # 组件入口,可以为 jsx 或 tsx
├─ index.less       # 组件样式,可以为 less 或 scss
└─ README.md        # 组件文档
1
2
3
4
5
6

采用这种目录结构时,组件的使用者需要分别引入 JS 和 CSS 文件,也可以通过 babel-plugin-import 自动引入样式。

通过引入样式源文件(less 或 scss)并修改样式变量,可以实现主题定制功能。(推荐使用)

使用 jsx 或者 tsx 方式编写组件,可以使用Vant Cli封装好的函数式组件的方式 下面以 Title 组件为例

// 创建命名空间
import { createNamespace } from '../utils';
// 实现发送事件的方式,类似 this.$emit
import { emit } from '../utils/functional';

// 引入的外部组件,以及相关类型
import Icon, { IconProps } from '../icon';
import Tag, { TagType } from '../tag';
import Button, { ButtonType } from '../button';

// 引入和定义相关类型
import { CreateElement, RenderContext } from 'vue/types';
import { ScopedSlots } from '../utils/types';

export type TitleSize = 'large' | 'normal' | 'small' | 'mini';

export type Tag = {
  type?: TagType;
  text?: string;
  color?: string;
  textColor?: string;
};

export type Button = {
  text: string;
  key: string | number;
  type: ButtonType;
};

export type TitleProps = {
  title?: string;
  size?: TitleSize;
  subtitle?: string;
  icon?: IconProps;
  tag?: Tag | Tag[];
  button?: Button | Button[];
  isLink?: boolean;
  linkName?: string;
  linkIcon?: string;
};

// 以当前组件名称生成组件相关方法
const [createComponent, bem] = createNamespace('title');

// 函数式组件入口,tsx
function Title(
  h: CreateElement,
  props: TitleProps,
  slots: ScopedSlots,
  ctx: RenderContext<TitleProps>
) {
  const {
    title,
    size = 'normal',
    subtitle,
    icon,
    tag,
    button,
    isLink,
    linkName,
    linkIcon = 'arrow',
  } = props;
  let tags: Tag[] = [];
  if (tag) {
    if (tag instanceof Array) tags = tag;
    else tags = [tag];
  }
  let buttons: Button[] = [];
  if (button) {
    if (button instanceof Array) buttons = button;
    else buttons = [button];
  }

  function renderIcon() {
    const sizes = {
      large: '28px',
      normal: '24px',
      small: '20px',
      mini: '20px',
    };
    if (icon) {
      return (
        <Icon
          class={bem('icon')}
          {...{ props: icon }}
          size={sizes[size]}
        ></Icon>
      );
    }
  }

  function renderTag() {
    return tags.map((item) => {
      // 只支持3个参数的配置
      const tagProps = {
        type: item.type,
        color: item.color,
        textColor: item.textColor,
      };
      return <Tag {...{ props: tagProps }}>{item.text}</Tag>;
    });
  }
  function renderButton() {
    return buttons.map((item) => {
      const buttonProps = {
        type: item.type || 'primary',
      };
      return (
        <Button
          size="mini"
          {...{ props: buttonProps }}
          key={item.key}
          onClick={() => emit(ctx, 'button-click', item.key)}
        >
          {item.text}
        </Button>
      );
    });
  }

  function renderLink() {
    if (isLink) {
      return (
        <span class={bem('link-wapper')} onClick={() => emit(ctx, 'link')}>
          <span class={bem('link-text')}>{linkName}</span>
          <Icon class={bem('link-icon')} name={linkIcon}></Icon>
        </span>
      );
    }
  }

  function renderTitle() {
    if (slots.title) {
      return <div class={bem('title-wapper')}>{slots.title()}</div>;
    }
    return (
      <div class={bem('title-wapper')}>
        {renderIcon()}
        <span class={bem('title')}>{title}</span>
        <span class={bem('tag')}>{renderTag()}</span>
      </div>
    );
  }

  function renderSubtitle() {
    if (slots.subtitle) {
      return <div class={bem('subtitle-wapper')}>{slots.subtitle()}</div>;
    }
    return (
      <div class={bem('subtitle-wapper')}>
        <span class={bem('subtitle')}>{subtitle}</span>
        <span class={bem('btns')}>{renderButton()}</span>
      </div>
    );
  }

  return (
    <div class={bem([size])}>
      {renderTitle()}
      {renderSubtitle()}
      {renderLink()}
    </div>
  );
}

// 定义组件的Props
Title.props = {
  title: String,
  size: {
    type: String,
    default: 'normal',
  },
  subtitle: String,
  icon: Object,
  tag: [Object, Array],
  button: [Object, Array],
  isLink: {
    type: Boolean,
    default: false,
  },
  linkName: String,
  linkIcon: {
    type: String,
    default: 'arrow',
  },
};

// 导出组件,需要用到前面命名空间函数返回的createComponent方法
export default createComponent<TitleProps>(Title);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190

# 打包并发布

编辑 (opens new window)
上次更新: 2022/10/24, 14:17:08
移动端web设计规范开发手册
待完善

← 移动端web设计规范开发手册 待完善→

最近更新
01
移动端web设计规范开发手册
10-24
02
UI设计规范在智医工作站落地实践
07-08
03
store-driver
07-08
更多文章>
Copyright © 2022-2022 IMFE | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式