全篇大概 7000 字(含代码),建议阅读时间 30min
UniApp 基于 Vue.js 的跨平台特性,提供了丰富的内置组件和灵活的扩展能力。本文将从内置组件、扩展组件库和自定义组件开发三个维度,系统解析 UniApp 的组件生态,并结合实际开发场景提供实践建议。
目录
UniApp 内置组件经过多端适配,可自动转换为原生控件,确保一致性和性能。以下是核心分类及使用要点:
标签名 | 描述 |
---|---|
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 1view>
<view class="box" style="background-color: #5bc0de;">Box 2view>
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 1view>
swiper-item>
<swiper-item>
<view class="swiper-item" style="background-color: #007aff;">Page 2view>
swiper-item>
swiper>
template>
<style>
.swiper-item {
height: 200px;
text-align: center;
line-height: 200px;
}
style>
标签名 | 描述 |
---|---|
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>
标签名 | 描述 |
---|---|
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>
标签名 | 描述 |
---|---|
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>
组件样式默认已适配多端,但如 button 在 H5 显示蓝色,小程序显示绿色。
原生组件(如 map、video)层级高于前端组件,需使用 cover-view 覆盖。
对于复杂场景,UniApp 生态提供了多款高质量扩展库:
功能
:官方维护的组件库,包含 uni-card(卡片)、uni-popup(弹窗)等 50+ 组件,支持主题定制和国际化。
安装方式
:
npm install @dcloudio/uni-ui
优势
:提供表格、级联选择器等交互组件,内置工具函数如日期格式化,适合中后台系统开发。
设计
:强调视觉表现,提供渐变色按钮、动画图标,适合电商、社交类应用。
示例
:uni-ui 按钮使用
<template>
<uni-button type="primary" @click="submit">提交uni-button>
template>
<script>
import { UniButton } from '@dcloudio/uni-ui';
export default { components: { UniButton } }
script>
当内置组件无法满足需求时,可通过以下步骤开发自定义组件:
目录规范
:在 components 目录下创建 MyButton.vue,包含模板、逻辑、样式三部分。
代码示例
:
<template>
<button :class="type" @click="$emit('click')">
<slot>slot>
button>
template>
<script>
export default {
props: {
type: {
type: String,
default: 'default' }
}
}
script>
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>
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>
<u-button @click="handleClick">Easycom按钮u-button>
view>
template>
<script>
export default {
methods: {
handleClick() {
uni.showToast({ title: '按钮点击' })
}
}
}
script>
CSS 变量
:通过 --theme-color 统一主题色,提升可维护性。
变量
/* App.vue 的