uniapp 系统学习,从入门到实战(五)—— 组件库与常用 UI 组件

全篇大概 7000 字(含代码),建议阅读时间 30min


UniApp 基于 Vue.js 的跨平台特性,提供了丰富的内置组件和灵活的扩展能力。本文将从内置组件、扩展组件库和自定义组件开发三个维度,系统解析 UniApp 的组件生态,并结合实际开发场景提供实践建议。

📚 目录

  1. 内置组件
  2. 扩展组件库
  3. 自定义组件开发
  4. 总结

1. 内置组件

UniApp 内置组件经过多端适配,可自动转换为原生控件,确保一致性和性能。以下是核心分类及使用要点:

1.1 视图容器​

标签名 描述
view 基础容器,类似HTML的div,支持fle布局和嵌套
scroll-view 可滚动区域,需设置固定高度(纵向滚动)或 white-space: nowrap(横向滚动)。支持触底事件 @scrolltolower 和下拉刷新。
swiper 轮播容器,需搭配 swiper-item 使用。通过 indicator-dots 显示指示点,autoplay 实现自动切换。

view示例代码:

html 复制代码
<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示例代码:

html 复制代码
<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示例代码:

html 复制代码
<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示例代码:

html 复制代码
<template>
  <!-- 可选中文本 -->
  <text selectable space="ensp">
    这是  带空格的文本(ENSP空格)
  </text>
  
  <!-- 换行文本 -->
  <text>\n换行文本示例</text>
</template>

image示例代码:

html 复制代码
<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示例代码:

html 复制代码
<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示例代码:

html 复制代码
<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示例代码:

html 复制代码
<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示例代码:

html 复制代码
<template>
  <!-- 保留当前页跳转 -->
  <navigator 
    url="/pages/detail/detail" 
    open-type="navigate"
  >
    跳转到详情页
  </navigator>

  <!-- 关闭当前页跳转 -->
  <navigator 
    url="/pages/home/home" 
    open-type="redirect"
  >
    返回首页
  </navigator>
</template>

video示例代码:

html 复制代码
<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+ 组件,支持主题定制和国际化。
安装方式

  1. 通过命令安装
bash 复制代码
 npm install @dcloudio/uni-ui
  1. 通过HBuilderX 插件市场导入

2.2 uView UI​

优势:提供表格、级联选择器等交互组件,内置工具函数如日期格式化,适合中后台系统开发。

2.3 ColorUI​

设计:强调视觉表现,提供渐变色按钮、动画图标,适合电商、社交类应用。
示例:uni-ui 按钮使用​

html 复制代码
<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,包含模板、逻辑、样式三部分。

代码示例

html 复制代码
<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

html 复制代码
<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

html 复制代码
<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

html 复制代码
<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

html 复制代码
<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 规范:无需手动注册,组件自动全局引用。

  1. 配置 pages.json
json 复制代码
// pages.json
{
  "easycom": {
    "autoscan": true,
    "custom": {
      // 匹配 components 目录下的所有vue文件
      "^u-(.*)": "@/components/uni-$1/uni-$1.vue"
    }
  }
}
  1. 创建组件文件
bash 复制代码
# 目录结构
components/
  └── uni-button/
        └── uni-button.vue
  1. 使用组件
html 复制代码
<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 统一主题色,提升可维护性。

  1. 全局定义变量
css 复制代码
/* App.vue 的 <style> 标签 */
:root {
  --theme-color: #007aff;    /* 主色调 */
  --warning-color: #ff4444;  /* 警告色 */
  --text-size: 16px;         /* 基础字号 */
}
  1. 使用变量
html 复制代码
<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>
  1. 动态修改变量
html 复制代码
<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 组件)。

相关推荐
程序猿看视界11 小时前
Uni-app页面信息与元素影响解析
uni-app·状态栏·安全区域·窗口信息·像素比
清晨細雨11 小时前
UniApp集成极光推送详细教程
android·ios·uni-app·极光推送
_未知_开摆11 小时前
uniapp APP端在线升级(简版)
开发语言·前端·javascript·vue.js·uni-app
Li_na_na0112 小时前
解决安卓手机WebView无法直接预览PDF的问题(使用PDF.js方案)
android·pdf·uni-app·html5
web_Hsir17 小时前
uniapp 微信小程序项目中 地图 map组件 滑动面板
微信小程序·uni-app·notepad++
平凡的阿泽20 小时前
uniapp编译的app在ios上内存泄漏了
uni-app
大叔_爱编程21 小时前
wx203基于ssm+vue+uniapp的教学辅助小程序
vue.js·小程序·uni-app·毕业设计·ssm·源码·课程设计
咸虾米_1 天前
uniapp微信小程序获取用户手机号uniCloud云开发版
微信小程序·小程序·uni-app·unicloud·获取手机号
伊泽瑞尔.2 天前
uniapp自定义目录tree(支持多选、单选、父子联动、全选、取消、目录树过滤、异步懒加载节点、v-model)vue版本
uni-app
lyz2468592 天前
uniapp uni-swipe-action滑动内容排版改造
uni-app