移动端H5封装一个 ScrollList 横向滚动列表组件,实现向左滑动

效果:

image.png

1.封装组件:

<template><div class="scroll-list"><divclass="scroll-list-content":style="{ background, color, fontSize: size }"ref="scrollListContent"><div class="scroll-list-group" v-for="(item, index) in list" :key="index"><div class="scroll-list-item" v-for="menuItem in item" :style="getItemStyle"><img class="scroll-list-item-img"  :style=iconSize alt="" v-lazy="menuItem[icon]"@click="navigateToRoute(menuItem.path)"/><!--<van-image--><!--		lazy-load--><!--		fit="cover"--><!--		class="scroll-list-item-img" :src="menuItem[icon]" :style=iconSize alt=""--><!--		@click="navigateToRoute(menuItem.path)"--><!--/>--><span class="scroll-list-item-text" :style="menuItemName[0]">{{ menuItem[name] }}</span></div></div></div><div v-if="isScrollBar && indicator" class="scroll-list-indicator"><divclass="scroll-list-indicator-bar":style="{ width: width }"ref="scrollListIndicatorBar"><span:style="{ height: height }"class="scroll-list-indicator-slider"></span></div></div></div>
</template><script>import {defineComponent,onMounted,onBeforeUnmount,reactive,ref,toRefs,nextTick,watch,} from "vue";import {useRouter} from "vue-router";export default defineComponent({props: {list: {type: Array,default: () => [], // 数据},indicator: {type: Boolean,default: true, // 是否显示面板指示器},indicatorColor: {type: String,default: "rgba(250,250,250,0.56)", // 指示器非激活颜色  (暂不支持)},indicatorActiveColor: {type: String,default: "rgba(250,250,250,0.56)", // 指示器滑块颜色  (暂不支持)},indicatorWidth: {type: String,default: "", // 指示器 宽度},indicatorBottom: {type: String,default: "", // 指示器 距离内容底部的距离 (设置 0 会隐藏指示器)},background: {type: String,default: "", // 内容区域背景色},color: {type: String,default: "", // 内容区域文本颜色},size: {type: String,default: "", // 内容区域文本字体大小},indicatorStyle: {type: String,default: "", // 指示器 样式 (暂不支持)},icon: {type: String,default: "icon", // 图标字段},name: {type: String,default: "name", // 文本字段},iconSize: {type: Object,default:{width:"40px", height:"40px"}}, // 设置默认的 icon 大小iconNum: {type: String,default: "4", // 设置默认的 icon 数量},menuItemName: {type: Array,//			font-size: 12px;//color: #6B5B50;default: () => [{fontSize: "12px",color: "#6B5B50",}],// 设置默认的 icon 数量}},computed: {getItemStyle() {const widthPercent = 100 / this.iconNum;return {width: `${widthPercent}%`,};},getNameStyle() {return {// 在这里添加样式属性,根据 menuItemName 的值来设置fontSize: this.menuItemName[0].size,color: this.menuItemName[0].color,//margin-top: this.menuItemName[0].top;}}	,},setup(props) {const router = useRouter(); // 获取 Vue Router 的实例const width = ref("");const height = ref("");const {indicatorWidth, indicatorBottom, indicator} = props;watch(() => [indicatorWidth, indicatorBottom],(newVal) => {//console.log(newVal);const _width = newVal[0].includes("px") ? newVal[0] : newVal[0] + "px";const _height = newVal[1].includes("px") ? newVal[1] : newVal[1] + "px";width.value = _width;height.value = _height;},{immediate: true});const state = reactive({scrollListContent: null, // 内容区域 domscrollListIndicatorBar: null, // 底部指示器 domisScrollBar: false,});onMounted(() => {nextTick(() => {state.isScrollBar = hasScrollbar();if (!indicator || !state.isScrollBar) return;state.scrollListContent.addEventListener("scroll", handleScroll);});});onBeforeUnmount(() => {if (!indicator || !state.isScrollBar) return;// 页面卸载,移除监听事件state.scrollListContent.removeEventListener("scroll", handleScroll);});function handleScroll() {/*** 使用滚动比例来实现同步滚动* tips: 这里时一道数学题, 不同的可以把下面的几个参数都打印处理看看* 解析一下 这里的实现* state.scrollListContent.scrollWidth  内容区域的宽度* state.scrollListContent.clientWidth  当前内容所占的可视区宽度* state.scrollListIndicatorBar.scrollWidth  指示器的宽度* state.scrollListIndicatorBar.clientWidth  当前指示器所占的可视区宽度** 内容区域的宽度 - 当前内容所占的可视区宽度 = 内容区域可滚动的最大距离* 指示器的宽度 - 当前指示器所占的可视区宽度 = 指示器可滚动的最大距离** 内容区域可滚动的最大距离 / 指示器可滚动的最大距离 = 滚动比例 (scale)** 最后通过滚动比例 来算出 指示器滚动的 距离 (state.scrollListIndicatorBar.scrollLeft)** 指示器滚动的距离 = 容器滚动的距离 / 滚动比例 (对应下面的公式)** state.scrollListIndicatorBar.scrollLeft = state.scrollListContent.scrollLeft / scale*/const scale =(state.scrollListContent.scrollWidth -state.scrollListContent.clientWidth) /(state.scrollListIndicatorBar.scrollWidth -state.scrollListIndicatorBar.clientWidth);state.scrollListIndicatorBar.scrollLeft =state.scrollListContent.scrollLeft / scale;}// 导航到目标路由的方法function navigateToRoute(menuItem) {// 在这里根据 menuItem 或其他条件构建目标路由的路径//const targetRoute = `/your-target-route/${menuItem.id}`; // 示例:根据 menuItem 的 id 构建目标路由//console.log(menuItem)//JSON.parse(menuItem)// 使用 Vue Router 导航到目标路由//跳转页面router.push(JSON.parse(menuItem));}function hasScrollbar() {return (state.scrollListContent.scrollWidth >state.scrollListContent.clientWidth ||state.scrollListContent.offsetWidth >state.scrollListContent.clientWidth);}return {...toRefs(state), width, height, handleScroll, hasScrollbar, navigateToRoute};},});</script><style lang="less" scoped>.scroll-list {&-content {width: 100%;overflow-y: hidden;overflow-x: scroll;// white-space: nowrap;display: flex;flex-wrap: nowrap;/*滚动条整体样式*/&::-webkit-scrollbar {width: 0;height: 0;}}&-group {display: flex;flex-wrap: wrap;// margin-bottom: 16px;min-width: 100%;&:nth-child(2n) {margin-bottom: 0;}}&-item {// display: inline-block;margin-bottom: 16px;text-align: center;width: calc(100% / 5);&-img {width: 44px;height: 44px;object-fit: cover;}&-text {display: block;//font-size: 12px;//color: #6B5B50;font-family: "Source Han Serif CN", "思源宋体 CN", serif;font-weight: normal;}&:nth-child(n + 5) {margin-bottom: 0;}}&-indicator {width: 100%;display: flex;align-items: center;justify-content: center;pointer-events: none; // 禁用滑动指示灯时 滑块滚动&-bar {width: 40px; // 指示器的默认宽度overflow-y: hidden;overflow-x: auto;white-space: nowrap;/*滚动条整体样式*/&::-webkit-scrollbar {width: 0;height: 4px;}/* 滚动条里面小滑块 样式设置 */&::-webkit-scrollbar-thumb {border-radius: 50px; /* 滚动条里面小滑块 - radius */background: #9b6a56; /* 滚动条里面小滑块 - 背景色 */}/* 滚动条里面轨道 样式设置 */&::-webkit-scrollbar-track {border-radius: 50px; /* 滚动条里面轨道 - radius */background: #C29E94FF; /* 滚动条里面轨道 - 背景色 */}}&-slider {height: 10px;min-width: 120px;display: block;}}}</style>

组件还没完善,但是可以使用,需要增加属性增加的可以自己添加。

2.引入


import ScrollList from "@/components/ScrollList/index.vue";

3.注册

	components: {ScrollList},

4.使用

	<div class="scrollList-1"><ScrollList :list="data" :indicator="true" :indicatorWidth="scrollListWidth" :indicatorBottom="scrollListBottom"iconNum="5":iconSize="iconSizeKnowledge"/></div>

我是vue3:

const data = [[{icon: require('../assets/pic/mtzx@2x.png'),name: "关注",path: JSON.stringify({name: "test", params: {type: 1}})},{icon: require('../assets/pic/mtzx@2x.png'),name: "媒体资讯",path: JSON.stringify({name: "test", params: {type: 1}})},{icon: require('../assets/pic/mzjs@2x.png'),name: "名作鉴赏",path: JSON.stringify({name: "test", params: {type: "famous"}})},{icon: require('../assets/pic/jxbd@2x.png'),name: "鉴赏宝典",path: JSON.stringify({name: "test", params: {type: 5}})},{icon: require('../assets/pic/gyjx@2x.png'),name: "工艺赏析",path: JSON.stringify({name: "test", params: {type: 3}})},// 更多项...],[{icon: require('../assets/pic/whls@2x.png'),name: "文化历史",path: JSON.stringify({name: "test", params: {type: 7}})},{icon: require('../assets/pic/rmzs@2x.png'),name: "入门知识",path: JSON.stringify({name: "test", params: {type: 7}})},{icon: require('../assets/pic/activity.png'),name: "活动资讯",path: JSON.stringify({name: "test", params: {type: 7}})},{icon: require('../assets/pic/government_information.png'),name: "官方公告",path: JSON.stringify({name: "test", params: {type: 8}})},{icon: require('../assets/pic/other@2x.png'),name: "产业信息",path: JSON.stringify({name: "test", params: {type: test}})},// 更多项...],// 更多分组...];const scrollListWidth = "60px";// 传递给 ScrollList 的宽度const scrollListBottom = "20px"; // 传递给 ScrollList 的指示器底部距离const iconSizeKnowledge = ref({width: "60px", height: "60px"})return {data,scrollListWidth,scrollListBottom,keyword,isSearchBoxFixed, famousLampStyle, masterStyle, iconSize, iconSizeJz, iconSizeKnowledge};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# OpenVino Yolov8 Pose 姿态识别

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenVino_Yolov8_Demo {public…

独立开发了一款Material3风格的RSS阅读器 - Agr Reader

截图 背景&#x1f4d6; 在之前接触到RSS后&#xff0c;发现RSS真是一个十分不错的信息聚合的方式&#xff0c;虽然现在看来RSS的时代已经开始落幕&#xff0c;但是至少目前还是处于能用的阶段。 在我用了Android上好几个RSS阅读App后&#xff0c;发现很多在全文解析方面不是…

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染&#xff0c;动态轨迹播放&#xff0c;自定义图形以及轨迹上显示箭头方向 1. 效果图2. 源码2.1 line.html2.2line_arrow.html 参考 今天要排查个问题&#xff0c;需要显示多个经纬度点连接成线段的方向&#xff0c;于是尝试下展示。 1. mapbox渲染经…

element plus封装el-select添加后缀图标并添加远程搜索和对话框功能

当提交的表单Form需要填某个实体的外键ID时&#xff0c;当然不可能使用el-input组件&#xff0c;这个适合提交字符串&#xff0c;然后用户又不可能记住某个引用的外键ID&#xff0c;这时候使用el-select还是必要的。 el-select组件一般都作为下拉选择框使用&#xff0c;但仅在…

远程计算机控制软件

远程控制软件允许您连接和控制位于不同位置的设备&#xff0c;对于 IT 帮助台技术人员来说&#xff0c;这是一个很好的工具&#xff0c;可以通过与用户协作、与他们聊天以及安全地访问他们的文件来轻松排除故障和修复远程设备。使用远程控制软件&#xff0c;距离不再是提供技术…

无涯教程-JavaScript - ATAN函数

描述 The ATAN function returns the arctangent, or inverse tangent, of a number. The returned angle is given in radians between -π/2 and π/2. The arctangent is the angle whose tangent is number. 语法 ATAN (number)争论 Argument描述Required/OptionalNumb…

Vulnhub实战-prime1

前言 VulnHub 是一个面向信息安全爱好者和专业人士的虚拟机&#xff08;VM&#xff09;漏洞测试平台。它提供了一系列特制的漏洞测试虚拟机镜像&#xff0c;供用户通过攻击和漏洞利用的练习来提升自己的安全技能。本次&#xff0c;我们本次测试的是prime1。 一、主机发现和端…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

【机器学习】文本多分类

声明&#xff1a;这只是浅显的一个小试验&#xff0c;且借助了AI。使用的是jupyter notebook,所以代码是一块一块&#xff0c;从上往下执行的 知识点&#xff1a;正则删除除数字和字母外的所有字符、高频词云、混淆矩阵 参考&#xff1a;使用python和sklearn的中文文本多分类…

DS相关题目

DS相关题目 题目一&#xff1a;消失的数字 拿到这道题目之后&#xff0c;首先可以想到的一个解题方法就是&#xff0c;我们可以先排序&#xff0c;排完序之后&#xff0c;这个数组其实就是一个有序的数组了&#xff0c;那只用比较数组中的每一个元素和他对应的下标是不是相等的…

代码管理工具git1

ctrl 加滚轮 放大字体 在计算机任意位置单击右键&#xff0c;选择&#xff1a;&#xff1a;Git Bash Here git version git清屏命令&#xff1a;ctrl L查看用户名和邮箱地址&#xff1a; $ git config user.name$ git config user.email修改用户名和邮箱地址&#xff1a;$ git…

C#中Visual Studio如何为解决方案设置启动项目

目录 第一种方法:快速选定启动项目的方法1.在解决方案资源管理器中,选择解决方案(最高层节点)2.选择解决方案节点的上下文(右键单击)菜单,然后选择“属性”。 “解决方案属性页”对话框随即显示第二种方法:右击First11或者second11,点击设置启动项目即可Visual Studio…

C#使用DirectX SDK 加载.x三维模型

最近因为项目要做显示一个三维模型&#xff0c;所以研究了下如何在Winform中加载并显示三维模型。在Windows平台巨硬公司提供了DirectX SDK用于渲染图形&#xff0c;参考了几篇文章做了个demo记录下&#xff0c;以便日后温习只用。这个SDK涉及到了计算机图形学的一些基础知识&a…

【物联网】简要解释RTK(Real-Time Kinematic)>>实时动态差分定位

引言&#xff1a; RTK&#xff08;Real-Time Kinematic&#xff09;技术是一种基于差分GPS的高精度定位技术&#xff0c;它通过实时通信和数据处理&#xff0c;能够提供厘米级甚至亚米级的定位精度。RTK技术在许多领域都得到了广泛应用&#xff0c;如测绘、航空航天、农业等。本…

Springboot -- DOCX转PDF(二)

之前记录了按照模板生成 DOCX 文件、并转换为 PDF 文件的方法 https://blog.csdn.net/qq_40096897/article/details/131979177?spm1001.2014.3001.5501 但是使用效果并不是很理想&#xff0c;转换完的 PDF 格式和原本的文档格式不匹配。所以在此重新找了一个文件转 PDF 的方法…

职场工作与生活

序言&#xff1a; 和很多在CSDN的博主一样&#xff0c;大家在工作之后就很少或者是不再回到CSDN&#xff0c;确实自己也一年多没上了。因为可能当初大家在这就是为了记录和分享当初自己学习技术的东西。而大家走出象牙塔开始工作后&#xff0c;发生了很大的转变。在国内…

PY32F003F18之输入捕获

输入捕获是定时器的功能之一&#xff0c;配合外部引脚&#xff0c;捕获脉宽时间或采集周期。 CPU中的定时器最基本的功能就是计数功能&#xff0c;其次是输入捕获(IC)&#xff0c;再次就是比较输出(OC)&#xff0c;还有就是使用引脚对外部时钟进行计数&#xff0c;触发信号捕捉…

阿里云 linux 的nginx 配置uni-app的H5前端项目vue,后端接口阿里云。

背景 vue项目调用接口是阿里云的&#xff0c;H5网站也要部署到阿里云&#xff0c;2个不同的服务器&#xff0c;需要做nginx部署与api代理。 端口配置 首先当然是买个阿里云服务器&#xff0c;这里是配置是linux系统&#xff0c;配置访问的域名 &#xff0c;再接着&#xff1…

iOS系统暗黑模式

系统暗黑模式&#xff1a; 暗黑模式颜色适配&#xff1a; 方式1&#xff1a; Assets配置&#xff1a;在Assets中配置好颜色后&#xff0c;可以通过colorNamed: 放大获取到动态颜色。 方式2&#xff1a;代码配置&#xff0c;通过代码colorWithDynamicProvider: 可以看出来生成…

【Obsidian】中编辑模式和阅读模式光标乱跳问题以及编辑模式中段落聚集的问题解决

前言 最近用Obsidian 软件写md笔记&#xff0c;但是当我分别使用编辑模式和阅读模式时出现了光标乱跳的问题。比如我在编辑模式&#xff0c;光标停留在第500行&#xff0c;但是切换成编辑模式就变成了1000行。而且光标根本没停在原来的位置。这样重新定位非常麻烦。 两种阅读…