速通-微信小程序 4Day
紧接前文,搭配有助于快速,巩固/学习!话不多说开始!
经过前面几篇的学习,好简单,最起码对于做过前端Vue 开发,小程序前后端 so so easy!
哦对了,顺便推荐一下之前的VUE学习blog,此篇有很多知识概念何Vue高度类似;
自定义组件:
什么是组件:
小程序自定义组件Component 是运行在 小程序框架内 的独立功能单元
包含 结构WXML、样式WXSS、逻辑JS、配置JSON 四部分,与页面功能类似
但 体积更小、作用域更独立 专门用于封装可复用的 UI 模块
-
如:按钮、导航栏、弹窗、商品卡片
-
复杂页面:评分组件、轮播图组件
组件和页面的区别:
两者的本质差异在于 运行形态、注册方式和生命周期,以下是详细对比表格:
| 对比维度 | 页面(Page) | 自定义组件(Component) |
|---|---|---|
| 生命周期 | 专属页面生命周期onLoad/onShow/onReady 等 | 专属组件生命周期created/attached/ready 等 |
| 文件结构 | 必须包含 4 个文件:.wxml/.wxss/.js/.json | 可按需省略文件 如:无需样式可省略 .wxss),核心是.js |
| 注册方式 | 在app.json的pages数组中注册 | 在页面的 .json 通过usingComponents 注册 不能注册到 app.json |
| 路由能力 | 支持 wx.navigateTo 等路由跳转 | 无路由能力,不能通过路由跳转 |
| 运行形态 | 独立的页面载体,可直接跳转访问; | 依附于页面/其他组件,无法直接跳转; |
| 样式隔离 | 全局样式 app.wxss 可覆盖页面样式 | 默认样式隔离,组件样式仅作用于自身 |
| 数据通信 | 无父子通信概念,数据通过 onLoad 接收 | 支持父传子 properties子传父 triggerEvent |
-
组件的 .json 文件中需要声明
"component": true属性; -
组件的事件处理函数需要定义到
methods节点中; -
组件的 .js 文件中调用的是
Component()函数;
组件的创建\引用
创建自定义组件:
在项目中新建 components 文件夹,统一存放所有组件 再创建组件子文件夹,创建 4 个文件:
- 在项目的根目录中,鼠标右键,创建
components -> 组件名文件夹 - 在新建的
components -> 组件名文件夹上,鼠标右键,点击新建 Component - 输入组件名称之后回车,会自动生成组件对应的 4 个文件,分别为
.js/.json/.wxml/.wxss
project
├── components
│ └── demo // 组件名:demo组件
│ ├── demo.wxml // 结构
│ ├── demo.wxss // 样式(可选)
│ ├── demo.json // 配置(可选)
│ └── demo.js // 逻辑(必选)
组件的引用:
组件的引用方式分为 局部引用 和 全局引用,顾名思义:
-
局部引用:组件只能在当前被引用的页面内使用;
-
全局引用:组件可以在每个小程序页面中使用;
局部引用:
仅在 少数页面 使用的组件,如:详情页专属的评分组件,避免全局注册导致的资源冗余。
在 目标页面 的 .json 中,通过 usingComponents 声明组件别名与路径:
{
"usingComponents": {
// 键:组件别名(自定义) : 值:组件绝对路径;
"demo1": "/components/demo1/demo1"
}
}
目标页面: 直接通过 组件别名 在 WXML 中调用,传递属性即可:
<view>
局部引用:
<demo1></demo1>
</view>
全局引用:
小程序 所有页面 都会用到的基础组件,如:导航栏、空状态页、加载动画、评分星标
在小程序根目录的 app.json 中,通过 usingComponents 全局注册组件:
{
"pages": ["pages/home/home", "pages/message/message", "pages/.../..."],
"usingComponents": {
"empty": "/components/demo2/demo2", // 全局空状态组件
}
}
直接在 任意页面 的 WXML 中调用组件别名即可:
<view>
全局引用:
<demo2></demo2>
</view>
组件样式隔离🧱:
默认情况下,自定义组件的样式只对当前组件生效,不会影响到组件之外的 UI 结构:
页面的 WXSS 样式,包括全局 app.wxss 不会影响组件内部;
样式隔离配置:
在组件的 .json 文件中,通过 styleIsolation 属性可自定义隔离规则,支持以下三种取值:
| 配置值 | 页面样式对组件的影响 |
|---|---|
isolated 默认 | 仅组件内部,无影响(完全隔离) 绝大多数场景,推荐使用,保证组件独立性 |
apply-shared | 仅组件内部,页面样式会影响组件,组件样式不会影响页面需复用页面全局样式的场景,如:统一字体、主题色 |
shared | 组件内部 + 页面,组件与页面样式互相影响 双向污染特殊场景: 如:组件需完全继承页面样式, 慎用 |
修改组件的样式隔离选项:
**方式一:**在组件的 .json 文件中新增如下配置;
{
"component": true,
"styleIsolation": "isolated" // 默认值,可省略
}
方式二: 在组件的 .js 文件中新增如下配置;
Component({
options: {
styleIsolation: 'isolated'
}
})
😎😎😎实际开发中,一般都是,方式一,默认配置 isolated,更方便;
注意事项:
注意:组件 和 页面最终会合并成一个页面,所以在最外层声明的样式,会传递到内层;
禁止使用 id 选择器、属性选择器、标签选择器,默认隔离模式下,这些选择器不会生效;
全局样式 app.wxss,默认不会影响组件: 若需让组件继承全局样式,
建议通过 apply-shared 而非 shared,避免双向污染;
数据\方法\属性:
小程序自定义组件的核心能力由
data 内部数据、methods 方法、properties 外部属性
三部分构成,分别负责组件的:状态存储、逻辑处理、外部通信;
data 数据
定义:组件的 私有内部数据,仅组件自身可读写,外部无法直接修改
作用:存储组件的临时状态、渲染所需的本地数据,如:交互状态、计算结果;
<text>组件的 count: {{count}}</text>
Component({
/** 组件的初始数据 */
data: {
count: 0
},
})
menthods 方法
定义:组件的 逻辑处理函数集合,包括事件处理、业务逻辑等;
作用:处理组件的交互事件、数据计算、通信逻辑等;
Demo: 定义一个函数 addcount 添加 count 值;
<text>组件的 count: {{count}}</text>
<button bind:tap="addconut" >count +1 按钮</button>
Component({
/*** 组件的属性列表 */
properties: { },
/** 组件的初始数据 */
data: {
count: 0
},
/*** 组件的方法列表 */
methods: {
addconut(){
this.setData({ count: this.data.count+1 })
},
}
})
properties 属性:
定义:组件的 外部输入属性,用于接收父组件传递的数据,是父组件与子组件通信的核心方式。
作用:接收外部参数,动态配置组件的行为和展示,如:初始值、开关状态;
Demo: 在调用组件时候,传递一个最大值,addcount 不允许超过 max;
调用组件传递值:max
<view>
<text class="styled" >全局引用: </text>
<demo2 max="10" ></demo2>
</view>
组件方接受,并处理不允许超过最大值: 接收父组件传递的参数,支持类型校验type 和默认值value;
- type 支持的类型包括:
String/Number/Boolean/Object/Array; - 父组件未传递参数时,组件自动使用
value作为属性默认值;
Component({
/*** 组件的属性列表 */
properties: {
//方式一: 完整定义(需指定默认值时使用)
max: {
type: Number, // 数据类型(Number/String/Boolean等)
value: 10 // 默认值 10
}
//方式二: 简化定义(无需默认值时使用)
// max: Number
},
/** 组件的初始数据 */
data: {
count: 0
},
/*** 组件的方法列表 */
methods: {
addconut(){
if(this.data.count>=this.properties.max){ return; }
this.setData({ count: this.data.count+1 })
},
}
})
data 和 properties 的区别
小程序组件的 data 和 properties 实际上是指向 同一个内部数据对象
this.data === this.properties 的结果为 true 同一个内存对象
尽管技术上可以互相读写,但需遵守以下规范以提升代码可维护性:
properties更倾向于存储外界传递到组件中的数据data更倾向于存储组件的私有数据
数据监听器📼:
❓什么是数据监听:
小程序组件的 数据监听器 是通过 observers字段定义的回调机制,作用是:
- 监测组件内
data(私有数据)或properties(外部属性)的变化; - 当指定数据发生改变时,自动触发预设的回调函数;
- 类似于 vue 中的 watch 侦听器;
数据监听基本使用:
在组件的 Component 构造器中,通过 observers 字段定义监听器,支持多种监听规则:
Demo: 数据监听器实现 n1、n2 自增后自动计算总和 sum 的功能;
- 交互方法:
addN1/addN2通过this.setData修改n1/n2的值,触发数据变化; - 数据监听器:
observers监听n1和n2的变化,当任意一个值更新时,自动计算sum并同步到视图
<!-- 组件的WXML结构 -->
<view>{{n1}} + {{n2}} = {{sum}}</view>
<button size="mini" bindtap="addN1">n1自增</button>
<button size="mini" bindtap="addN2">n2自增</button>
Component({
data: { n1: 0, n2: 0, sum: 0 },
methods: {
addN1() { this.setData({ n1: this.data.n1 + 1 }); },
addN2() { this.setData({ n2: this.data.n2 + 1 }); }
},
// 监听n1和n2的变化,自动计算sum
observers: {
'n1, n2': function(n1, n2) {
this.setData({ sum: n1 + n2 });
}
}
})
监听对象属性的变化:
小程序数据监听器支持 监听对象中单个或多个属性的变化,通过指定 对象.属性 的路径语法;
Component({
observers: {
// 语法: "对象.属性A,对象.属性B"(多个属性用逗号分隔)
"对象.属性A,对象.属性B": function(objA, objB) {
// 回调参数顺序与监听的属性顺序一致,接收对应属性的新值
// 触发此监听器的 3种情况:
//[为属性A赋值] 使用 setData 设置 this.data.对象.属性A 时触发
//[为属性B赋值] 使用 setData 设置 this.data.对象.属性B 时触发
//[直接为对象赋值] 使用 setData 设置 this.data.对象 时触发
}
}
})
数据监听 - 案例: 动态 RGB 颜色选择器组件,通过按钮调整 R/G/B 颜色通道值;
利用数据监听器自动同步颜色展示区域的背景色与数值;
<view style="background-color: rgb({{fullColor}});" class="colorBox">
颜色值:{{fullColor}}
</view>
<button size="mini" bindtap="changeR" type="default">R</button>
<button size="mini" bindtap="changeG" type="primary">G</button>
<button size="mini" bindtap="changeB" type="warn">B</button>
Component({
// 1. 初始数据:RGB对象+颜色值字符串
data: {
rgb: { r: 0, g: 0, b: 0 },
fullColor: '0, 0, 0' // 用于渲染背景色的字符串
},
// 2. 事件处理函数:调整RGB通道值(最大255)
methods: {
// 调整R G B通道
// 每个按钮绑定对应的changeX方法,通过 this.setData 修改rgb对象的对应属性
// 用三元运算符限制通道值不超过 255 RGB 颜色通道的最大值)
changeR() { this.setData({ 'rgb.r': this.data.rgb.r + 5 > 255 ? 255 : this.data.rgb.r + 5 }); },
changeG() { this.setData({ 'rgb.g': this.data.rgb.g + 5 > 255 ? 255 : this.data.rgb.g + 5 }); },
changeB() { this.setData({ 'rgb.b': this.data.rgb.b + 5 > 255 ? 255 : this.data.rgb.b + 5 }); }
},
// 3. 数据监听器(方式1:监听指定属性)
observers: {
// 监听rgb对象的r、g、b属性变化
'rgb.r, rgb.g, rgb.b': function(r, g, b) { this.setData({ fullColor: `${r}, ${g}, ${b}` }); }
// 方式2:通配符监听对象所有属性(属性过多时简化写法)
// 'rgb.**': function(obj) {
// this.setData({
// fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
// });
// }
}
})
数据监听器的两种用法:
-
方式一:
'对象.属性A, 对象.属性B',精准监听指定属性,回调参数顺序与监听的属性顺序一致,直接获取对应属性的新值
-
方式二:
'对象.**',监听对象的 所有子属性变化, 回调参数是整个对象,适用于属性较多的场景;
纯数据字段
什么是纯数据字段:
纯数据字段指的是那些,不用于界面渲染的 data 字段
例如:有些情况下,某些 data 中的字段,既不会展示在界面上,也不会传递给其他组件
仅仅在当前组件内部使用,这种特性的字段适合被设置为纯数据字段,有助于提升页面更新的性能;
配置纯数据字段:
通过组件 Component 构造器的 options 节点,
指定pureDataPattern为 正则表达式,匹配该规则的 data 字段会被标记为 纯数据字段;
Demo案例: 将之前案例中的 rgb(仅内部计算用,不直接渲染)改造为纯数据字段 _rgb
Component({
// 1. 配置纯数据字段规则(下划线开头)
options: {
pureDataPattern: /^_/
},
// 初始数据:RGB对象+颜色值字符串
data: {
// 2. 将原rgb改为纯数据字段_rgb
_rgb: { r: 0, g: 0, b: 0 },
fullColor: '0, 0, 0' // 用于渲染背景色的字符串
},
// 3. 事件处理:修改纯数据字段_rgb的属性
// 事件处理函数:调整RGB通道值(最大255)
methods: {
// 调整R G B通道
// 每个按钮绑定对应的changeX方法,通过 this.setData 修改rgb对象的对应属性
// 用三元运算符限制通道值不超过 255 RGB 颜色通道的最大值)
changeR() { this.setData({ '_rgb.r': this.data._rgb.r + 5 > 255 ? 255 : this.data._rgb.r + 5 }); },
changeG() { this.setData({ '_rgb.g': this.data._rgb.g + 5 > 255 ? 255 : this.data._rgb.g + 5 }); },
changeB() { this.setData({ '_rgb.b': this.data._rgb.b + 5 > 255 ? 255 : this.data._rgb.b + 5 }); }
},
// 4. 数据监听器:监听纯数据字段_rgb的变化
// 数据监听器(方式1:监听指定属性)
observers: {
// 监听rgb对象的r、g、b属性变化
// '_rgb.r, _rgb.g, _rgb.b': function(r, g, b) { this.setData({ fullColor: `${r}, ${g}, ${b}` }); }
// 方式2:通配符监听对象所有属性(属性过多时简化写法)
'_rgb.**': function(obj) {
this.setData({
fullColor: `${obj.r}, ${obj.g}, ${obj.b}`
});
}
}
})
- 配置纯数据字段规则:
_下划线开头,将原rgb改为纯数据字段_rgb - 事件处理:修改纯数据字段
_rgb的属性,数据监听器:监听纯数据字段_rgb的变化;
组件的生命周期🧬
小程序组件的生命周期分为:
- 组件自身生命周期: 控制组件自身的
创建、初始化、销毁 - 组件所在页面生命周期: 响应控制组件,所在页面状态变化;
二者通过不同节点配置,是组件逻辑初始化、资源清理的核心机制;
组件生命周期:
组件自身生命周期控制组件从 创建 到 销毁 的过程,通过 lifetimes 节点配置;
| 生命周期 | 参数 | 描述说明 |
|---|---|---|
⭐created | 无 | 组件实例刚被创建时执行, 此时不能调用 setData,仅用于给组件添加自定义属性 |
⭐attached | 无 | 组件实例进入页面节点树时执行,this.data已初始化,适合做初始化工作 如: 请求数据 |
⭐detached | 无 | 组件实例被从页面节点树移除时执行,适合做清理工作如: 清除定时器 |
ready | 无 | 组件在视图层布局完成后执行,可操作 DOM 节点 |
moved | 无 | 组件实例被移动到节点树另一个位置时执行 极少用 |
error | Object Error | 组件方法抛出错误时执行,用于错误捕获 |
lifetimes 节点:
推荐在lifetimes节点中声明生命周期函数,优先级高于 直接定义在 Component 第一级参数:
Component({
// 推荐方式:lifetimes节点
lifetimes: {
created() { /** 给组件添加自定义属性 */ },
attached() { /** 初始化:请求组件初始数据 */ },
detached() {
// 清理:清除定时器
clearInterval(this.timer);
}
},
// 旧方式(不推荐)
// attached() {},
// detached() {}
})
组件>页面生命周期
当组件行为 依赖页面状态变化时触发 如:页面展示时组件更新数据;
组件所在页面的生命周期函数,会在 组件所在页面的对应生命周期触发时 执行,
用于实现 页面状态变化→组件行为同步 的联动逻辑,如:页面切回前台时,组件刷新数据;
| 生命周期函数 | 参数 | 描述 |
|---|---|---|
show | 无 | 组件所在页面被展示时执行(如页面从后台切回前台) |
hide | 无 | 组件所在页面被隐藏时执行(如页面切到后台) |
resize | Object Size | 组件所在页面尺寸变化时执行(如屏幕旋转) |
pageLifetimes 节点
页面生命周期函数需定义在 pageLifetimes 节点中:
Component({
pageLifetimes: {
show() { /** 页面展示时,执行组件逻辑(如刷新数据) */ },
hide() { /** 页面隐藏时,暂停组件任务(如暂停播放)*/ },
resize(size) { /** 页面尺寸变化时,调整组件布局 */ }
}
})
插槽🔌
插槽是小程序自定义组件的 内容占位机制,
通过 <slot> 节点在组件中 预留位置,由,组件使用者自定义填充内容,
让组件兼具 封装性 与 灵活性 既保留组件的基础结构,又支持使用者自定义部分内容:
单个插槽:
小程序组件默认仅支持 1 个插槽,称为 单个插槽,是最基础的插槽用法:
组件中定义插槽(组件 WXML)
- 在组件的 WXML 中添加
<slot>节点,作为内容占位符: - 组件使用者在引用组件时 ,在组件标签内编写的 WXML 结构,会自动填充到
<slot>的位置;
<view>
<!-- 组件的固定结构 -->
<view>demo4slot 组件内部↓</view>
<!-- 插槽:使用者自定义的内容会填充到这里 -->
<slot></slot>
<view>demo4slot 组件内部↑</view>
</view>
调用接受方: 在引用组件的标签内,直接编写需要填充的 WXML 结构,会自动替换组件中的<slot>
<!-- 引用: 单slot插槽组件 -->
<demo4slot>
<view>主页引用demoslot插槽组件1</view>
<view>主页引用demoslot插槽组件2</view>
<view>主页引用demoslot插槽组件3</view>
</demo4slot>
启用多个插槽:
默认不支持多个插槽,需手动启用后,可在组件中定义 多个带名称的插槽,实现 多区域内容自定义
启用多个插槽 组件 JS 在组件的 Component 构造器中,通过 options 节点设置
multipleSlots: true,启用多插槽支持🔌🔌🔌;
组件.JS 文件配置📄
// 组件的JS
Component({
options: {
multipleSlots: true // 启用多插槽支持
},
properties: {},
methods: {},
data:{}
})
组件中定义多插槽 组件 WXML 给<slot>添加 name 属性区分不同插槽:
<view style="border: 2px solid #f60;">
<!-- 插槽1:name为“header” -->
<slot name="header"></slot>
<!-- 组件的固定内容 -->
<view>组件的固定的主体区域</view>
<!-- 插槽2:name为“footer” -->
<slot name="footer"></slot>
</view>
使用者填充多插槽内容: 在引用组件时,通过 slot 属性指定内容对应的插槽名称:
<!-- 引用: 多slot插槽组件 -->
<demo5slots>
<!-- 填充到name="header"的插槽 -->
<view slot="header" style="background-color: gold;">自定义头部内容1</view>
<view slot="header" style="background-color: gold;">自定义头部内容2</view>
<!-- 填充到name="footer"的插槽 -->
<view slot="footer" class="custom-footer">自定义底部内容1</view>
<view slot="footer" class="custom-footer">自定义底部内容2</view>
<view slot="header" style="background-color: gold;">自定义头部内容3</view>
<view slot="header" style="background-color: gold;">自定义头部内容4</view>
</demo5slots>
-
单个插槽无 name:单个插槽不需要设置
name,使用者的内容会默认填充; -
多插槽需启用:必须在组件 JS 的
options中设置multipleSlots: true,否则多插槽不生效; -
插槽的作用域:插槽中使用的数据,是 组件使用者的作用域
而非组件的作用域即插槽内可直接使用,使用者页面/父组件的 data 数据;
父子组件通信👨👦
小程序父子组件通信是组件协作的核心机制,包含:
属性绑定 父→子、事件绑定 子→父、 获取组件实例 父直接操作子 三种方式,覆盖不同场景通信需求;
| 通信方式 | 数据流向 | 核心用途 |
|---|---|---|
| 属性绑定 | 父→子 | JSON 兼容数据类型:数字、字符串、等 … 父向子传递配置参数、初始数据; |
| 事件绑定 | 子→父 | 任意类型:对象、函数、等 … 子向父传递交互结果、状态变化; |
| 获取组件实例 | 父→子(直接操作) | 父直接调用子组件:方法、修改数据; |
属性绑定:父-子
通过父组件给子组件设置属性,子组件在 properties 中声明后使用,实现 父向子传递数据
- 父组件定义数据:在父组件的
data中声明要传递的数据, - 在引用子组件的标签中,通过
属性名="{{数据}}"传递; - 在子组件的
properties中声明对应属性指定类型; - 在子组件的
WXML/JS中直接使用该属性;
父组件:JS
Page({
data: { count: 1 }, // 要传递给子组件的数据
addcount(){ this.setData({count: this.data.count+1 }) } //父组件 count++ 更新;
})
父组件:wxml
<view>
全局引用:
<view>父组件中,count值为: {{count}}</view>
<button bind:tap="addcount" >父组件 count++</button>
<demo6zjParam1 Zcount="{{count}}" ></demo6zjParam1>
</view>
子组件:JS
// 子组件JS
Component({
properties: { Zcount: Number }
})
子组件:wxml
<!-- 子组件WXML -->
<text>子组件中 获取 父组件 count 值为: {{Zcount}}</text>
父组件的 count 值会同步传递到子组件 Zcount,父组件修改 count 时,子组件会自动更新 Zcount;
事件绑定:子-父
通过 父组件绑定自定义事件 + 子组件触发事件 的方式,实现子向父传递数据,支持任意类型数据;
-
父组件定义处理函数:父组件中定义:
接收子组件数据的函数在引用子组件的标签中,通过
bind:自定义事件名="处理函数"绑定 -
子组件触发事件:子组件中通过
this.triggerEvent('自定义事件名', {参数对象})触发事件并传参; -
父组件接收数据:父组件的处理函数通过
e.detail获取子组件传递的参数;
父组件:JS
Page({
data: { count: 1 },
//父组件 count++ 更新;
addcount(){ this.setData({count: this.data.count+1 }) },
// 接收子组件数据的处理函数
syncCount(e){
console.log("通过e.detail获取子组件传递的参数");
this.setData({ count: e.detail.value });
}
})
父组件:wxml
<view>
全局引用: 子传父
<view>父组件中,count值为: {{count}}</view>
<demo7zjParam2 count="{{count}}" bind:sync="syncCount"></demo7zjParam2>
</view>
子组件:JS
// 子组件JS
Component({
properties: { count: Number },
methods: {
addCount() {
console.log("调用: 子组件 count ++");
this.setData({ count: this.properties.count + 1 });
this.triggerEvent('sync', { value: this.properties.count }); // 触发自定义事件,向父组件传参
}
}
})
子组件:wxml
<!-- 子组件WXML -->
<text>子组件中,count值为:{{count}}</text>
<button bindtap="addCount">子组件 count ++</button>
点击子组件的 +1 按钮,子组件的count增加,
同时通过 triggerEvent 将新值传递给父组件,父组件的 count 同步更新;
获取组件实例:
父组件通过 this.selectComponent(选择器) 获取子组件实例,
直接调用子组件的方法、修改其数据,适用于需要 父主动控制子组件 的场景;
-
子组件加标识:在子组件标签中添加
class或id(作为选择器) -
父组件获取实例:父组件中通过
this.selectComponent('选择器')获取子组件实例;父组件操作子组件:调用子组件的方法、修改其数据;
修改上述代码: ==父组件.JS==
Page({
data: { count: 1 },
//父组件 count++ 更新;
addcount(){ this.setData({count: this.data.count+1 }) },
// 接收子组件数据的处理函数
syncCount(e){
console.log("通过e.detail获取子组件传递的参数");
this.setData({ count: e.detail.value });
},
// 获取子组件实例,调用子组件count++
getChild(){
console.log("通过class选择器获取子组件实例");
const child = this.selectComponent('.customA');
// 直接调用子组件的方法
child.addCount();
},
})
父组件:wxml
<view>
全局引用: 获取组件实例
<view>父组件中,count值为: {{count}}</view>
<demo7zjParam2 count="{{count}}" bind:sync="syncCount" class="customA" ></demo7zjParam2>
<button bindtap="getChild">获取子组件实例,调用子组件count++</button>
</view>
behavious
behaviors 是小程序中 实现组件间代码共享 的特性
功能类似 Vue.js 的 mixins,可让多个组件复用同一套属性、数据、方法与生命周期逻辑
behaviors 的核心作用是组件间代码复用: 一个 behavior 可封装属性、数据、方法、生命周期函数等逻辑;
-
多个组件可引用同一个 behavior,共享其封装的逻辑,
-
组件引用 behavior 后,behavior 的内容会 合并到组件自身的配置中;
-
单个组件可以引用 多个 behavior,behavior 自身也可以引用其他 behavior
支持嵌套复用
创建 behavior: Behavior(Object object) 方法创建 behavior 实例,并导出供组件使用,示例如下:
// 定义并导出behavior(如behaviors/my-behavior.js)
module.exports = Behavior({
// 属性节点(同组件的properties)
properties: {},
// 私有数据节点(同组件的data)
data: { username: 'zs' },
// 方法/事件处理函数节点(同组件的methods)
methods: {},
// 生命周期函数(同组件的生命周期)
created() {},
attached() {}
// 其他节点...
})
导入并使用 behavior: 组件需通过 require 导入 behavior,并挂载到 behaviors 数组中;
// 组件的JS文件
// 1. 导入behavior
const myBehavior = require("../../behaviors/my-behavior")
Component({
// 2. 挂载behavior到behaviors数组
behaviors: [myBehavior],
// 组件自身的其他配置(可与behavior的内容合并)
properties: {},
data: {},
methods: {}
})
behavior 支持的节点
| 可用节点 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
behaviors | String Array | 否 | 引用其他 behavior |
properties | Object Map | 否 | 同组件的属性配置 |
data | Object | 否 | 同组件的私有数据 |
methods | Object | 否 | 同组件的方法 / 事件处理函数 |
created | Function | 否 | 生命周期函数(组件创建时) |
attached | Function | 否 | 生命周期函数(组件挂载时) |
ready | Function | 否 | 生命周期函数(布局完成时) |
moved | Function | 否 | 生命周期函数(组件移动时) |
detached | Function | 否 | 生命周期函数(组件销毁时) |
同名字段的覆盖 / 组合规则
当组件与引用的 behavior 包含同名字段时,会按以下类别处理 详细规则需参考微信官方文档
-
同名数据字段(data):组件自身的 data 会覆盖 behavior 的 data;
-
同名属性(properties)/ 方法(methods):组件自身的定义会覆盖 behavior 的定义;
-
同名生命周期函数:组件 与 behavior生命周期函数会 按顺序依次执行
behavior函数先执行
相关文档
黑马—小程序简介_哔哩哔哩_bilibili 对应:Day4 天内容!