携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第17天,点击查看活动详情
小程序从v1.6.3开始, 小程序开始支持自定义组件开发
有了组件化的思想,我们在之后的开发中尽可能的将页面拆分成一个个小的、可复用的组件,
让我们的代码更加方便组织和管理,并且扩展性也更强
类似于页面,自定义组件由 json wxml wxss js 4个文件组成
和页面不同的时候,在组件的json文件中需要将component
选项设置为true,以表示其是一个组件
组件和页面都可以使用自定义组件和第三方组件的,只不过和内置组件可以直接使用不一样
如果需要在组件和页面中使用自定义组件或第三方组件,需要将自定义组件和第三方组件先在usingComponents
中进行注册
- 自定义组件也是可以引用自定义组件的,引用方法类似于页面引用自定义组件的方式(使用usingComponents 字段)
- 自定义组件和页面所在项目根目录名 不能以“wx-”为前缀,否则会报错
- 如果在app.json的usingComponents声明某个组件,那么所有页面和组件可以直接使用该组件,即该组件会被识别为全局组件
组件 --- /components/Cpn
wxml
<text class="cpn">Cpn</text>
使用组件的页面
{
"usingComponents": {
"Cpn": "/components/Cpn/Cpn"
}
}
<Cpn />
组件样式
组件内样式对组件外样式的影响
- 组件内的class样式,只对组件wxml内的节点生效, 对于引用组件的Page页面不生效
- 组件内不能使用id选择器、属性选择器、标签选择器,不是不能用,而是无法进行样式隔离,会对组件外样式产生污染
组件外样式对组件内样式的影响
- 外部使用class的样式,只对外部wxml的class生效,对组件内是不生效的
- 外部使用了id选择器、属性选择器不会对组件内产生影响
- 外部使用了标签选择器,会对组件内产生影响
所以推荐在小程序中尽可能的使用类选择器来设置样式,以最大程度减少样式之间的相互影响
styleIsolation
在Conponent构造函数的配置对象中,可以传入一个options属性,其中options属性中有一个styleIsolation(隔离)属性
styleIsolation属性中存在如下三个值:
合法值 | 说明 |
---|---|
isolated | 表示启用样式隔离,在自定义组件内外,使用 class 指定的样式将不会相互影响(默认取值) |
apply-shared | 表示页面 wxss 样式将影响到自定义组件,但自定义组件 wxss 中指定的样式不会影响页面 |
shared | 表示页面 wxss 样式将影响到自定义组件,自定义组件 wxss 中指定的样式也会影响页面和其他设置 |
组件间通信
父传子
大部分情况下,组件只负责布局和样式,内容是由使用组件的对象决定的
所以,我们经常需要从外部传递数据给我们的组件,让我们的组件来进行展示
我们可以使用使用properties属性来接收调用者向组件内部传入的值
properties支持以下数据类型
-
String、Number、Boolean
-
Object、Array、null(不限制类型)
组件调用者
<Cpn propTitle="外部传入的数据" />
组件
<view>{{ title }}</view>
<view>{{ propTitle }}</view>
Component({
properties: {
propTitle: {
type: String,
// 小程序中使用value属性来设置默认值
// 在小程序中设置引用类型值的默认值设置不需要使用函数
// 直接设置即可 例如 value: [], 不需要通过 value: () => []进行设置
value: '默认值'
}
},
data: {
title: 'data中定义的数据'
}
})
传递样式
有时候,我们不希望将样式在组件内固定不变,而是外部可以决定样式
这个时候,我们可以使用externalClasses属性给组件传入样式
- 在Component对象中,定义externalClasses属性
- 在组件内的wxml中使用externalClasses属性中的class
- 在页面中传入对应的class,并且给这个class设置样式
组件调用者
<Cpn foo="foo" />
.foo {
background-color: skyblue;
}
组件
<view class="foo">Cpn</view>
Component({
externalClasses: ['foo']
})
子传父
子组件
<view bind:tap="handleTap">Cpn</view>
Component({
// 组件中的事件不是写在配置对象顶层的
// 而是写在methods选项下边的
methods: {
handleTap() {
// triggerEvent 的作用和vue中的$emit的作用是一致的
this.triggerEvent('cpnClick', {
name: 'Klaus',
age: 23
})
}
}
})
父组件
<!-- 事件名是大小写敏感的 -->
<Cpn bind:cpnClick="handleClick" />
Page({
handleClick(e) {
console.log(e.detail) // => {name: "Klaus", age: 23}
}
})
页面调用组件方法
Page({
onShow() {
// 通过小程序内置方法 this.selectComponent 可以获取对应的组件实例
// selectComponent功能类似于 querySelector
// 小程序同样提供方法selectAllComponents 可以获取所有符合条件的组件实例
// selectAllComponents功能类似于 querySelectorAll
// 通过selectComponent和selectAllComponents只能获取自定义组件或第三方组件
// 无法通过这两个方法去获取原生组件实例
const cpnCpn = this.selectComponent('.cpn')
// 获取组件后,就可以直接调用组件中的属性和方法
cpnCpn.foo()
}
})
使用外部npm包
-
在控制台中使用传统的方式去下载和依赖对应的npm包
-
使用
工具
选项标下的构建npm
选项,将node_modules
中的依赖包构建到小程序中的
miniprogram_npm
中 -
和传统使用npm的方式一样去使用对应的npm依赖包
如果更新或修改了对应的依赖包,就需要重新构建npm,以更新对应的
miniprogram_npm
文件夹