手把手教你封装一个高复用的uni-app自定义组件
大家好!在uni-app开发中,我们总会遇到一些需要在多个页面重复使用的UI元素,比如一个特定样式的按钮、一个信息卡片或是一个自定义导航栏。把这些元素封装成自定义组件,不仅能极大提升开发效率,还能让项目代码更易于维护。这篇文章将从零开始,手把手带你封装一个功能完善、高复用的“信息卡片”组件。
一、为什么要封装组件?
想象一下,如果你的App里有10个页面都需要展示用户信息卡片,你是不是要把同样的一段 <view> 结构和对应的CSS复制10遍?如果以后UI改版,需要给卡片加个圆角,你又得改10个地方。这就是“重复造轮子”的痛点。
组件化开发就是为了解决这个问题,它允许我们:
-
提高代码复用性:一次封装,处处使用。 -
降低维护成本:只需修改组件本身,所有引用的地方都会同步更新。 -
提升项目结构清晰度:页面由一个个组件“积木”搭建而成,逻辑更分明。
二、开始封装“信息卡片”组件
我们的目标是创建一个 info-card 组件,它可以展示标题、内容、右侧附加信息,并且支持点击事件。
1. 创建组件文件
在uni-app项目的 components 目录下,新建一个 info-card 文件夹,并在其中创建 info-card.vue 文件。这是一个标准的Vue单文件组件结构。
<!-- components/info-card/info-card.vue --><template> <view class="card-wrapper" @click="handleClick"> <view class="card-content"> <text class="card-title">{{ title }}</text> <text class="card-body">{{ content }}</text> </view> <view class="card-extra"> <text class="card-note">{{ note }}</text> <uni-icons v-if="showArrow" type="right" size="16" color="#999"></uni-icons> </view> </view></template><script>export default { name: "info-card", props: { title: { type: String, default: '默认标题' }, content: { type: String, default: '' }, note: { type: String, default: '' }, showArrow: { type: Boolean, default: true } }, methods: { handleClick() { // 通过$emit触发父组件监听的自定义事件 this.$emit('click'); } }}</script><style scoped>.card-wrapper { display: flex; justify-content: space-between; align-items: center; padding: 12px 15px; background-color: #ffffff; border-bottom: 1px solid #f5f5f5; transition: background-color 0.2s;}.card-wrapper:active { background-color: #fafafa;}.card-content { display: flex; flex-direction: column;}.card-title { font-size: 16px; color: #333; margin-bottom: 4px;}.card-body { font-size: 14px; color: #666;}.card-extra { display: flex; align-items: center;}.card-note { font-size: 14px; color: #999; margin-right: 5px;}</style>
2. 组件代码解析
-
** <template>**:定义了组件的HTML结构。我们用flex布局实现左中右的结构。 -
** props**:这是组件的“接口”,父组件通过props向子组件传递数据。我们定义了title、content、note和showArrow四个属性,并设置了默认值。 -
** methods**:定义了组件的行为。handleClick方法通过this.$emit('click')触发一个名为click的自定义事件。这样父组件就能“监听”到这个组件的点击动作。 -
** <style scoped>**:scoped属性确保这里的CSS样式只对当前组件生效,不会污染其他组件或页面。
三、在页面中使用组件
组件封装好了,我们来看看如何在页面上使用它。
1. 引入并注册组件
在需要使用该组件的页面(比如 pages/index/index.vue)的 <script> 部分:
// pages/index/index.vueimport infoCard from'@/components/info-card/info-card.vue'exportdefault {components: { infoCard },methods: { handleCardClick() { uni.showToast({title: '卡片被点击了',icon: 'none' }); } }}
小技巧:如果你的组件使用频率非常高,可以在 main.js 中进行全局注册,这样就不需要在每个页面单独引入了。
2. 在模板中使用
现在,你可以在页面的 <template> 中像使用普通HTML标签一样使用 info-card 了。
<!-- pages/index/index.vue --><template> <view> <!-- 基础用法 --> <info-card title="我的订单" note="查看全部"></info-card> <!-- 传递更多数据,并监听点击事件 --> <info-card title="个人信息" content="点击修改您的头像和昵称" note="已完善" @click="handleCardClick" ></info-card> <!-- 不显示右侧箭头 --> <info-card title="版本号" content="当前版本 V1.0.0" :show-arrow="false"></info-card> </view></template>
四、实战经验总结
🎯 案例:组件支持自定义插槽
-
背景:有时我们希望卡片左侧不是简单的文字标题,而是一个图标。 -
问题: props只能传文本等简单数据,无法传递复杂的HTML结构。 -
解决方案:使用插槽(Slot)。改造 info-card.vue:<!-- 将 <text class="card-title">... 改为 <slot> --><viewclass="card-content"><slotname="title"><!-- 这里是后备内容,如果没有提供插槽,则显示默认标题 --><textclass="card-title">{{ title }}</text></slot><textclass="card-body">{{ content }}</text></view>在页面中使用时,可以这样传递自定义结构:
<info-cardcontent="使用插槽定义标题"><templatev-slot:title><viewstyle="display: flex; align-items: center;"><uni-iconstype="person"size="20"style="margin-right: 5px;"></uni-icons><textstyle="font-size: 16px; color: blue;">自定义标题</text></view></template></info-card> -
结果:组件的灵活性和可扩展性大大增强。
五、注意事项
-
⚠️ 命名规范:组件命名建议使用短横线连接(kebab-case),如 info-card,这在模板中直接使用。 -
⚠️ Props校验:在实际项目中,建议为 props提供更详细的校验,如required: true或自定义validator函数。 -
⚠️ 事件命名: $emit的事件名也建议使用kebab-case,虽然在监听时v-on会自动转换,但保持一致是好习惯。
写在最后
封装自定义组件是uni-app开发的核心技能之一。一个好的组件就像一个可靠的零件,能让你的应用搭建过程事半功倍。希望通过这个“信息卡片”的例子,你能掌握组件封装的基本思想和技巧。建议先收藏,然后动手实践一下吧!
本文生成时间:2026 年 03 月 15 日
IT技术交流:
软件接单交流群:

夜雨聆风