uniapp v-tabs修改了几项功能,根据自己需求自己改

news2024/12/20 12:32:41

根据自己的需求都可以改

这里写自定义目录标题

    • 1.数组中的名字过长,导致滑动异常
    • 2.change 事件拿不到当前点击的数据,通过index在原数组中查找得到所需要的id 各种字段麻烦
    • 3.添加指定下标下新加红点显示样式

在这里插入图片描述

1.数组中的名字过长,导致滑动异常

2.change 事件拿不到当前点击的数据,通过index在原数组中查找得到所需要的id 各种字段麻烦

直接帮点前点击的传上来 change方法中 直接获取 item ,index

<v-tabs v-model="current" v-model:tipsindex='tipsindex' ellipsisNums='3'  v-model:tipsnums='tipsnums'  isEllipsis :tabs="tabs" @change="changeTab">
const changeTab =(item,index)=>{
	console.log(item)
	console.log(index)
}

3.添加指定下标下新加红点显示样式

一般情况下只能会在某一项上添加红点,所以只用传显示的下标以及数量,每一项都显示的话这种场景直接在作者的源码里v-tabs.vue里面 slot这里直接添加一个布局,显示每一列的数量就行,

直觉贴代码

props.js 里面新加
  // 名字过长是否缩写
  isEllipsis: {
    type: Boolean,
    default: false
  },
  // 超过数量
  ellipsisNums: {
    type: [Number, String],
    default: 5
  },
  // 红点显示的下标
  tipsindex: {
    type: [Number, String],
    default: 0
  },
  // 红点显示的数量
  tipsnums: {
    type: [Number, String],
    default: 0
  },
    // 红点背景颜色
  tipbg: {
    type:String,
    default: 'red'
  },
  // 红点颜色
  tipcolor: {
    type:String,
    default: '#ff'
  }
v-tabs.vue  直接复制
<template>
  <view class="v-tabs">
    <scroll-view
      :id="getDomId"
      :scroll-x="scroll"
      :scroll-left="scroll ? scrollLeft : 0"
      :scroll-with-animation="scroll"
      :style="{ position: fixed ? 'fixed' : 'relative', zIndex, width: '100%' }">
      <view
        class="v-tabs__container"
        :style="{
          display: scroll ? 'inline-flex' : 'flex',
          whiteSpace: scroll ? 'nowrap' : 'normal',
          background: bgColor,
          height,
          padding
        }">
        <view
          :class="['v-tabs__container-item', { disabled: !!v.disabled }, { active: current == i }]"
          v-for="(v, i) in tabs"
          :key="i"
          :style="{
            color: current == i ? activeColor : color,
            fontSize: current == i ? fontSize : fontSize,
            fontWeight: bold && current == i ? 'bold' : '',
            justifyContent: !scroll ? 'center' : '',
            flex: scroll ? '' : 1,
            padding: paddingItem
          }"
          @click="change(v,i)">
          <slot :row="v" :index="i">
			  <view class="name">{{ field ? limitText( v[field]) : limitText(v) }}</view>
			  <view class="tip" v-if="tipsindex===i">
				  {{tipsnums}}
			  </view>
		  </slot>
        </view>
        <template v-if="!!tabs.length">
          <view
            v-if="!pills"
            :class="['v-tabs__container-line', { animation: lineAnimation }]"
            :style="{
              background: lineColor,
              width: lineWidth + 'px',
              height: lineHeight,
              borderRadius: lineRadius,
              transform: `translate3d(${lineLeft}px, 0, 0)`
            }" />
          <view
            v-else
            :class="['v-tabs__container-pills', { animation: lineAnimation }]"
            :style="{
              background: pillsColor,
              borderRadius: pillsBorderRadius,
              width: currentWidth + 'px',
              transform: `translate3d(${pillsLeft}px, 0, 0)`,
              height
            }" />
        </template>
      </view>
    </scroll-view>
    <!-- fixed 的站位高度 -->
    <view class="v-tabs__placeholder" :style="{ height: fixed ? height : '0', padding }"></view>
  </view>
</template>

<script>
import { startMicroTask, throttle } from './utils'
import props from './props'
/**
 * v-tabs
 * @property {Number} value 选中的下标
 * @property {Array} tabs tabs 列表
 * @property {String} bgColor = '#fff' 背景颜色
 * @property {String} color = '#333' 默认颜色
 * @property {String} activeColor = '#2979ff' 选中文字颜色
 * @property {String} fontSize = '28rpx' 默认文字大小
 * @property {String} activeFontSize = '28rpx' 选中文字大小
 * @property {Boolean} bold = [true | false] 选中文字是否加粗
 * @property {Boolean} scroll = [true | false] 是否滚动
 * @property {String} height = '60rpx' tab 的高度
 * @property {String} lineHeight = '10rpx' 下划线的高度
 * @property {String} lineColor = '#2979ff' 下划线的颜色
 * @property {Number} lineScale = 0.5 下划线的宽度缩放比例
 * @property {String} lineRadius = '10rpx' 下划线圆角
 * @property {Boolean} pills = [true | false] 是否胶囊样式
 * @property {String} pillsColor = '#2979ff' 胶囊背景色
 * @property {String} pillsBorderRadius = '10rpx' 胶囊圆角大小
 * @property {String} field 如果是对象,显示的键名
 * @property {Boolean} fixed = [true | false] 是否固定
 * @property {String} paddingItem = '0 22rpx' 选项的边距
 * @property {Boolean} lineAnimation = [true | false] 下划线是否有动画
 * @property {Number} zIndex = 1993 默认层级
 * @property {Boolean} isEllipsis  = [true | false] 名字过长是否简写...
 * @property {Boolean} ellipsisNums  =  名字超过几个
 * @property {Boolean} tipsindex  =  红点要显示的下标
 * @property {Boolean} tipsnums  =  红点要显示的数量 
 * @event {Function(current)} change 改变标签触发
 */ 
export default {
  name: 'VTabs',
  props,
  // #ifdef VUE3
  emits: ['update:modelValue', 'change'],
  // #endif
  data() {
    return {
      lineWidth: 30,
      currentWidth: 0, // 当前选项的宽度
      lineLeft: 0, // 滑块距离左侧的位置
      pillsLeft: 0, // 胶囊距离左侧的位置
      scrollLeft: 0, // 距离左边的位置
      container: { width: 0, height: 0, left: 0, right: 0 }, // 容器的宽高,左右距离
      current: 0, // 当前选中项
      scrollWidth: 0 // 可以滚动的宽度
    }
  },
  computed: {
    getDomId() {
      const len = 16
      const $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678' /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
      const maxPos = $chars.length
      let pwd = ''
      for (let i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos))
      }
      return `xfjpeter_${pwd}`
    }
  },
  watch: {
    // #ifdef VUE3
    modelValue: {
    // #endif
    // #ifdef VUE2
    value: {
    // #endif
      immediate: true,
      handler(newVal) {
        this.current = newVal > -1 && newVal < this.tabs.length ? newVal : 0
        this.$nextTick(this.update)
      }
    }
  },
  methods: {
	  limitText(val) {
	    val += ''
	    if (!val) return
	    if (!this.isEllipsis) return val
	    return val.length > this.ellipsisNums ? `${val.slice(0, this.ellipsisNums)}...` : val
	  },
    // 切换事件
    change: throttle(function(item,index) {
      const isDisabled = !!this.tabs[index].disabled
      if (this.current !== index && !isDisabled) {
        this.current = index
        // #ifdef VUE3
        this.$emit('update:modelValue', index)
        // #endif
        // #ifdef VUE2
        this.$emit('input', item,index)
        // #endif
        this.$emit('change', item,index)
      }
    }, 300),
    createQueryHandler() {
      let query
      // #ifndef MP-ALIPAY
      query = uni.createSelectorQuery().in(this)
      // #endif
      // #ifdef MP-ALIPAY
      query = uni.createSelectorQuery()
      // #endif

      return query
    },
    update() {
      const _this = this
      startMicroTask(() => {
        // 没有列表的时候,不执行
        if (!this.tabs.length) return
        _this
          .createQueryHandler()
          .select(`#${this.getDomId}`)
          .boundingClientRect(data => {
            const { width, height, left, right } = data || {}
            // 获取容器的相关属性
            this.container = { width, height, left, right: right - width }
            _this.calcScrollWidth()
            _this.setScrollLeft()
            _this.setLine()
          })
          .exec()
      })
    },
    // 计算可以滚动的宽度
    calcScrollWidth(callback) {
      const view = this.createQueryHandler().select(`#${this.getDomId}`)
      view.fields({ scrollOffset: true })
      view
        .scrollOffset(res => {
          if (typeof callback === 'function') {
            callback(res)
          } else {
            // 获取滚动条的宽度
            this.scrollWidth = res.scrollWidth
          }
        })
        .exec()
    },
    // 设置滚动条滚动的进度
    setScrollLeft() {
      this.calcScrollWidth(res => {
        // 动态读取 scrollLeft
        let scrollLeft = res.scrollLeft
        this.createQueryHandler()
          .select(`#${this.getDomId} .v-tabs__container-item.active`)
          .boundingClientRect(data => {
            if (!data) return
            // 除开当前选项外容器的一半宽度
            let curHalfWidth = (this.container.width - data.width) / 2
            let scrollDiff = this.scrollWidth - this.container.width
            // 在原有滚动条的基础上 + (当前元素距离左侧的距离 - 计算的一半宽度) - 容器的外边距之类的
            scrollLeft += data.left - curHalfWidth - this.container.left
            // 已经滚动在左侧了
            if (scrollLeft < 0) scrollLeft = 0
            // 已经超出右侧了
            else if (scrollLeft > scrollDiff) scrollLeft = scrollDiff
            this.scrollLeft = scrollLeft
          })
          .exec()
      })
    },
    setLine() {
      this.calcScrollWidth(res => {
        const scrollLeft = res.scrollLeft
        this.createQueryHandler()
          .select(`#${this.getDomId} .v-tabs__container-item.active`)
          .boundingClientRect(data => {
            if (!data) return
            if (this.pills) {
              this.currentWidth = data.width
              this.pillsLeft = scrollLeft + data.left - this.container.left
            } else {
              this.lineWidth = data.width * this.lineScale
              this.lineLeft = scrollLeft + data.left + (data.width - data.width * this.lineScale) / 2 - this.container.left
            }
          })
          .exec()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.v-tabs__container-item{
	position: relative !important;
	.tip{
		  width: 14px;
		    height: 14px;
		    background: red;
		    position: absolute;
		    top: 0px;
		    right: 0px;
		    text-align: center;
		    line-height: 14px;
			border-radius: 6px;
			color: #fff;
	}
}
.v-tabs {
  width: 100%;
  box-sizing: border-box;
  overflow: hidden;

  /* #ifdef H5 */
  ::-webkit-scrollbar {
    display: none;
  }
  /* #endif */

  &__container {
    min-width: 100%;
    position: relative;
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    overflow: hidden;

    &-item {
      flex-shrink: 0;
      display: flex;
      align-items: center;
      height: 100%;
      position: relative;
      z-index: 10;
      transition: all 0.3s;
      white-space: nowrap;

      &.disabled {
        opacity: 0.5;
        color: #999;
      }
    }

    &-line {
      position: absolute;
      left: 0;
      bottom: 0;
    }

    &-pills {
      position: absolute;
      z-index: 9;
    }

    &-line,
    &-pills {
      &.animation {
        transition: all 0.3s linear;
      }
    }
  }
}

</style>

组件中使用 index.vue

<template>
	<view>
	<!-- <son4></son4>
	 -->
	 <view class="main">
	 	<view class="left">
	 	<v-tabs v-model="current" v-model:tipsindex='tipsindex' ellipsisNums='3'  v-model:tipsnums='tipsnums'  isEllipsis :tabs="tabs" @change="changeTab">
		</v-tabs>
	 	</view>
		<view class="right">
			站位
		</view>
	 </view>
	</view>
</template>

<script setup>
import { ref,provide} from 'vue'
// import son4 from "../../components/son4.vue";
// let toChildValue = ref('传递给所有子集的数据')
// provide( 'toChildValue', toChildValue)

let current  = ref(0)
let tipsindex  = ref(2)
let tipsnums  = ref(2)
let tabs  = ref([])

// 模拟请求数据
setTimeout(()=>{
	tabs.value = ['军事', '国内', '新闻新闻新闻新闻新闻新闻新闻新闻', '军事', '国内', '新闻', '军事', '国内', '新闻']
},1500)
const changeTab =(item,index)=>{
	console.log(item)
	console.log(index)
}
// 模拟修改红点数量
setTimeout(()=>{
	tipsnums.value = 6
},6000)


</script>

<style>
.main{
	width: 100%;
	height: 40px;
	background: pink;
	display: flex;
}
.left{
	flex: 1;
	width: 0;
	height: 40px;
}
.right{
	width: 100px;
	height: 40px;
	background: springgreen;
}
</style>

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

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

相关文章

iOS - 超好用的隐私清单修复脚本(持续更新)

文章目录 前言开发环境项目地址下载安装隐私访问报告隐私清单模板最后 前言 在早些时候&#xff0c;提交应用到App Store审核&#xff0c;大家应该都收到过类似这样的邮件&#xff1a; Although submission for App Store review was successful, you may want to correct th…

c语言-----数组

基本概念 数组是C语言中一种用于存储多个相同类型数据的数据结构。这些数据在内存中是连续存储的&#xff0c;可以通过索引&#xff08;下标&#xff09;来访问数组中的各个元素。数组的索引从0开始&#xff0c;这是C语言的规定。例如&#xff0c;一个有n个元素的数组&#xff…

社区版 IDEA 开发webapp 配置tomcat

1.安装tomcat 参考Tomcat配置_tomcat怎么配置成功-CSDN博客 2.构建webapp项目结构 新建一个普通项目 然后添加webapp的目录结构&#xff1a; main目录下新建 webapp 文件夹 webapp文件夹下新建WEB_INF文件夹 *WEB_INF目录下新建web.xml wenapp文件夹下再新建index.html …

全面解析 Kubernetes 流量负载均衡:iptables 与 IPVS 模式

目录 Kubernetes 中 Service 的流量负载均衡模式 1. iptables 模式 工作原理 数据路径 优点 缺点 适用场景 2. IPVS 模式 工作原理 数据路径 优点 缺点 适用场景 两种模式的对比 如何切换模式 启用 IPVS 模式 验证模式 总结 Kubernetes 中 Service 的流量负载…

C 语言数据类型详解

目录 一、引言 二、基本数据类型 &#xff08;一&#xff09;整型 &#xff08;二&#xff09;浮点型 &#xff08;三&#xff09;字符型 三、构造数据类型 &#xff08;一&#xff09;数组 &#xff08;二&#xff09;结构体 &#xff08;三&#xff09;联合体&#…

Python图注意力神经网络GAT与蛋白质相互作用数据模型构建、可视化及熵直方图分析...

全文链接&#xff1a;https://tecdat.cn/?p38617 本文聚焦于图注意力网络GAT在蛋白质 - 蛋白质相互作用数据集中的应用。首先介绍了研究背景与目的&#xff0c;阐述了相关概念如归纳设置与转导设置的差异。接着详细描述了数据加载与可视化的过程&#xff0c;包括代码实现与分析…

LeetCode 1925 统计平方和三元组的数目

探索平方和三元组&#xff1a;从问题到 Java 代码实现 在数学与编程的交叉领域&#xff0c;常常会遇到一些有趣且富有挑战性的问题。今天&#xff0c;就让我们深入探讨一下 “平方和三元组” 这个有趣的话题&#xff0c;并使用 Java 语言来实现计算满足特定条件的平方和三元组…

回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测

回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiGRU-Attention卷积神经网络结合双向门控循环单元融合注意力机制多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效…

vue横向滚动日期选择器组件

vue横向滚动日期选择器组件 组件使用到了element-plus组件库和dayjs库&#xff0c;使用前先保证项目中已经下载导入 主要功能&#xff1a;选择日期&#xff0c;点击日期可以让此日期滚动到视图中间&#xff0c;左滑右滑同理&#xff0c;支持跳转至任意日期&#xff0c;支持自…

Firecrawl教程①:自动化抓取与数据转化,赋能AI应用

Firecrawl教程①:自动化抓取与数据转化,赋能AI应用 前言一、功能特点1. 支持 LLM 可处理的数据格式2. 全面抓取网站3. 强大的操作支持4. 灵活的定制选项5. 支持多种编程语言 SDK二、如何开始使用 Firecrawl第一步:获取 API 密钥第二步:官网在线工具使用第三步:安装 Firecr…

WatchAlert - 开源多数据源告警引擎

概述 在现代 IT 环境中&#xff0c;监控和告警是确保系统稳定性和可靠性的关键环节。然而&#xff0c;随着业务规模的扩大和数据源的多样化&#xff0c;传统的单一数据源告警系统已经无法满足复杂的需求。为了解决这一问题&#xff0c;我开发了一个开源的多数据源告警引擎——…

svn版本丢失导致无法访问临时解决方法

#svn异常问题# 在使用svn的过程中&#xff0c;有时候在数据量比较大的情况下&#xff0c;有涉及到数据迁移或者是文件移动操作时容易出现迁移过程中有人还提交了数据&#xff0c;导致迁移的数据出现版本丢失的情况。 比如说&#xff0c;我实际遇到的情况是迁移数据的时候记录…

0009.基于springboot+layui的ERP企业进销存管理系统

一、系统说明 基于springbootlayui的ERP企业进销存管理系统,系统功能齐全, 代码简洁易懂&#xff0c;适合小白学编程,课程设计&#xff0c;毕业设计。 二、系统架构 前端&#xff1a;html| layui 后端&#xff1a;springboot | mybatis| thymeleaf 环境&#xff1a;jdk1.8 |…

Latex+VsCode+Win10搭建

最近在写论文&#xff0c;overleaf的免费使用次数受限&#xff0c;因此需要使用本地的形式进行编译。 安装TEXLive 下载地址&#xff1a;https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…

[创业之路-199]:《华为战略管理法-DSTE实战体系》- 3 - 价值转移理论与利润区理论

目录 一、价值转移理论 1.1. 什么是价值&#xff1f; 1.2. 什么价值创造 &#xff08;1&#xff09;、定义 &#xff08;2&#xff09;、影响价值创造的因素 &#xff08;3&#xff09;、价值创造的三个过程 &#xff08;4&#xff09;、价值创造的实践 &#xff08;5&…

如何在单选按钮中添加图标和文字

文章目录 1. 概念介绍2. 使用方法3. 示例代码我们在上一章回中介绍了Radio Widget相关的内容,本章回中将介绍RadioListTile Widget.闲话休提,让我们一起Talk Flutter吧。 1. 概念介绍 我们在这里介绍的RadioListTile和上一章回中介绍的Radio类似,不同之处在于RadioListTile组…

启动异常:Caused by: java.lang.IllegalStateException: Failed to introspect Class

背景 今天项目需要&#xff0c;导入一个本地的jar包&#xff0c;在pom文件&#xff0c;添加自定义依赖后&#xff0c;并通过mvn命令&#xff1a; mvn install:install-file -Dfilejar包的位置 -DgroupId自定义的groupId -DartifactId自定义的artifactId -Dversion自定义的ver…

clickhouse-副本和分片

1、副本 1.1、概述 集群是副本和分片的基础&#xff0c;它将ClickHouse的服务拓扑由单节点延伸到多个节点&#xff0c;但它并不像Hadoop生态的某些系统那样&#xff0c;要求所有节点组成一个单一的大集群。ClickHouse的集群配置非常灵活&#xff0c;用户既可以将所有节点组成…

Python机器学习算法KNN、MLP、NB、LR助力油气钻井大数据提速参数优选及模型构建研究...

全文链接&#xff1a;https://tecdat.cn/?p38601 分析师&#xff1a;Huayan Mu 随着机器学习和大数据分析技术的发展&#xff0c;帮助客户进行油气行业数字化转型势在必行&#xff0c;钻井提速参数优选呈现由经验驱动、逻辑驱动向数据驱动转变的趋势。机械钻速最大化、机械比能…

【尚硅谷 - SSM+SpringBoot+SpringSecurity框架整合项目 】项目打包并且本地部署

前后端分离开发&#xff1a;把一个项目拆成两部分进行开发&#xff0c;所以在打包的时候&#xff0c;需要使用不同的打包方式。 后端 – SpringBoot – jar包 前端 – Vue: 因为使用了vue-admin-template框架&#xff1a;所以先使用框架进行打包使用Nginx部署&#xff0c;通…