uniapp 系统学习,从入门到实战(五)—— 组件库与常用 UI 组件
全篇大概 7000 字(含代码),建议阅读时间 30min
UniApp 基于 Vue.js 的跨平台特性,提供了丰富的内置组件和灵活的扩展能力。本文将从内置组件、扩展组件库和自定义组件开发三个维度,系统解析 UniApp 的组件生态,并结合实际开发场景提供实践建议。
📚 目录
- 内置组件
- 扩展组件库
- 自定义组件开发
- 总结
1. 内置组件
UniApp 内置组件经过多端适配,可自动转换为原生控件,确保一致性和性能。以下是核心分类及使用要点:
1.1 视图容器
标签名 | 描述 |
---|---|
view | 基础容器,类似HTML的div,支持fle布局和嵌套 |
scroll-view | 可滚动区域,需设置固定高度(纵向滚动)或 white-space: nowrap(横向滚动)。支持触底事件 @scrolltolower 和下拉刷新。 |
swiper | 轮播容器,需搭配 swiper-item 使用。通过 indicator-dots 显示指示点,autoplay 实现自动切换。 |
view
示例代码:
<template>
<!-- 基础布局容器 -->
<view class="container">
<view class="box" style="background-color: #f0ad4e;">Box 1</view>
<view class="box" style="background-color: #5bc0de;">Box 2</view>
</view>
</template>
<style>
.container {
display: flex;
padding: 20px;
}
.box {
width: 100px;
height: 100px;
margin: 10px;
text-align: center;
line-height: 100px;
}
</style>
scroll-view
示例代码:
<template>
<!-- 纵向滚动 -->
<scroll-view
scroll-y
:style="{height: '300px'}"
@scrolltolower="onReachBottom"
>
<view v-for="i in 20" :key="i" class="item">Item {{i}}</view>
</scroll-view>
</template>
<script>
export default {
methods: {
onReachBottom() {
uni.showToast({ title: '触底了' })
}
}
}
</script>
<style>
.item {
height: 80px;
line-height: 80px;
border-bottom: 1px solid #eee;
}
</style>
swiper
示例代码:
<template>
<!-- 自动轮播 -->
<swiper
:indicator-dots="true"
:autoplay="true"
interval="2000"
>
<swiper-item>
<view class="swiper-item" style="background-color: #4cd964;">Page 1</view>
</swiper-item>
<swiper-item>
<view class="swiper-item" style="background-color: #007aff;">Page 2</view>
</swiper-item>
</swiper>
</template>
<style>
.swiper-item {
height: 200px;
text-align: center;
line-height: 200px;
}
</style>
1.2 基础内容
标签名 | 描述 |
---|---|
text | 文本组件,支持 selectable 长按选中和 space 控制空格显示(如 ensp、emsp)。 |
image | 图片组件,支持 mode=“aspectFit” 等比缩放。注意默认宽高为 300px×225px,建议通过 CSS 优化加载闪烁问题。 |
text
示例代码:
<template>
<!-- 可选中文本 -->
<text selectable space="ensp">
这是 带空格的文本(ENSP空格)
</text>
<!-- 换行文本 -->
<text>\n换行文本示例</text>
</template>
image
示例代码:
<template>
<!-- 等比缩放图片 -->
<image
src="https://example.com/image.jpg"
mode="aspectFit"
style="width: 300px; height: 200px;"
/>
</template>
1.3表单交互
标签名 | 描述 |
---|---|
input/textarea | 输入框支持 v-model 双向绑定。textarea 需设置 white-space: pre-wrap 实现自动换行。 |
picker | 数据选择器,支持 mode=“selector”(普通选择器)或 mode=“date”(日期选择),通过 @change 事件获取选中值。 |
button | 按钮类型包括 primary(蓝色)、warn(红色),支持 loading 状态和 open-type 微信开放能力。 |
input/textarea
示例代码:
<template>
<!-- 双向绑定 -->
<input v-model="inputValue" placeholder="请输入内容" />
<!-- 自动换行文本域 -->
<textarea
v-model="textValue"
:style="{whiteSpace: 'pre-wrap'}"
placeholder="多行输入"
/>
</template>
<script>
export default {
data() {
return {
inputValue: '',
textValue: ''
}
}
}
</script>
picker
示例代码:
<template>
<!-- 日期选择器 -->
<picker
mode="date"
:value="date"
@change="onDateChange"
>
<view>选择日期:{{date}}</view>
</picker>
<!-- 普通选择器 -->
<picker
mode="selector"
:range="options"
@change="onSelectChange"
>
<view>当前选择:{{options[selectedIndex]}}</view>
</picker>
</template>
<script>
export default {
data() {
return {
date: '2023-01-01',
options: ['选项A', '选项B', '选项C'],
selectedIndex: 0
}
},
methods: {
onDateChange(e) {
this.date = e.detail.value
},
onSelectChange(e) {
this.selectedIndex = e.detail.value
}
}
}
</script>
button
示例代码:
<template>
<!-- 带加载状态的按钮 -->
<button
type="primary"
:loading="isLoading"
@click="handleSubmit"
>
提交
</button>
<!-- 微信开放能力 -->
<button
open-type="getUserInfo"
@getuserinfo="onGetUserInfo"
>
微信登录
</button>
</template>
<script>
export default {
data() {
return {
isLoading: false
}
},
methods: {
handleSubmit() {
this.isLoading = true
setTimeout(() => {
this.isLoading = false
}, 2000)
},
onGetUserInfo(e) {
console.log('用户信息:', e.detail.userInfo)
}
}
}
</script>
1.4 导航与媒体
标签名 | 描述 |
---|---|
navigator | 页面跳转组件,支持 open-type=“navigate”(保留当前页)或 redirect(关闭当前页)。 |
video | 视频播放器,需注意 iOS 平台可能需添加 webkit-playsinline 属性实现内联播放。 |
navigator
示例代码:
<template>
<!-- 保留当前页跳转 -->
<navigator
url="/pages/detail/detail"
open-type="navigate"
>
跳转到详情页
</navigator>
<!-- 关闭当前页跳转 -->
<navigator
url="/pages/home/home"
open-type="redirect"
>
返回首页
</navigator>
</template>
video
示例代码:
<template>
<!-- 内联播放视频 -->
<video
src="https://example.com/video.mp4"
:webkit-playsinline="true"
controls
style="width: 100%; height: 300px;"
/>
</template>
1.5 跨平台差异处理:
组件样式默认已适配多端,但如 button 在 H5 显示蓝色,小程序显示绿色。
原生组件(如 map、video)层级高于前端组件,需使用 cover-view 覆盖。
2. 扩展组件库
对于复杂场景,UniApp 生态提供了多款高质量扩展库:
2.1 uni-ui
功能
:官方维护的组件库,包含 uni-card(卡片)、uni-popup(弹窗)等 50+ 组件,支持主题定制和国际化。
安装方式
:
- 通过命令安装
npm install @dcloudio/uni-ui
- 通过HBuilderX 插件市场导入
2.2 uView UI
优势
:提供表格、级联选择器等交互组件,内置工具函数如日期格式化,适合中后台系统开发。
2.3 ColorUI
设计
:强调视觉表现,提供渐变色按钮、动画图标,适合电商、社交类应用。
示例
:uni-ui 按钮使用
<template>
<uni-button type="primary" @click="submit">提交</uni-button>
</template>
<script>
import { UniButton } from '@dcloudio/uni-ui';
export default { components: { UniButton } }
</script>
3. 自定义组件开发
当内置组件无法满足需求时,可通过以下步骤开发自定义组件:
3.1 创建组件
目录规范
:在 components 目录下创建 MyButton.vue,包含模板、逻辑、样式三部分。
代码示例
:
<template>
<button :class="type" @click="$emit('click')">
<slot></slot>
</button>
</template>
<script>
export default {
props: {
type: {
type: String,
default: 'default' }
}
}
</script>
3.2 组件通信
Props 传值
:父组件通过 :color=“red” 传递数据。
子组件 MyButton.vue
<template>
<!-- 使用父组件传入的颜色 -->
<view
class="custom-btn"
:style="{backgroundColor: color}"
@click="handleClick"
>
<slot>默认按钮</slot>
</view>
</template>
<script>
export default {
props: {
// 接收颜色值,默认值为灰色
color: {
type: String,
default: '#cccccc'
}
},
methods: {
handleClick() {
// 向父组件触发 click 事件
this.$emit('click')
}
}
}
</script>
<style>
.custom-btn {
padding: 10px 20px;
border-radius: 8px;
color: white;
display: inline-block;
}
</style>
父组件Parent.vuew
<template>
<view>
<!-- 传递颜色并监听事件 -->
<my-button
:color="btnColor"
@click="onButtonClick"
>
红色按钮
</my-button>
<text>点击次数:{{count}}</text>
</view>
</template>
<script>
export default {
data() {
return {
btnColor: '#dd514c', // 红色
count: 0
}
},
methods: {
onButtonClick() {
this.count++
uni.showToast({ title: `点击了 ${this.count} 次` })
}
}
}
</script>
事件触发
:子组件通过 $emit(‘click’) 通知父组件。
子组件DataSender.vue
<template>
<view>
<input v-model="inputValue" />
<button @click="sendData">提交数据</button>
</view>
</template>
<script>
export default {
data() {
return {
inputValue: ''
}
},
methods: {
sendData() {
// 携带输入框数据触发事件
this.$emit('data-submit', this.inputValue)
this.inputValue = ''
}
}
}
</script>
父组件ParentAdvanced.vue
<template>
<view>
<!-- 监听自定义事件并接收参数 -->
<data-sender @data-submit="handleDataSubmit" />
<view v-for="(item, index) in list" :key="index">
{{index + 1}}. {{item}}
</view>
</view>
</template>
<script>
export default {
data() {
return {
list: []
}
},
methods: {
handleDataSubmit(data) {
if (data.trim()) {
this.list.push(data)
uni.showToast({ title: '收到数据:' + data })
}
}
}
}
</script>
3.3 优化实践
easycom 规范
:无需手动注册,组件自动全局引用。
- 配置
pages.json
// pages.json
{
"easycom": {
"autoscan": true,
"custom": {
// 匹配 components 目录下的所有vue文件
"^u-(.*)": "@/components/uni-$1/uni-$1.vue"
}
}
}
- 创建
组件文件
# 目录结构
components/
└── uni-button/
└── uni-button.vue
- 使用
组件
<template>
<view>
<!-- 自动识别 components/uni-button/uni-button.vue -->
<u-button @click="handleClick">Easycom按钮</u-button>
</view>
</template>
<script>
export default {
methods: {
handleClick() {
uni.showToast({ title: '按钮点击' })
}
}
}
</script>
CSS 变量
:通过 --theme-color 统一主题色,提升可维护性。
- 全局定义
变量
/* App.vue 的 <style> 标签 */
:root {
--theme-color: #007aff; /* 主色调 */
--warning-color: #ff4444; /* 警告色 */
--text-size: 16px; /* 基础字号 */
}
- 使用
变量
<template>
<view class="card">
<text class="title">CSS变量示例</text>
<text class="warning-text">警告信息</text>
</view>
</template>
<style>
.card {
padding: 20px;
background-color: var(--theme-color); /* 使用主色调 */
}
.title {
font-size: var(--text-size);
color: white;
}
.warning-text {
color: var(--warning-color);
}
</style>
- 动态
修改
变量
<script>
export default {
methods: {
// 切换夜间模式
toggleDarkMode() {
const root = document.documentElement
if (this.isDark) {
root.style.setProperty('--theme-color', '#007aff')
root.style.setProperty('--text-size', '16px')
} else {
root.style.setProperty('--theme-color', '#2c2c2c')
root.style.setProperty('--text-size', '14px')
}
this.isDark = !this.isDark
}
}
}
</script>
4. 总结
基础功能
:优先使用内置组件(如 scroll-view 区域滚动),确保跨端兼容性。
复杂交互
:选择 uni-ui 或 uView 减少重复开发,例如表格渲染、复杂表单。
定制需求
:通过自定义组件封装业务逻辑,如实现拖拽缩放视图(参考 movable-view 组件)。