坦途的博客

vuePress-theme-reco 坦途    2020 - 2025
坦途的博客 坦途的博客
主页
博客
  • 开发实践
  • 技术笔记
  • 技术实践
  • 前端优化
  • 鉴权
  • 心情物语
  • 杂谈游记
  • 前端
标签
时间轴
关于
author-avatar

坦途

22

文章

33

标签

主页
博客
  • 开发实践
  • 技术笔记
  • 技术实践
  • 前端优化
  • 鉴权
  • 心情物语
  • 杂谈游记
  • 前端
标签
时间轴
关于

UniApp 跨平台开发实践:如何封装通用组件,提高代码复用率

vuePress-theme-reco 坦途    2020 - 2025

UniApp 跨平台开发实践:如何封装通用组件,提高代码复用率

坦途 2023-07-26 UniApp组件封装跨平台开发

摘要

UniApp 作为一款支持多端编译的框架,封装通用组件可以大大提高代码复用率,减少重复开发成本。本文将介绍如何封装高复用性的 UniApp 组件,并适配多个平台,实现真正的 一次开发,多端运行。

# 一、为什么要封装通用组件?

在 UniApp 开发中,如果直接在每个页面写 UI 组件,可能会导致以下问题:

❌ 代码冗余:同样的 UI 逻辑在多个页面重复出现,后期维护困难。
❌ 不易维护:如果一个 UI 逻辑需要调整,就得改多个页面,容易出错。
❌ 平台差异:不同端(H5、小程序、App)可能存在细微的 UI 差异,统一管理更方便。

因此,我们需要封装 可复用、可配置、跨平台适配 的通用组件。


# 二、封装通用组件的基本方法

# 1️⃣ 组件结构

在 UniApp 中,封装组件的基本结构如下:

/components
 ├── CustomButton
 │   ├── CustomButton.vue  // 组件文件
 │   ├── index.js          // 组件导出
 ├── CustomModal
 │   ├── CustomModal.vue
 │   ├── index.js

每个组件独立管理,所有组件都存放在 components 目录下,便于维护。

# 2️⃣ 组件基础封装

以 CustomButton.vue 为例,我们封装一个通用按钮组件:

<template>
  <button 
    class="custom-button" 
    :class="[type]" 
    :style="{ backgroundColor: bgColor, color: textColor }" 
    @click="handleClick"
  >
    <slot></slot>
  </button>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue';

const props = defineProps({
  type: { type: String, default: 'primary' },  // 按钮类型
  bgColor: { type: String, default: '#007AFF' }, // 背景颜色
  textColor: { type: String, default: '#ffffff' } // 文字颜色
});

const emit = defineEmits(['click']);

const handleClick = () => {
  emit('click');
};
</script>

<style scoped>
.custom-button {
  padding: 10px 20px;
  border-radius: 5px;
  font-size: 16px;
  border: none;
}
.primary { background-color: #007AFF; color: white; }
.secondary { background-color: #ccc; color: black; }
</style>

✅ 组件特点:

  • 通过 props 接收外部参数,可配置按钮样式。
  • 使用 slot 让按钮内容可自定义。
  • 通过 emit('click') 让父组件监听按钮点击事件。

# 3️⃣ 在页面中使用组件

<template>
  <view>
    <CustomButton type="primary" @click="handlePrimaryClick">确定</CustomButton>
    <CustomButton type="secondary" @click="handleSecondaryClick">取消</CustomButton>
  </view>
</template>

<script setup>
import CustomButton from '@/components/CustomButton.vue';

const handlePrimaryClick = () => console.log('Primary 按钮点击');
const handleSecondaryClick = () => console.log('Secondary 按钮点击');
</script>

# 三、封装可跨平台适配的组件

不同端 UI 存在差异,比如:

  • H5 端 可能需要 div
  • 微信小程序 需要 view
  • App 端 可能需要 button

# 1️⃣ 适配不同平台

我们可以用 uni.getSystemInfoSync() 判断运行平台,并动态调整 UI:

<template>
  <view v-if="platform === 'H5'">H5 显示</view>
  <button v-else-if="platform === 'APP'">App 按钮</button>
  <text v-else>小程序显示</text>
</template>

<script setup>
import { ref, onMounted } from "vue";

const platform = ref("");

onMounted(() => {
  const systemInfo = uni.getSystemInfoSync();
  platform.value = systemInfo.platform;
});
</script>

✅ 这样,不同平台会自动选择合适的 UI 元素!


# 四、封装弹窗组件(支持传入插槽内容)

很多业务场景需要弹窗,我们可以封装一个通用弹窗 CustomModal.vue:

<template>
  <view v-if="visible" class="modal-mask">
    <view class="modal-content">
      <slot></slot>  <!-- 这里可以传入任意内容 -->
      <button @click="closeModal">关闭</button>
    </view>
  </view>
</template>

<script setup>
import { defineProps, defineEmits } from "vue";

const props = defineProps({
  visible: { type: Boolean, default: false },
});

const emit = defineEmits(["update:visible"]);

const closeModal = () => {
  emit("update:visible", false);
};
</script>

<style scoped>
.modal-mask {
  position: fixed;
  top: 0; left: 0; width: 100%; height: 100%;
  background: rgba(0, 0, 0, 0.5);
  display: flex; align-items: center; justify-content: center;
}
.modal-content {
  background: white;
  padding: 20px;
  border-radius: 10px;
  width: 80%;
}
</style>

# 使用方式

<template>
  <view>
    <CustomButton @click="showModal = true">打开弹窗</CustomButton>
    <CustomModal v-model:visible="showModal">
      <text>这是一个通用弹窗</text>
    </CustomModal>
  </view>
</template>

<script setup>
import { ref } from "vue";
import CustomModal from "@/components/CustomModal.vue";

const showModal = ref(false);
</script>

✅ 组件特点:

  • visible 控制显示隐藏,支持 v-model。
  • <slot> 允许插入任意内容,复用性更强。

# 五、组件封装的最佳实践

✅ 1. 组件功能单一化:避免让一个组件做太多事情,每个组件尽可能只负责一件事。
✅ 2. 组件参数可配置:使用 props 让组件可定制,避免硬编码。
✅ 3. 适配不同平台:考虑 uni.getSystemInfoSync() 进行适配,确保组件能在所有端正常运行。
✅ 4. 组件间通信:使用 emit 事件机制让父组件和子组件交互,而不是直接操作数据。


# 六、总结

🚀 完整组件封装流程:

  1. 创建基础组件(如按钮、弹窗)。
  2. 封装通用逻辑(支持 props 配置,使用 slot 让内容可定制)。
  3. 适配多端 UI 差异(使用 uni.getSystemInfoSync() 判断平台)。
  4. 组件间交互(使用 emit 事件通信)。

封装通用组件后,开发效率提高 50%+,代码复用率提升,维护成本降低! 🎯

👉 如果你觉得有帮助,欢迎点赞、收藏! 🚀