微信小程组件开发合集

版本支持

  • 从小程序基础库版本 1.6.3 开始支持简洁的组件化编程
  • 开发者工具 1.02.1810190 及以上版本支持全局组件
  • 自基础库版本 2.0.9 开始,还可以在组件绑定数据中包含函数
  • :host 选择器需要包含基础库 1.7.2 或更高版本的开发者工具支持
  • 外部样式类这个特性从小程序基础库版本 1.9.90 开始支持
  • 全局样式类这个特性从小程序基础库版本 2.2.3 开始支持
  • 从基础库 2.0.9 开始,对象类型的属性和 data 字段中可以包含函数类型的子字段
  • 自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段内进行声明
  • resize(组件所在的页面尺寸变化,2.4.0开始支持)
  • 抽象节点自小程序基础库版本 1.9.6 开始支持
  • 自定义组件扩展从小程序基础库版本 2.2.3 开始支持。
  • 小程序从基础库版本 2.2.1 、开发者工具从 1.02.1808300 开始支持使用 npm 安装第三方包

导读

首先看几个学习地址,用于方便理解小程序组件的能力。

自定义组件
组件模板和样式
Component构造器

组件npm开发
开发第三方自定义组件
命令行工具
小程序自定义组件脚手架
npm支持

自定义组件功能

组件模板

写法与页面模板相同

模板数据绑定

向子组件的属性传递动态数据

1
2
3
4
5
6
7
<!-- 引用组件的页面模板 -->
<view>
<component-tag-name prop-a="{{dataFieldA}}" prop-b="{{dataFieldB}}">
<!-- 这部分内容将被放置在组件 <slot> 的位置上 -->
<view>这里是插入到组件slot中的内容</view>
</component-tag-name>
</view>

注意

  • 自基础库版本 2.0.9 开始,还可以在数据中包含函数

组件的slot

在组件模板中可以提供一个 <slot> 节点,用于承载组件引用时提供的子节点。

支持默认slot和具名slot

注意

  • slot是view组件的话,查看文档结构,slot的代码和组件代码是同级的

组件样式

不支持的写法

1
2
3
4
#a { } /* ID选择器在组件中不能使用 */
[a] { } /* 属性选择器在组件中不能使用 */
button { } /* 标签名选择器在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */

外部样式类

Component 中用 externalClasses 定义段定义若干个外部样式类。这个特性从小程序基础库版本 1.9.90 开始支持

注意:在同一个节点上使用普通样式类和外部样式类时,两个类的优先级是未定义的,因此最好避免这种情况。

1
2
3
4
/* 组件 custom-component.js */
Component({
externalClasses: ['my-class']
})
1
2
<!-- 组件 custom-component.wxml -->
<custom-component class="my-class">这段文本的颜色由组件外的 class 决定</custom-component>

全局样式类

如果希望组件外样式类能够完全影响组件内部,可以将组件构造器中的options.addGlobalClass字段置为true。这个特性从小程序基础库版本 2.2.3 开始支持.

组件构造器

  • 在自定义组件的 js 文件中,需要使用 Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法。
  • 使用 this.data 可以获取内部数据和属性值,但不要直接修改它们,应使用 setData 修改。
  • 从基础库 2.0.9 开始,对象类型的属性和 data 字段中可以包含函数类型的子字段

组件事件

组件间的基本通信方式有以下几种。

  • WXML 数据绑定:用于父组件向子组件的指定属性设置数据,仅能设置 JSON 兼容数据(自基础库版本 2.0.9 开始,还可以在数据中包含函数)。具体在 组件模板和样式 章节中介绍。
  • 事件:用于子组件向父组件传递数据,可以传递任意数据。
  • 如果以上两种方式不足以满足需要,父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以直接访问组件的任意数据和方法。
1
2
3
4
5
<!-- 监听事件 -->
<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 -->
<component-tag-name bindmyevent="onMyEvent" />
<!-- 或者可以写成 -->
<component-tag-name bind:myevent="onMyEvent" />
1
2
3
4
5
6
// 触发事件
onTap: function(){
var myEventDetail = {} // detail对象,提供给事件监听函数
var myEventOption = {} // 触发事件的选项
this.triggerEvent('myevent', myEventDetail, myEventOption)
}

在写自定义form组件事件时,发送事件的数据detail对象使用{value: ''}格式,便于同监听原生form input事件时使用同一个input监听事件

1
2
3
4
5
// 事件监听方法
inputHandler(e) {
this.setData({
[e.currentTarget.dataset.key]: e.detail.value,
});

1
2
3
4
// 自定义input组件发送事件
inputHandler: function (event) {
this.triggerEvent('myinput', { value: 123});
},
1
2
3
4
<!-- 自定义组件绑定监听事件 -->
<yii-input value="{{value}}" data-key="code" bind:myinput="inputHandler"/>
<!-- 原生组件绑定监听事件 -->
<input value="{{value}}" data-key="code" bindinput="inputHandler"></input>

组件生命周期

最重要的生命周期是 created(组件实例刚刚被创建好时) attached(组件完全初始化完毕、进入页面节点树后) detached(在组件离开页面节点树后) ,包含一个组件实例生命流程的最主要时间点。

生命周期方法可以直接定义在 Component 构造器的第一级参数中。

自小程序基础库版本 2.2.3 起,组件的的生命周期也可以在 lifetimes 字段内进行声明(这是推荐的方式,其优先级最高)。如:attacheddetached

behaviors 中也可以编写生命周期方法

组件所在页面的生命周期在 pageLifetimes 定义段中定义show(组件所在的页面被展示) hide(组件所在的页面被隐藏) resize(组件所在的页面尺寸变化,2.4.0开始支持)

behaviors

用于组件间代码共享的特性,类似于一些编程语言中的“mixins”或“traits”。

每个组件可以引用多个 behavior 。 behavior 也可以引用其他 behavior 。

  • 组件本身的属性或方法会覆盖 behavior 中的属性或方法,如果引用了多个 behavior ,在定义段中靠后 behavior 中的属性或方法会覆盖靠前的属性或方法;
  • 如果有同名的数据字段,如果数据是对象类型,会进行对象合并,如果是非对象类型则会进行相互覆盖;
  • 生命周期函数不会相互覆盖,而是在对应触发时机被逐个调用。

内置 behaviors:wx://form-field wx://component-export

组件间关系

抽象节点

这个特性自小程序基础库版本 1.9.6 开始支持。

自定义组件模板中的一些节点,其对应的自定义组件不是由自定义组件本身确定的,而是自定义组件的调用者确定的。这时可以把这个节点声明为“抽象节点”。

节点的 generic 引用 generic:xxx=”yyy” 中,值 yyy 只能是静态值,不能包含数据绑定。不能动态决定。

自定义组件扩展

从小程序基础库版本 2.2.3 开始支持。

使用自定义组件

声明局部组件

index.json中对自定义组进行引用声明

1
2
3
4
5
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}

index.wxml中使用

1
2
3
4
<view>
<!-- 以下是对一个自定义组件的引用 -->
<component-tag-name inner-text="Some text"></component-tag-name>
</view>

声明全局组件

在 app.json 中声明 usingComponents 字段,在此处声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。

注意

  • 自定义组件也是可以引用自定义组件的
  • 开发者工具 1.02.1810190 及以上版本支持声明全局组件

这里不多说了,只记录关键信息,详细情况查看官方文档自定义组件

开发第三方自定义组件

小程序从基础库版本 2.2.1 开始支持使用 npm 安装第三方包。

开发

初始化

可使用下载模板和命令行工具进行开发,推荐使用命令行开发,如果是已有项目则不需要。

初始化之后需要安装依赖,安装依赖的时候可能会安装失败,在登录npm账号之后会正常安装npm包。如果不行试试verdaccio

1
2
3
4
5
6
7
8
# 安装命令行工具
npm install -g @wechat-miniprogram/miniprogram-cli
# 在指定目录初始化
miniprogram init --type custom-component
# npm 登录。可先跳过执行下面语句,不成功在回来执行
npm login
# 安装依赖
npm install

命令行工具用法

项目模板用法

开发注意事项

为了方便开发执行命令npm run watch,默认会在包根目录下生成miniprogram_dev目录,src中的源代码会被构建并生成到miniprogram_dev/components目录下。/tools/demo下的内容也会复制到该目录下

内置支持多入口构建,如若需要可自行调整 tools/config.js 配置文件的 entry 字段。无论是js模块还是自定义组件都要配置

执行测试npm run test、检测覆盖率npm run coverage

发布使用命令npm run dist

测试工具文档

以下为推荐使用的目录结构,如果有必要开发者也可以自行做一些调整:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|--miniprogram_dev // 开发环境构建目录
|--miniprogram_dist // 生产环境构建目录
|--src // 源码
| |--common // 通用 js 模块
| |--components // 通用自定义组件
| |--images // 图片资源
| |--wxml // 通用 wxml 模版资源
| |--wxs // 通用 wxs 资源
| |--wxss // 通用 wxss 资源
| |
| |--xxx.js/xxx.wxml/xxx.json/xxx.wxss // 暴露的 js 模块/自定义组件入口文件
|
|--test // 测试用例
|--tools // 构建相关代码
| |--demo // demo 小程序目录,开发环境下会被拷贝生成到 miniprogram_dev 目录中
| |--test // 测试工具相关目录
| |--config.js // 构建相关配置文件
|
|--gulpfile.js

新加图片之后要重启服务

编写文档

包括但不限于版本说明、使用效果、使用方法、详细说明

发布

发布小程序 npm 包的约束

这里要发布的 npm 包是特指专为小程序定制的 npm 包(简称小程序 npm 包)。

  1. 在 package.json 文件中新增一个 miniprogram 字段来指定构建文件生成目录(默认为 miniprogram_dist 目录)。
  2. 小程序 npm 包里只有构建文件生成目录会被算入小程序包的占用空间。

发布其他 npm 包的约束

  1. 只支持纯 js 包,不支持自定义组件。
  2. 必须有入口文件,即需要保证 package.json 中的 main 字段是指向一个正确的入口,如果 package.json 中没有 main 字段,则以 npm 包根目录下的 index.js 作为入口文件。
  3. 测试、构建相关的依赖请放入 devDependencies 字段中避免被一起打包到小程序包中,这一点和小程序 npm 包的要求相同。
  4. 不支持依赖 c++ addon,不支持依赖 nodejs 的内置库:
  5. 小程序环境比较特殊,一些全局变量(如 window 对象)和构造器(如 Function 构造器)是无法使用的。

发布流程

  1. 如果还没有 npm 帐号,可以到 npm 官网注册一个 npm 帐号。
  2. 在本地登录 npm 帐号,在本地执行:npm adduser或者npm login
  3. 在已完成编写的 npm 包根目录下执行npm publish

使用

npm支持

  1. 在小程序中执行命令安装 npm 包:

    1
    npm install --save packageName
  2. 点击开发者工具中的菜单栏:工具 –> 构建 npm
    02

  3. 勾选“使用 npm 模块”选项:
    03

  4. 构建完成后即可使用 npm 包。

js 中引入 npm 包:

1
2
const package = require('packageName')
const packageOther = require('packageName/other')

使用 npm 包中的自定义组件:

1
2
3
4
5
6
{
"usingComponents": {
"package": "packageName",
"package-other": "packageName/other"
}
}

思考:这里有一个/other,为什么是这样的,难道因为默认找index组件?如果使用其他组件就要这样使用?

官方自定义组件

slide-view
navigation-bar
recycle-view

官方扩展

computed
sm-crypto