在HBuilderX进行组件开发
在 HBuilderX 中封装组件,是基于 uni-app(使用 Vue 语法)进行组件开发。
封装一个通用组件的标准流程,分为 创建、编写、使用 三个主要阶段。
第一步:创建组件文件
HBuilderX 提供了便捷的向导,且 uni-app 有一个非常强大的特性叫 easycom(自动注册),只要遵循特定目录结构,甚至不需要手动引入即可使用。
-
在项目的根目录下找到
components目录(如果没有则新建一个)。 -
右键点击
components-> 新建组件。 -
勾选 “创建同名目录”(推荐,方便管理资源)。
-
输入组件名称(建议使用大驼峰或连字符,如
MyButton或my-button)。
注意: 目录结构最好是
components/组件名/组件名.vue,这样 HBuilder 会自动识别并注册,你在页面里直接写标签就能用。
第二步:编写组件逻辑 (Implementation)
在 HBuilderX (uni-app) 中编写组件逻辑(第二步)是整个封装的核心。我们可以把它分为 “入门:能用就行” 和 “进阶:好用且通用” 两个层次。
一、 入门篇:把组件“跑”起来
入门阶段的核心目标是:实现“父子通信”。你需要搞清楚三个问题:父组件传给子组件什么(Props)?子组件自己管什么(Data)?子组件怎么通知外面(Events)?
1. 简单的 Props(接收数据)
入门时,你只需要知道 props 是用来接收外面传进来的参数的。
// 入门写法:数组形式(简单,但不严谨)
props: ['title', 'imageUrl']
-
应用场景:比如封装一个“商品卡片”,父组件把商品名和图片传进来,子组件负责展示。
2. 私有 Data(内部状态)
组件内部自己变化的数据,不要用 props,要用 data。
-
应用场景:比如一个“折叠面板”,它是展开还是收起,这个状态只有它自己关心,应该放在
data里。
3. 基础的 $emit(向外喊话)
当组件内部发生了交互(比如用户点了个按钮),子组件不能直接修改父组件的数据,必须“喊话”。
// 子组件内部
methods: {
onTap() {
// 这里的 'buy' 是自定义事件名,父组件监听 @buy
this.$emit('buy', { id: 123 });
}
}
二、 进阶篇:让组件“强”起来
进阶阶段的核心目标是:健壮性、灵活性和开发者体验。我们要防止别人传错参数,支持双向绑定,还要能灵活控制样式和结构。
1. 严格的 Prop 验证(健壮性)
不要只用数组写 props,要用对象写法,规定类型、默认值,甚至自定义验证函数。
props: {
// 1. 规定类型:如果传了 Number 会报错,方便排查 bug
title: {
type: String,
required: true // 必填项
},
// 2. 默认值:如果父组件没传,就用这个
theme: {
type: String,
default: 'light'
},
// 3. 高级:自定义验证器
score: {
type: Number,
validator: function (value) {
// 分数必须在 0 到 100 之间
return value >= 0 && value <= 100;
}
}
}
2. 实现 v-model 双向绑定(开发者体验)
如果你封装的是输入框、开关、选择器类组件,一定要支持 v-model,这样父组件用起来非常爽。
-
原理:v-model 本质是接收一个名为
value的 prop,并在变化时触发input事件。
// MyInput.vue
props: {
value: String // 1. 接收 value
},
methods: {
onInput(e) {
// 2. 触发 input 事件,把新值传出去
this.$emit('input', e.detail.value);
}
}
-
父组件使用:
<my-input v-model="searchText" />(不需要写繁琐的监听事件)。
3. 多插槽与作用域插槽(灵活性)
入门只用一个 <slot>,进阶要学会具名插槽(Named Slots)。
-
场景:封装一个“通用的弹窗组件”。
-
标题栏可能想放文字,也可能想放图标 -> 使用具名插槽。
-
底部按钮可能是“确定/取消”,也可能只有一个“知道了” -> 使用具名插槽。
-
<view class="modal">
<view class="header">
<slot name="header">默认标题</slot>
</view>
<view class="content">
<slot></slot> </view>
</view>
<my-modal>
<template v-slot:header>
<text style="color:red">警告!</text>
</template>
<view>这是内容...</view>
</my-modal>
4. 生命周期的大坑(重要知识点)
这是新手进阶最容易卡住的地方。
-
页面生命周期:
onLoad,onShow等(仅在pages里的页面有效)。 -
组件生命周期:
created,mounted等(在components里的组件必须用这个)。
切记:在组件里写
onLoad是不会执行的!初始化数据请求要写在mounted或created里。
总结: 入门进阶对比,封装组件的“三要素”
我把入门和进阶整合成一个表格,放在一起做比较。
| 维度 | 入门做法 | 进阶做法 | 为什么进阶更好? |
| 参数接收 | props: ['color'] |
对象写法,含 type 和 default |
防止父组件漏传参数导致报错,代码更健壮。 |
| 数据同步 | 父组件手动监听 @update 修改值 |
支持 v-model |
父组件代码量减少一半,逻辑更清晰。 |
| 内容分发 | 单一 <slot> |
具名插槽、作用域插槽 | 组件结构可被高度定制,复用性极高。 |
| 样式 | 写死 CSS | 支持传入 custom-class 或 style |
父组件可以微调子组件的样式。 |
| 初始化 | 混淆 onLoad 和 mounted |
明确区分生命周期 | 避免代码写了却不执行的尴尬。 |
在设计组件时,只需要想清楚这三点就可以了:
| 要素 | 对应代码 | 作用 |
| 属性 (Props) | props: {} |
父 -> 子:你可以配置组件的哪些外观或数据? |
| 事件 (Events) | this.$emit() |
子 -> 父:组件内部发生了什么需要告诉外面? |
| 插槽 (Slots) | <slot></slot> |
内容分发:组件内部哪块区域的内容由父组件决定? |
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)