微信小程序-自定义组件扩展
数据监听器
数据监听器主要用于监听任何属性(properties)和数据(data)的变化
在组件中需要进行数据监听,需要用到observers
如果是data中的数据,数据变化时可触发监听
如果是properties的数据,数据传递时就会触发监听
组件通讯
父往子传递
properties就是父子传递的方式
子往父传递
当子组件需要向父组件发送数据时,它会触发一个自定义事件,并把数据作为事件的一部分传递出去。父组件则监听这个事件,并在事件触发时执行相应的方法来接收数据。
子组件通过触发函数调用 this.triggerEvent(eventName, detail, options) 方法来定义并触发一个自定义事件eventName,并添加想要传输的数据detail。
1 | |
在引用子组件时,将自定义事件作为属性,绑定触发一个处理函数
处理方法会接收到一个事件对象 event。子组件传递的数据会存储在 event.detail 属性中
获取子组件实例
在父组件中,我们可以通过类选择器或者id选择器作为参数,调用this.selectComponent方法来获取到子组件的实例,就可以获取到子组件的所有信息
组件的生命周期
组件的生命周期需要在lifetimes字段进行声明,组件的生命周期有五个函数
options(组件选项,仅限组件)created:指主键实例被创建好时执行- attached:指主键被挂载到页面上时执行
- ready
- moved
- detached:组件被销毁时执行
注:在created声明周期时,不能调用setData函数
组件所在页面的生命周期
组件所在也页面的生命周期有四个,需要在pageLifetimes进行声明
- show:监听组件所在的页面展示状态
- hide:监听组件所在的页面隐藏状态
- resize
- routeDone
使用组件来构造页面
小程序中区分了组件和页面,但仍然可以使用component来构造页面
注意事项:
- 要求.json文件中必须包含usingComponents字段
- 里面的配置项要与Component保持一致
- 页面中Page方法有一些钩子函数,和事件监听方法等必须放在method中
最佳实践中,不推荐直接将组件来作为页面使用,而是选择页面容器模式,页面的主要职责是装组件,作为一个容器,不实现具体逻辑
组件复用机制
Behavior 是微信小程序中实现代码复用和逻辑共享的强大工具。通过将通用的数据、方法和生命周期封装到 Behavior 中,你可以大大减少代码冗余,提高开发效率,并使代码结构更加清晰和易于维护。在实际项目中,它被广泛应用于处理各种跨组件/页面的通用逻辑。
我们可以在behavior中预定义一些逻辑,例如上拉加载更多数据,在其中预定义了一些方法和数据
当组合在页面或组件中时,相同的数据会覆盖掉behavior中的数据,然后可以调用预定义的方法,来执行相应的逻辑
微信小程序 Behavior 冲突解决原则
核心思想是:页面/组件拥有最终的控制权。 大多数情况下,如果页面/组件与 Behavior 定义了同名的字段,页面/组件的定义会覆盖 Behavior 的定义。但生命周期函数是例外,它们会按顺序执行。
1. data 对象 (数据字段)
合并方式: 浅合并 (Shallow Merge) + 覆盖。
冲突解决:
- 如果
Behavior和页面/组件都定义了某个同名的数据字段(例如message),页面/组件中的值会覆盖Behavior中的值。 - 如果数据字段是对象,且同名,则整个对象会被替换,而不是深度合并。
- 如果只有
Behavior定义了,则该字段会被合并到页面/组件的data中。 - 如果只有页面/组件定义了,则该字段保持不变。
- 如果
2. properties 对象 (组件属性,仅限组件)
- 合并方式: 浅合并 (Shallow Merge) + 覆盖。
- 冲突解决: 与
data类似,如果Behavior和组件都定义了某个同名属性,组件中的定义会覆盖Behavior中的定义。
3. methods 对象 (方法)
合并方式: 覆盖。
冲突解决: 如果
Behavior和页面/组件都定义了某个同名方法,页面/组件中的方法会覆盖Behavior中的方法。这允许你在特定页面/组件中对Behavior提供的通用方法进行定制或重写。
4. 生命周期函数 (lifetimes, pageLifetimes)
合并方式: 顺序执行 (而非覆盖)。
冲突解决:
Behavior中定义的生命周期函数会先于页面/组件中定义的同名生命周期函数执行。- 如果引入了多个
Behavior,它们的生命周期函数会按照在behaviors数组中声明的顺序依次执行,然后再执行页面/组件自身的生命周期函数。 - 注意:
created和attached是特例,它们在Behavior中执行时,this.data尚未完全合并,可能无法访问到页面/组件独有的数据。通常建议在ready中进行数据初始化。
5. behaviors 数组 (引入其他 Behavior)
合并方式: 数组连接 (Concatenation)。
冲突解决: 数组会进行合并。如果一个组件引入了多个
Behavior,并且这些Behavior之间也有重叠(例如都定义了data.a),那么后引入的Behavior会覆盖先引入的Behavior。最终,页面/组件的定义会覆盖所有Behavior的定义。
observers(数据监听器,仅限组件)
- 合并方式: 数组连接。
- 冲突解决:
Behavior和组件的observers数组会合并。所有定义的监听器都会被执行。
relations(组件间关系,仅限组件)
- 合并方式: 对象合并。
- 冲突解决: 如果
Behavior和组件定义了同名的relations键,组件的定义会覆盖Behavior的定义。
externalClasses(外部样式类,仅限组件)
- 合并方式: 数组连接。
- 冲突解决:
Behavior和组件的externalClasses数组会合并。
options(组件选项,仅限组件)
- 合并方式: 对象合并。
- 冲突解决: 如果
Behavior和组件定义了同名的options键,组件的定义会覆盖Behavior的定义
外部样式类
外部样式类本质上是组件内部预留的占位符类名。当组件被引用时,外部可以通过一个特定的属性将实际的样式类名传递给这些占位符,从而实现对组件内部元素的样式控制。
可以把它想象成一个插槽,但这个插槽是用来插入CSS类名的。
在子组件中定义好默认的样式,但配置额外的样式占位符,并通过externalClasses: [‘custom-class’, ‘text-class’]关键字声明
在调用组件时,在wxml的模板文件中将外部样式类作为属性传递值,或者直接在父组件的css文件中编辑样式文件即可
CSS 变量(Custom Properties)
小程序也支持 CSS 变量(--var-name: value;)。在某些场景下,CSS 变量可以作为外部样式类的替代方案,甚至更优:
- 外部样式类: 适用于需要完全替换或添加一组样式规则的场景(如改变背景色、边框、字体等)。它传递的是一个完整的类名。
- CSS 变量: 适用于需要调整组件内部某个具体样式属性值的场景(如主题色、间距、字体大小等)。它传递的是一个值。
示例(CSS 变量):
组件内部:
1 | |
外部使用:
1 | |
CSS 变量的优势在于它更细粒度,不需要暴露内部的 DOM 结构,更符合“配置”而非“覆盖”的理念。但它不能像外部样式类那样直接添加新的 CSS 规则(比如 border),只能修改已有的属性值。