Vue3评分(Rate)

news2024/11/25 1:05:30

可自定义设置以下属性:

  • 是否允许再次点击后清除(allowClear),类型:boolean,默认 true

  • 是否允许半选(allowHalf),类型:boolean,默认 false

  • star 总数,类型:number,默认 5

  • 自定义字符,预置 'star' 'heart' 两种svg图标(character),类型:string | slot ,默认 ''

  • 字符时是字体高度,图标时是图片大小(size),类型:number,单位px,默认 20

  • 字符间距(gap),类型:number,单位px,默认 8

  • 只读,无法进行交互(disabled),类型:boolean,默认 false

  • 前数,受控值 1,2,3...(v-model:value),类型:number,默认 0

效果如下图:

①创建评分组件Rate.vue:

<script setup lang="ts">
import { ref, watch } from 'vue'
interface Props {
  allowClear?: boolean // 是否允许再次点击后清除
  allowHalf?: boolean // 是否允许半选
  count?: number // star 总数
  character?: string // 自定义字符,string | slot 预置 'star' 'heart' 两种svg图标
  size?: number // 字符时是字体高度,图标时是图片大小
  gap?: number // 字符间距
  disabled?: boolean // 只读,无法进行交互
  value?: number // v-model 当前数,受控值 1,2,3...
}
const props = withDefaults(defineProps<Props>(), {
  allowClear: true,
  allowHalf: false,
  count: 5,
  character: '',
  size: 20,
  gap: 8,
  disabled: false,
  value: 0
})
const activeValue = ref(props.value)
const tempValue = ref() // 清除时保存点击value
watch(
  () => props.value,
  (to) => {
    activeValue.value = to
  }
)
const emits = defineEmits(['update:value', 'change', 'hoverChange'])
function onClick (value: number) {
  tempValue.value = null
  if (value !== props.value) {
    emits('change', value) // 选择时的回调
    emits('update:value', value)
  } else {
    if (props.allowClear) {
      tempValue.value = value
      emits('change', 0)
      emits('update:value', 0)
    } else { // 不允许清除
      emits('change', value) // 选择时的回调
    }
  }
}
function onFirstEnter (value: number) {
  activeValue.value = value
  emits('hoverChange', value) // 鼠标经过时数值变化的回调
}
function onSecondEnter (value: number) {
  activeValue.value = value
  emits('hoverChange', value)
}
function resetTempValue () { // 重置点击value
  tempValue.value = null
}
function onLeave () {
  activeValue.value = props.value
}
function preventDefault (e: Event) {
  e.preventDefault()
}
</script>
<template>
  <div class="m-rate" :class="{'disabled': disabled}" @mouseleave="onLeave">
    <div
      class="m-star"
      :style="`margin-right: ${n !== count ? gap:0}px;`"
      :class="{'u-star-half': allowHalf && activeValue >= n - 0.5 && activeValue < n, 'u-star-full': activeValue >= n, 'temp-gray': !allowHalf && tempValue === n}"
      @click="!allowHalf ? onClick(n):preventDefault($event)"
      v-for="n in count" :key="n">
      <div
        v-if="allowHalf"
        class="u-star-first"
        :class="{'temp-gray-first': tempValue === n - 0.5}"
        @click.stop="onClick(n - 0.5)"
        @mouseenter="onFirstEnter(n - 0.5)"
        @mouseleave="resetTempValue">
        <svg v-if="character === 'star'" class="u-star" :style="`width: ${size}px;`" focusable="false" data-icon="star" aria-hidden="true" viewBox="64 64 896 896"><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3z"></path></svg>
        <svg v-else-if="character === 'heart'" class="u-star" :style="`width: ${size}px;`" focusable="false" data-icon="heart" aria-hidden="true" viewBox="64 64 896 896"><path d="M923 283.6a260.04 260.04 0 00-56.9-82.8 264.4 264.4 0 00-84-55.5A265.34 265.34 0 00679.7 125c-49.3 0-97.4 13.5-139.2 39-10 6.1-19.5 12.8-28.5 20.1-9-7.3-18.5-14-28.5-20.1-41.8-25.5-89.9-39-139.2-39-35.5 0-69.9 6.8-102.4 20.3-31.4 13-59.7 31.7-84 55.5a258.44 258.44 0 00-56.9 82.8c-13.9 32.3-21 66.6-21 101.9 0 33.3 6.8 68 20.3 103.3 11.3 29.5 27.5 60.1 48.2 91 32.8 48.9 77.9 99.9 133.9 151.6 92.8 85.7 184.7 144.9 188.6 147.3l23.7 15.2c10.5 6.7 24 6.7 34.5 0l23.7-15.2c3.9-2.5 95.7-61.6 188.6-147.3 56-51.7 101.1-102.7 133.9-151.6 20.7-30.9 37-61.5 48.2-91 13.5-35.3 20.3-70 20.3-103.3.1-35.3-7-69.6-20.9-101.9zM512 814.8S156 586.7 156 385.5C156 283.6 240.3 201 344.3 201c73.1 0 136.5 40.8 167.7 100.4C543.2 241.8 606.6 201 679.7 201c104 0 188.3 82.6 188.3 184.5 0 201.2-356 429.3-356 429.3z"></path></svg>
        <span v-else class="u-star" :style="`font-size: ${0.66*size}px; height: ${size}px;`">
          <slot name="character">{{ character }}</slot>
        </span>
      </div>
      <div
        class="u-star-second"
        :class="{'temp-gray-second': tempValue === n}"
        @click.stop="onClick(n)"
        @mouseenter="onSecondEnter(n)"
        @mouseleave="resetTempValue">
        <svg v-if="character === 'star'" class="u-star" :style="`width: ${size}px;`" focusable="false" data-icon="star" aria-hidden="true" viewBox="64 64 896 896"><path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3z"></path></svg>
        <svg v-else-if="character === 'heart'" class="u-star" :style="`width: ${size}px;`" focusable="false" data-icon="heart" aria-hidden="true" viewBox="64 64 896 896"><path d="M923 283.6a260.04 260.04 0 00-56.9-82.8 264.4 264.4 0 00-84-55.5A265.34 265.34 0 00679.7 125c-49.3 0-97.4 13.5-139.2 39-10 6.1-19.5 12.8-28.5 20.1-9-7.3-18.5-14-28.5-20.1-41.8-25.5-89.9-39-139.2-39-35.5 0-69.9 6.8-102.4 20.3-31.4 13-59.7 31.7-84 55.5a258.44 258.44 0 00-56.9 82.8c-13.9 32.3-21 66.6-21 101.9 0 33.3 6.8 68 20.3 103.3 11.3 29.5 27.5 60.1 48.2 91 32.8 48.9 77.9 99.9 133.9 151.6 92.8 85.7 184.7 144.9 188.6 147.3l23.7 15.2c10.5 6.7 24 6.7 34.5 0l23.7-15.2c3.9-2.5 95.7-61.6 188.6-147.3 56-51.7 101.1-102.7 133.9-151.6 20.7-30.9 37-61.5 48.2-91 13.5-35.3 20.3-70 20.3-103.3.1-35.3-7-69.6-20.9-101.9zM512 814.8S156 586.7 156 385.5C156 283.6 240.3 201 344.3 201c73.1 0 136.5 40.8 167.7 100.4C543.2 241.8 606.6 201 679.7 201c104 0 188.3 82.6 188.3 184.5 0 201.2-356 429.3-356 429.3z"></path></svg>
        <span v-else class="u-star" :style="`font-size: ${0.66*size}px; height: ${size}px;`">
          <slot name="character">{{ character }}</slot>
        </span>
      </div>
    </div>
  </div>
</template>
<style lang="less" scoped>
.m-rate {
  display: inline-block;
  .m-star {
    position: relative;
    display: inline-block;
    cursor: pointer;
    transition: all 0.3s;
    &:hover {
      transform: scale(1.1);
    }
    .u-star {
      display: inline-flex;
      align-items: center;
      text-align: center;
      vertical-align: middle;
      fill: rgba(0, 0, 0, 0.06);
      color: rgba(0, 0, 0, 0.06);
      transition: all 0.3s;
    }
    .u-star-first {
      position: absolute;
      top: 0;
      width: 50%;
      height: 100%;
      opacity: 0;
      overflow: hidden;
      transition: all 0.3s;
      &:hover {
        opacity: 1;
        .u-star {
          fill: #fadb14;
          color: #fadb14;
        }
      }
    }
    .u-star-second {
      display: inline-block;
      &:hover {
        .u-star {
          fill: #fadb14;
          color: #fadb14;
        }
      }
    }
    .temp-gray-first {
      &:hover {
        opacity: 0;
        .u-star {
          fill: rgba(0, 0, 0, 0.06);
          color: rgba(0, 0, 0, 0.06);
        }
      }
    }
    .temp-gray-second {
      &:hover {
        .u-star {
          fill: rgba(0, 0, 0, 0.06);
          color: rgba(0, 0, 0, 0.06);
        }
      }
    }
  }
  .u-star-half {
    .u-star-first {
      opacity: 1;
      .u-star {
        fill: #fadb14;
        color: #fadb14;
      }
    }
  }
  .u-star-full {
    .u-star-second {
      .u-star {
        fill: #fadb14;
        color: #fadb14;
      }
    }
  }
}
.disabled {
  pointer-events: none;
}
</style>

 ②在要使用的页面引入:

<script setup lang="ts">
import { Rate } from './Rate.vue'
import { ref, watch } from 'vue'

const value = ref(2.99)
const desc = ref(['terrible', 'bad', 'normal', 'good', 'wonderful'])
watch(value, (to) => {
  console.log('p to:', to)
})
function onChange (value: number) {
  console.log('change value:', value)
}
function onHoverChange (value: number) {
  console.log('hover value:', value)
}
</script>
<template>
  <div>
    <h2 class="mb10">Rate 评分基本使用 (character: star)</h2>
    <Rate
      :count="5"
      character="star"
      :disabled="false"
      v-model:value="value"
      @change="onChange"
      @hoverChange="onHoverChange"/>
    <h2 class="mt30 mb10">使用预置的心型字符图标,并设置高度为30px (character: heart & size: 30)</h2>
    <Rate
      :allowClear="true"
      :allowHalf="true"
      :count="5"
      character="heart"
      :size="30"
      :disabled="false"
      v-model:value="value"
      @change="onChange"
      @hoverChange="onHoverChange"/>
    <h2 class="mt30 mb10">使用中文: 好 (character: 好 & size: 30)</h2>
    <Rate
      :allowClear="false"
      :allowHalf="true"
      :count="5"
      character="好"
      :size="30"
      v-model:value="value"
      @change="onChange"
      @hoverChange="onHoverChange"/>
    <h2 class="mt30 mb10">使用英文字母: A (character: A & size: 50)</h2>
    <Rate
      :allowClear="false"
      :allowHalf="true"
      :count="5"
      character="A"
      :size="50"
      v-model:value="value"
      @change="onChange"
      @hoverChange="onHoverChange"/>
  </div>
</template>
<style lang="less" scoped>
</style>

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

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

相关文章

Java每日一练(20230417)

目录 1. N 皇后 &#x1f31f;&#x1f31f;&#x1f31f; 2. 搜索二维矩阵 &#x1f31f;&#x1f31f; 3. 发奖金问题 &#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 …

神经网络之反向传播算法(自适应矩估计算法Adam变形形式之Adamax、Nadam)

文章目录自适应矩估计算法&#xff08;Adam&#xff09;的两种变形形式1、Adamax算法原理2、Nadam算法原理3、算法实现3.1 Adamax训练过程3.2 Adamax测试过程及结果3.3 Nadam训练过程3.4 Nadam测试过程及结果4、参考源码及数据集自适应矩估计算法&#xff08;Adam&#xff09;的…

打造安全无忧软件应用的十大最佳实践

安全无忧的软件开发最佳实践实在是很有必要&#xff0c;因为安全风险无处不在。在网络攻击盛行的时代&#xff0c;它们可能影响到每个人&#xff0c;包括个人、公司和政府。因此&#xff0c;确保软件开发的安全性至关重要。 本篇文章将解释了什么是安全的软件&#xff0c;如何…

你了解C语言中的柔性数组吗?

本篇博客主要讲解C99中的新语法&#xff1a;柔性数组。 1.什么是柔性数组&#xff1f; 柔性数组就是大小可以变化的数组。 注意跟C99中的变长数组区分开来&#xff0c;变长数组指的是可以使用变量来指定大小&#xff0c;并且不能初始化的数组&#xff0c;比如&#xff1a; i…

实例方法、类方法、静态方法、实例属性、类属性

背景&#xff1a;今天在复习类相关知识的时候&#xff0c;突然想到这几种类型的方法的区别和用法&#xff0c;感觉有点模棱两可&#xff0c;于是总结一下&#xff0c;加深记忆。 定义&#xff1a;想要区别和理解几种方法&#xff0c;首先要定义一个类&#xff0c;要在类中加深…

mysql如何修改时区

mysql 里CST时区的坑 一、 问题简述 mysql里CST时区是个非常坑的概念&#xff0c;因为在mysql里CST既表示中国也表示美国的时区。但是在JDK代码里&#xff0c;CST这个字符串被理解为CenTral Standard Time&#xff08;USA&#xff09;&#xff08;GMT-6&#xff09;&#xff…

java框架都有哪些

Java框架是对Java2中的一些基本概念进行抽象&#xff0c;封装成能被开发者使用的类库&#xff0c;使之能快速开发应用程序。它让开发者能够专注于业务逻辑而不是实现细节。可以说&#xff0c; Java框架是 Java开发中的重要组成部分&#xff0c;它极大地方便了开发者。下面为大家…

腾讯云GPU服务器NVIDIA P40 GPU、P4、T4和GPU自由卡详解

腾讯云GPU云服务器&#xff0c;GPU云服务器实例可选GN8机型、GN6S机型、GN7机型等规格&#xff0c;搭载 NVIDIA P40 GPU&#xff0c;最长可3年&#xff0c;云服务器吧来详细说下腾讯云GPU云服务器&#xff1a; 目录 腾讯云GPU云服务器 腾讯云GPU自由卡 腾讯云GPU云服务器 腾…

选品趋势分析 | 2023开斋节将至,穆斯林时尚在TIKTOK上增长势头正劲!

2023年Q1 穆斯林时尚的销售额环比2022年Q4 暴涨153%&#xff0c;领跑TikTok电商大盘&#xff0c;成为2023年Q1的超级黑马品类。加之开斋节临近&#xff0c;人民陆续开始为庆祝开斋节作采购准备&#xff0c;购物需求相应激增&#xff0c;其中&#xff0c;穆斯林群体会在开斋节的…

GELU激活函数

GELU是一种常见的激活函数&#xff0c;全称为“Gaussian Error Linear Unit”, 作为2020年提出的优秀激活函数&#xff0c;越来越多的引起了人们的注意。 GELU (Gaussian Error Linear Units) 是一种基于高斯误差函数的激活函数&#xff0c;相较于 ReLU 等激活函数&#xff0c…

java版工程项目管理系统-功能清单 图文解析

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显示…

MySQL事务的四大特性及事务的隔离级别

什么是事务&#xff1f;Transaction 常言道&#xff1a;能不麻烦就不麻烦&#xff0c;能简单化就简单化。但是为什么需要事务呢&#xff1f; 事务&#xff1a;用来保证一个业务的完整性&#xff0c;最大的优势就是回滚&#xff0c;并撤销正在进行的所有未提交的修改&#xff1…

linux运行串口相关的java.jar报错:java.lang.UnsatisfiedLinkError

目录 linux运行串口相关的java.jar报错如下&#xff1a; java.lang.UnsatisfiedLinkError是Java中的一个错误类型&#xff0c;通常发生在调用本地&#xff08;native&#xff09;方法或使用JNI&#xff08;Java Native Interface&#xff09;时。 在Java中&#xff0c;本地方…

微分中值定理—柯西中值定理

微分中值定理—柯西中值定理前面我们已经学习了罗尔中值定理,和拉格朗日中值定理&#xff0c;它们的相同点是&#xff0c;研究的曲线都能用函数来表示。那假如曲线不能被函数表示呢&#xff0c;用柯西中值定理。 1 定义 柯西中值定理是拉格朗日中值定理的推广。如果&#xff0c…

助力企业节能降耗:综合能效管理之场景控制

企业综合能效管理系统是为企业提供能耗管理、电能质量和用能安全监测的整套解决方案&#xff0c;系统可采集多种类型能源&#xff08;电、水、天然气、工业气体、冷热量等&#xff09;数据&#xff0c;并对能源消耗进行分析&#xff0c;包括分类分项能耗、区域能耗、部门能耗数…

海思编码:1、mpp系统详谈以及VI、VPSS、VENC之间的关系

在HiMPP手册中都会有这么一张图 1、VI部分 视频输入设备 视频输入设备支持标准 BT.656、标准 BT.1120、自定义时序等若干种时序输入&#xff0c;负责对时序进行解析。 视频物理通道 视频物理通道负责将输入设备解析后得到的视频数据输出到 DDR。在真正将数据输出到 DDR 之前…

FTP-----局域网内部远程桌面

此文包含详细的图文教程。有疑问评论区留言。博主第一时间解决。 目录 一、被远程桌面的电脑 1.开启远程权限 2.添加账户&#xff0c;有本地账户跳过这步 3.帐号隶属于 远程桌面 4.帐号隶属于 本地用户组 二、本地电脑连接远程桌面 前提条件&#xff1a; 1.两台电脑在…

接口自动化【二】(图形验证码处理)

文章目录 前言一、图形验证码图片获取(需要实际截图做对比补充)二、调第三方接口获取验证码三、后端登录接口&#xff08;举例&#xff09;总结前言 讲解了图片验证的处理&#xff1b;在接口测试中遇见的一些问题&#xff1b;多部分编码的注意点 一、图形验证码图片获取(需要实…

【4.13(补)】二叉搜索树的遍历、插入、删除

文章目录二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点二叉搜索树的最近公共祖先 235. 二叉搜索树的最近公共祖先 - 力扣&#xff08;LeetCode&#xff09; 因为二叉搜索树是有序的&#xff0c;第一次找到p和q中间的值&#xff0c;就是最近的公共祖先…

【FPGA-DSP】第六期:Black Box调用流程

目录 1. 实际操作流程 1.1 Verilog 代码编写 1.2 system generator操作 1.2.1 Black box模块 1.2.2 Simulink 搭建 2. Simulink模型优化 System Generator是一个Xilinx公司的工具&#xff0c;用于设计数字信号处理系统。Black Box是System Generator中的一个block&#…