当前位置: 首页 > ds >正文

鸿蒙OSUniApp制作动态筛选功能的列表组件(鸿蒙系统适配版)#三方框架 #Uniapp

使用UniApp制作动态筛选功能的列表组件(鸿蒙系统适配版)

前言

随着移动应用的普及,用户对应用内容检索和筛选的需求也越来越高。在开发跨平台应用时,动态筛选功能已成为提升用户体验的重要组成部分。本文将详细介绍如何使用UniApp开发一个功能完善的动态筛选列表组件,并重点关注如何适配鸿蒙系统,确保在华为设备上获得良好的用户体验。

需求分析

在日常应用场景中,常见的动态筛选功能包括:

  1. 多条件组合筛选(如价格、分类、评分等)
  2. 筛选条件的动态加载
  3. 筛选结果的实时更新
  4. 筛选历史记录保存
  5. 鸿蒙系统上的特殊适配

一个优秀的筛选组件应该具备以下特点:易用性强、响应速度快、视觉反馈清晰、适配多平台(特别是鸿蒙系统)。

技术选型

我们将使用以下技术栈:

  • UniApp作为跨平台开发框架
  • Vue3 + TypeScript提供响应式编程体验
  • uView UI组件库辅助界面开发
  • Vuex管理筛选状态
  • 针对鸿蒙系统的特殊API调用

组件设计与实现

1. 基础结构设计

首先,我们设计组件的基础结构:

<template><view class="filter-container"><!-- 筛选条件区域 --><view class="filter-header"><view v-for="(item, index) in filterOptions" :key="index"class="filter-tab":class="{'active': currentTab === index}"@click="switchTab(index)"><text>{{ item.name }}</text><text class="icon" :class="{'icon-up': item.isOpen, 'icon-down': !item.isOpen}"></text></view></view><!-- 筛选面板 --><view class="filter-panel" v-if="showPanel"><component :is="activeComponent" :options="activeOptions"@confirm="confirmFilter"@reset="resetFilter"></component></view><!-- 列表区域 --><view class="list-container"><view v-for="(item, index) in filteredList" :key="index"class="list-item harmony-list-item"><text class="item-title">{{ item.title }}</text><text class="item-desc">{{ item.description }}</text></view><!-- 空数据提示 --><view class="empty-tip" v-if="filteredList.length === 0"><text>暂无符合条件的数据</text></view></view></view>
</template><script lang="ts">
import { defineComponent, ref, reactive, computed, onMounted } from 'vue';
import CategoryFilter from './filter-components/CategoryFilter.vue';
import PriceFilter from './filter-components/PriceFilter.vue';
import SortFilter from './filter-components/SortFilter.vue';
import { isHarmonyOS, adaptToHarmonyOS } from '@/utils/platform';export default defineComponent({components: {CategoryFilter,PriceFilter,SortFilter},setup() {// 是否为鸿蒙系统const isHarmony = ref(false);// 筛选选项定义const filterOptions = reactive([{ name: '分类', type: 'category', isOpen: false },{ name: '价格', type: 'price', isOpen: false },{ name: '排序', type: 'sort', isOpen: false },]);// 当前选中的标签const currentTab = ref(-1);// 是否显示筛选面板const showPanel = computed(() => currentTab.value >= 0);// 筛选条件const filterConditions = reactive({category: [],price: { min: 0, max: 9999 },sort: 'default'});// 原始数据列表const originalList = ref([]);// 获取筛选后的列表const filteredList = computed(() => {return originalList.value.filter((item: any) => {// 分类筛选if (filterConditions.category.length > 0 && !filterConditions.category.includes(item.category)) {return false;}// 价格筛选if (item.price < filterConditions.price.min || item.price > filterConditions.price.max) {return false;}return true;}).sort((a: any, b: any) => {// 排序逻辑if (filterConditions.sort === 'price-asc') {return a.price - b.price;} else if (filterConditions.sort === 'price-desc') {return b.price - a.price;}return 0;});});// 当前激活的筛选组件const activeComponent = computed(() => {if (currentTab.value < 0) return null;const type = filterOptions[currentTab.value].type;return type.charAt(0).toUpperCase() + type.slice(1) + 'Filter';});// 当前筛选组件的选项const activeOptions = computed(() => {if (currentTab.value < 0) return {};const type = filterOptions[currentTab.value].type;return filterConditions[type];});// 切换筛选标签const switchTab = (index: number) => {if (currentTab.value === index) {currentTab.value = -1;filterOptions[index].isOpen = false;} else {// 关闭之前打开的标签if (currentTab.value >= 0) {filterOptions[currentTab.value].isOpen = false;}currentTab.value = index;filterOptions[index].isOpen = true;}};// 确认筛选const confirmFilter = (data: any) => {const type = filterOptions[currentTab.value].type;filterConditions[type] = data;currentTab.value = -1;filterOptions[currentTab.value].isOpen = false;// 保存筛选历史saveFilterHistory();};// 重置筛选const resetFilter = () => {const type = filterOptions[currentTab.value].type;if (type === 'category') {filterConditions.category = [];} else if (type === 'price') {filterConditions.price = { min: 0, max: 9999 };} else if (type === 'sort') {filterConditions.sort = 'default';}};// 保存筛选历史const saveFilterHistory = () => {uni.setStorageSync('filter_history', JSON.stringify(filterConditions));};// 获取筛选历史const getFilterHistory = () => {try {const history = uni.getStorageSync('filter_history');if (history) {const parsedHistory = JSON.parse(history);Object.assign(filterConditions, parsedHistory);}} catch (e) {console.error('获取筛选历史失败', e);}};// 获取列表数据const fetchListData = () => {// 这里模拟数据请求setTimeout(() => {originalList.value = [{ id: 1, title: '商品1', description: '这是商品1的描述', category: 'food', price: 129 },{ id: 2, title: '商品2', description: '这是商品2的描述', category: 'food', price: 59 },{ id: 3, title: '商品3', description: '这是商品3的描述', category: 'cloth', price: 199 },{ id: 4, title: '商品4', description: '这是商品4的描述', category: 'electronic', price: 1299 },{ id: 5, title: '商品5', description: '这是商品5的描述', category: 'electronic', price: 899 },];}, 500);};onMounted(() => {// 检测是否为鸿蒙系统isHarmony.value = isHarmonyOS();// 鸿蒙系统适配if (isHarmony.value) {adaptToHarmonyOS();}// 获取数据fetchListData();// 获取历史筛选条件getFilterHistory();});return {filterOptions,currentTab,showPanel,filteredList,activeComponent,activeOptions,switchTab,confirmFilter,resetFilter,isHarmony};}
});
</script><style>
.filter-container {display: flex;flex-direction: column;width: 100%;
}.filter-header {display: flex;height: 88rpx;border-bottom: 1rpx solid #eee;background-color: #fff;
}.filter-tab {flex: 1;display: flex;justify-content: center;align-items: center;font-size: 28rpx;color: #333;
}.filter-tab.active {color: #007aff;
}.icon {margin-left: 10rpx;font-size: 24rpx;
}.filter-panel {border-bottom: 1rpx solid #eee;background-color: #fff;
}.list-container {padding: 20rpx;
}.list-item {margin-bottom: 20rpx;padding: 20rpx;background-color: #fff;border-radius: 8rpx;box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}.harmony-list-item {/* 鸿蒙系统特有样式 */border-radius: 16rpx;background: linear-gradient(to right, #f8f8f8, #fff);
}.item-title {font-size: 32rpx;font-weight: bold;margin-bottom: 10rpx;
}.item-desc {font-size: 28rpx;color: #666;
}.empty-tip {display: flex;justify-content: center;padding: 100rpx 0;color: #999;
}
</style>

2. 分类筛选子组件

<template><view class="category-filter"><view class="filter-options"><view v-for="(item, index) in categories" :key="index"class="category-item":class="{'selected': selected.includes(item.value)}"@click="toggleSelect(item.value)"><text>{{ item.label }}</text></view></view><view class="filter-actions"><button class="btn-reset" @click="reset">重置</button><button class="btn-confirm" @click="confirm">确定</button></view></view>
</template><script lang="ts">
import { defineComponent, ref } from 'vue';export default defineComponent({props: {options: {type: Array,default: () => []}},emits: ['confirm', 'reset'],setup(props, { emit }) {// 分类选项const categories = [{ label: '食品', value: 'food' },{ label: '服装', value: 'cloth' },{ label: '电子产品', value: 'electronic' },{ label: '家居', value: 'household' },{ label: '美妆', value: 'beauty' }];// 已选择的分类const selected = ref(props.options || []);// 切换选择const toggleSelect = (value: string) => {const index = selected.value.indexOf(value);if (index > -1) {selected.value.splice(index, 1);} else {selected.value.push(value);}};// 确认选择const confirm = () => {emit('confirm', [...selected.value]);};// 重置选择const reset = () => {selected.value = [];emit('reset');};return {categories,selected,toggleSelect,confirm,reset};}
});
</script><style>
.category-filter {padding: 20rpx;
}.filter-options {display: flex;flex-wrap: wrap;margin-bottom: 30rpx;
}.category-item {width: 30%;height: 80rpx;margin: 10rpx 1.66%;display: flex;justify-content: center;align-items: center;border: 1rpx solid #eee;border-radius: 8rpx;font-size: 28rpx;
}.category-item.selected {background-color: #e1f0ff;border-color: #007aff;color: #007aff;
}.filter-actions {display: flex;justify-content: space-between;padding: 20rpx 0;
}.btn-reset, .btn-confirm {width: 45%;height: 80rpx;line-height: 80rpx;text-align: center;border-radius: 8rpx;font-size: 28rpx;
}.btn-reset {background-color: #f5f5f5;color: #666;
}.btn-confirm {background-color: #007aff;color: #fff;
}
</style>

3. 鸿蒙系统适配工具函数

// utils/platform.ts/*** 检测当前环境是否为鸿蒙系统*/
export function isHarmonyOS(): boolean {// #ifdef APP-PLUSconst systemInfo = uni.getSystemInfoSync();const systemName = systemInfo.osName || '';const systemVersion = systemInfo.osVersion || '';// 鸿蒙系统识别return systemName.toLowerCase().includes('harmony') || (systemName === 'android' && systemVersion.includes('harmony'));// #endifreturn false;
}/*** 鸿蒙系统适配操作*/
export function adaptToHarmonyOS(): void {// #ifdef APP-PLUStry {// 调整状态栏plus.navigator.setStatusBarStyle('dark');// 适配鸿蒙特有APIif (plus.os.name === 'Android' && plus.device.vendor === 'HUAWEI') {// 这里可以添加针对华为设备的特殊处理console.log('正在运行于华为设备,进行鸿蒙系统适配');// 示例:自定义字体适配// 鸿蒙系统使用HarmonyOS Sans字体const fontFamily = plus.os.version.includes('harmony') ? 'HarmonyOS_Sans' : 'sans-serif';// 可以通过CSS变量设置全局字体document.documentElement.style.setProperty('--app-font-family', fontFamily);}} catch (e) {console.error('鸿蒙系统适配失败', e);}// #endif
}/*** 针对鸿蒙系统优化动画效果* @param element DOM元素*/
export function optimizeAnimationForHarmony(element: any): void {if (!isHarmonyOS()) return;// #ifdef APP-PLUStry {// 在鸿蒙系统上优化动画性能if (element && element.style) {element.style.setProperty('transform', 'translateZ(0)');element.style.setProperty('backface-visibility', 'hidden');element.style.setProperty('perspective', '1000px');}} catch (e) {console.error('动画优化失败', e);}// #endif
}

功能详解

1. 动态筛选核心逻辑

组件的核心是通过计算属性filteredList实现动态筛选。每当筛选条件变化时,该计算属性会重新计算,过滤出符合条件的数据项:

const filteredList = computed(() => {return originalList.value.filter((item: any) => {// 分类筛选if (filterConditions.category.length > 0 && !filterConditions.category.includes(item.category)) {return false;}// 价格筛选if (item.price < filterConditions.price.min || item.price > filterConditions.price.max) {return false;}return true;}).sort((a: any, b: any) => {// 排序逻辑if (filterConditions.sort === 'price-asc') {return a.price - b.price;} else if (filterConditions.sort === 'price-desc') {return b.price - a.price;}return 0;});
});

2. 鸿蒙系统适配要点

在开发过程中,我们需要特别关注鸿蒙系统的适配问题:

  1. 系统检测:通过isHarmonyOS()函数检测当前运行环境是否为鸿蒙系统
  2. UI适配:针对鸿蒙系统的UI特点(如圆角大小、渐变风格等)进行样式调整
  3. 字体适配:鸿蒙系统推荐使用HarmonyOS Sans字体
  4. 动画优化:针对鸿蒙系统的渲染引擎特点进行动画性能优化

示例中的.harmony-list-item样式类展示了如何为鸿蒙系统添加特定样式:

.harmony-list-item {/* 鸿蒙系统特有样式 */border-radius: 16rpx;background: linear-gradient(to right, #f8f8f8, #fff);
}

3. 性能优化

为了确保组件在各平台(尤其是鸿蒙系统)上的流畅运行,我们采取了以下优化措施:

  1. 虚拟列表:当数据量大时,可以使用虚拟列表技术,只渲染可视区域的内容
  2. 懒加载:筛选条件组件采用懒加载方式,按需渲染
  3. 数据缓存:对筛选结果进行缓存,避免重复计算
  4. 防抖处理:对筛选操作添加防抖处理,避免频繁触发

实际应用案例

电商商品列表筛选

在电商应用中,可以使用该组件实现商品的多维度筛选,如根据分类、价格、销量等条件筛选商品。

资讯内容筛选

在新闻资讯类应用中,可以使用该组件实现内容的分类筛选,如按照时间、类别、关键词等条件筛选文章。

鸿蒙生态应用

特别是在针对华为鸿蒙生态开发的应用中,该组件可以很好地适配鸿蒙系统的UI风格,提供流畅的用户体验。

总结

本文详细介绍了如何使用UniApp开发一个功能完善的动态筛选列表组件,并重点关注了鸿蒙系统的适配问题。通过合理的组件设计和性能优化,我们可以开发出用户体验良好的筛选功能,满足各种业务场景的需求。

在实际开发中,还可以根据具体业务需求对组件进行扩展和定制,比如添加更多的筛选维度、优化筛选条件的展示方式、增强数据加载性能等。希望本文对你在UniApp开发中实现动态筛选功能有所帮助。

参考资源

  1. UniApp官方文档
  2. 鸿蒙系统设计规范
  3. Vue3官方文档
  4. TypeScript官方文档
http://www.xdnf.cn/news/6440.html

相关文章:

  • 青少年编程与数学 02-019 Rust 编程基础 14课题、并发编程
  • 网络安全EN18031-1,EN18031-2,EN18031-3三个标准对应的测试项目
  • google-Chrome常用插件
  • 费曼技巧实践
  • YOLO v3:目标检测领域的质变性飞跃
  • 如何快速入门-衡石科技分析平台
  • 单片机 | 基于STM32的智能马桶设计
  • 微信小程序云函数中的 limit() 和 skip(),以及实现分页请求
  • React与Docker中的MySQL进行交互
  • 如何在Google Chrome浏览器里-安装梦精灵AI提示词管理工具
  • 从单体架构到微服务:架构演进之路
  • AI、机器学习、深度学习:一文厘清三者核心区别与联系
  • CentOS7 OpenSSL升级1.1.1w
  • 华为数字政府与数字城市售前高级专家认证介绍
  • Java - Junit框架
  • 鸿蒙OSUniApp 制作自定义弹窗与模态框组件#三方框架 #Uniapp
  • 专项智能练习(加强题型)-DA-02
  • 【HarmonyOS 5】鸿蒙星闪NearLink详解
  • 【redis】redis常见数据结构及其底层,redis单线程读写效率高于多线程的理解,
  • PaddleClas 车辆属性模型vehicle_attribute_model转onnx并部署
  • 2025年5月H12-831新增题库带解析
  • mac安装cast
  • 医疗数据迁移质量与效率的深度研究:三维六阶框架与实践创新
  • 【QGIS二次开发】地图显示与交互-03
  • Windows平台OpenManus部署及WebUI远程访问实现
  • JS中的数据类型
  • 匿名函数lambda、STL与正则表达式
  • 3天北京旅游规划
  • 动态规划问题 -- 多状态模型(删除并获得点数)
  • 【python】windows实现与k230使用socket通信并传输文件