【Vue3】封装数字框组件
数量选择组件-基本结构
(1)准备基本结构
<script lang="ts" setup name="Numbox">
//
</script>
<template><div class="numbox"><div class="label">数量</div><div class="numbox"><a href="javascript:;">-</a><input type="text" readonly value="1" /><a href="javascript:;">+</a></div></div>
</template><style scoped lang="less">
.numbox {display: flex;align-items: center;.label {width: 60px;color: #999;padding-left: 10px;}.numbox {width: 120px;height: 30px;border: 1px solid #e4e4e4;display: flex;> a {width: 29px;line-height: 28px;text-align: center;background: #f8f8f8;font-size: 16px;color: #666;&:first-of-type {border-right: 1px solid #e4e4e4;}&:last-of-type {border-left: 1px solid #e4e4e4;}}> input {width: 60px;padding: 0 5px;text-align: center;color: #666;}}
}
</style>
(2)全局注册
import Numbox from '@/components/numbox/index.vue'
export default {install(app: App) {app.component('Numbox', Numbox)},
}
(3)提供类型声明
import Numbox from '@/components/numbox/index.vue'
declare module 'vue' {export interface GlobalComponents {Numbox: typeof Numbox}
}export {}
(4)渲染
<div class="spec"><!-- 数字选择框 --><XtxNumbox></XtxNumbox>
</div>
效果
数量选择组件-v-model语法糖
目标:掌握vue3.0的v-model语法糖原理
在vue2.0中v-mode语法糖简写的代码 <Son :value="msg" @input="msg=$event" />
在vue3.0中v-model语法糖有所调整:<Son :modelValue="msg" @update:modelValue="msg=$event" />
演示代码:
<script lang="ts" setup>
defineProps({money: {type: Number,default: 0,},
})const emit = defineEmits(['update:money'])
</script><template><h3>子组件-{{ money }}</h3><button @click="emit('update:money', money + 1)">+1</button>
</template><style scoped lang="less"></style>
总结: vue3.0封装组件支持v-model的时候,父传子:modelValue
子传父 @update:modelValue
补充: vue2.0的 xxx.sync
语法糖解析 父传子 :xxx
子传父 @update:xxx
在vue3.0 使用 v-model:xxx
代替。
数量选择组件-功能实现
大致功能分析:
- 默认值为1
- 可限制最大最小值
- 点击-就是减1 点击+就是加1
- 需要完成v-model得实现
- 存在无label情况
<script lang="ts" setup name="Numbox">
const props = defineProps({modelValue: {type: Number,default: 1,},min: {type: Number,default: 1,},max: {type: Number,default: 20,},showLabel: {type: Boolean,default: false,},
})const emit = defineEmits<{(e: 'update:modelValue', value: number): void
}>()const add = () => {if (props.modelValue >= props.max) returnemit('update:modelValue', props.modelValue + 1)
}const sub = () => {if (props.modelValue <= props.min) returnemit('update:modelValue', props.modelValue - 1)
}
</script>
<template><div class="numbox"><div class="label" v-if="showLabel"><slot>数量</slot></div><div class="numbox"><a href="javascript:;" @click="sub">-</a><input type="text" readonly :value="modelValue"/><a href="javascript:;" @click="add">+</a></div></div>
</template><style scoped lang="less">
.numbox {display: flex;align-items: center;.label {width: 60px;color: #999;padding-left: 10px;}.numbox {width: 120px;height: 30px;border: 1px solid #e4e4e4;display: flex;> a {width: 29px;line-height: 28px;text-align: center;background: #f8f8f8;font-size: 16px;color: #666;&:first-of-type {border-right: 1px solid #e4e4e4;}&:last-of-type {border-left: 1px solid #e4e4e4;}}> input {width: 60px;padding: 0 5px;text-align: center;color: #666;}}
}
</style>
动态控制禁用效果
<script lang="ts" setup name="Numbox">
const props = defineProps({modelValue: {type: Number,default: 1,},min: {type: Number,default: 1,},max: {type: Number,default: 20,},showLabel: {type: Boolean,default: false,},
})const emit = defineEmits<{(e: 'update:modelValue', value: number): void
}>()const add = () => {if (props.modelValue >= props.max) returnemit('update:modelValue', props.modelValue + 1)
}const sub = () => {if (props.modelValue <= props.min) returnemit('update:modelValue', props.modelValue - 1)
}
</script>
<template><div class="numbox"><div class="label" v-if="showLabel"><slot>数量</slot></div><div class="numbox">+ <a href="javascript:;" @click="sub" :class="{not:props.modelValue <= props.main}">-</a><input type="text" readonly :value="modelValue" />+ <a href="javascript:;" @click="add" :class="{not:props.modelValue >= props.max}">+</a></div></div>
</template><style scoped lang="less">
.numbox {display: flex;align-items: center;.label {width: 60px;color: #999;padding-left: 10px;}.numbox {width: 120px;height: 30px;border: 1px solid #e4e4e4;display: flex;> a {width: 29px;line-height: 28px;text-align: center;background: #f8f8f8;font-size: 16px;color: #666;+ &.not {+ cursor: not-allowed;+ }&:first-of-type {border-right: 1px solid #e4e4e4;}&:last-of-type {border-left: 1px solid #e4e4e4;}}> input {width: 60px;padding: 0 5px;text-align: center;color: #666;}}
}
</style>
使用组件:src/views/goods/index.vue
<script lang="ts" setup name="Numbox">
import {ref} from "vue";const count = ref(1)
</script><!-- 商品信息 -->
<div class="goods-info"><!-- 数字选择框 --><XtxNumbox v-model="count" min:"1" :max="20" ></XtxNumbox>
</div>
思考:
我们的输入框不仅能点击加减还可以输入数字,如果用户通过输入框输入非数字会出现什么问题?
优化代码
<script lang="ts" setup name="Numbox">
const props = defineProps({modelValue: {type: Number,default: 1,},min: {type: Number,default: 1,},max: {type: Number,default: 20,},showLabel: {type: Boolean,default: false,},
})
+const { proxy } = getCurrentInstance() as ComponentInternalInstance
const emit = defineEmits<{(e: 'update:modelValue', value: number): void
}>()const add = () => {if (props.modelValue >= props.max) returnemit('update:modelValue', props.modelValue + 1)
}const sub = () => {if (props.modelValue <= props.min) returnemit('update:modelValue', props.modelValue - 1)
}+const handleChange = (e: Event) => {
+ // 通过类型断言,让ts知道目前元素的类型
+ const element = e.target as HTMLInputElement
+ let value = +element.value
+ if (isNaN(value)) value = 1
+ if (value >= props.max) value = props.max
+ if (value <= props.main) value = props.main
+ emit('update:modelValue',value)+ // 强制刷新
+ proxy?.$forceUpdate()
}
</script>
<template><div class="numbox"><div class="label" v-if="showLabel"><slot>数量</slot></div><div class="numbox"><a href="javascript:;" @click="sub" :class="{not:props.modelValue <= props.main}">-</a><input type="text" readonly :value="modelValue" @change="handleChange($event)"/><a href="javascript:;" @click="add" :class="{not:props.modelValue >= props.max}">+</a></div></div>
</template><style scoped lang="less">
.numbox {display: flex;align-items: center;.label {width: 60px;color: #999;padding-left: 10px;}.numbox {width: 120px;height: 30px;border: 1px solid #e4e4e4;display: flex;> a {width: 29px;line-height: 28px;text-align: center;background: #f8f8f8;font-size: 16px;color: #666;&.not {cursor: not-allowed;}&:first-of-type {border-right: 1px solid #e4e4e4;}&:last-of-type {border-left: 1px solid #e4e4e4;}}> input {width: 60px;padding: 0 5px;text-align: center;color: #666;}}
}
</style>
相关文章:

【Vue3】封装数字框组件
数量选择组件-基本结构 (1)准备基本结构 <script lang"ts" setup name"Numbox"> // </script> <template><div class"numbox"><div class"label">数量</div><div cla…...
C++-简述strcpy、sprintf 和 memcpy 的区别
回答如下: strcpy 函数:用于将一个字符串(以 NULL 结尾)从源地址复制到目标地址。函数原型为 char* strcpy(char* destination, const char* source)。需要注意的是,该函数会复制整个字符串,包括 NULL 终止…...
用CPU大法忽悠ChatGPT写前端,油猴子工具库+1
文章目录用CPU大法忽悠ChatGPT写前端,油猴子工具库1源起对话1. 作为一名天才js程序员,开发一个油猴子脚本,实现所有浏览器网页的自动下滑功能,每一个步骤都加上中文注释2. 加一个按钮,只有我点击了按钮才会开始自动下滑…...

初识虚拟DOM渲染器
初识虚拟DOM渲染器什么是虚拟DOM什么是渲染器渲染器的实现组件是什么什么是虚拟DOM 首先简单说一下什么是虚拟DOM,虚拟DOM就是一个描述真实DOM的JS对象 例如: 真实的DOM元素 <div onClick"alert(click me)">click me</div>可以…...

工作日志day03
同时构建静态和动态库 //如果用这种方式,只会构建一个动态库,虽然静态库的后缀是.a ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC}) //修改静态库的名字,这样是可以的,但是我们往往希望他…...
【数据挖掘与商务智能分析】第三章 线性回归模型
一元线性回归 一元线性回归的代码实现 1. 绘制散点图 import matplotlib.pyplot as plt X = [[1], [2], [4], [5]] Y...

iOS开发之UIStackView基本运用
UIStackView UIStackView是基于自动布局AutoLayout,创建可以动态适应设备方向、屏幕尺寸和可用空间的任何变化的用户界面。UIStackView管理其ArrangedSubview属性中所有视图的布局。这些视图根据它们在数组中的顺序沿堆栈视图的轴排列。由axis, distribution, align…...
【java】为什么 main 方法是 public static void ?
main 方法是我们学习Java编程语言时知道的第一个方法,你是否曾经想过为什么 main 方法是 public、static、void 的。当然,很多人首先学的是C和C,但是在Java中main方法与前者有些细微的不同,它不会返回任何值,为什么 ma…...

最简单的线性回归模型-标量
首先考虑yyy为标量,www为标量的情况,那么我们的线性函数为ywxbywxbywxb。每批输入的量batch size 为111,每批输入的xxx为一个标量,设为x∗x^*x∗,标签yyy同样为一个标量,设为y∗y^*y∗。因此每批训练的损失…...
k8s-Kubernetes集群升级
文章目录前言一、集群升级1.部署cri-docker (所有集群节点)2.升级master节点3.升级worker节点前言 一、集群升级 https://v1-24.docs.kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/ 1.部署cri-docker (所有…...

Linux25 -- 监听队列链接上限测试、命令uname、ulimit
一、监听队列链接上限测试 1、res listen(sockfd,5); //创建监听队列res listen(sockfd,5);不懂版本有不同的限制,2.6早期版本有限制为128,超过默认为128,可使用uname -a 查看版本 2、测试将链接数到达上限, 方法࿱…...

idea:地址被占用
问题启动idea报:java.net.BindException: Address already in use: bind,具体截图如下:解决步骤1、首先想到的是改idea端口,但按网上方法试下了几个4位数和5位数的端口,没啥作用2、根据idea抛异常的弹出框提示…...
JavaScript常用小技巧(js优化)
JavaScript常用小技巧(js优化)常见JS操作1、解构交换两数2、短路赋值3、if 判断优化4、 switch 判断优化6、动态正则匹配Number1、幂运算2、安全计算String1、反转字符串、判断是否回文数2、数组求和3、初始化二维数组Object1、对象遍历2、冻结对象3、解…...
【项目实战】MySQL 5.7中的关键字与保留字详解
一、什么是关键字和保留字 关键字是指在SQL中有意义的字。 某些关键字(例如SELECT,DELETE或BIGINT)是保留的,需要特殊处理才能用作表和列名称等标识符。 这一点对于内置函数的名称也适用。 二、如何使用关键字和保留字 非保留关…...

Git图解-常用命令操作
目录 一、前言 二、初始化仓库 三、添加文件 四、Git 流程全景图 五、Git工作流程 六、工作区和暂存区 七、查看文件状态 八、查看提交日志 九、查看差异 十、版本回退 十一、管理修改 十二、修改撤销 十三、删除文件 十四、分支管理 十五、项目分支操作 十六、…...

LeetCode096不同的二叉搜索树(相关话题:卡特兰数)
目录 题目描述 解题思路 代码实现 进出栈序列理解卡特兰数分析策略 相关知识 参考文章 题目描述 给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。 示例 1: …...

软件测试7
一 CS和BS软件架构 CS:客户端-服务器端,BS:浏览器端-服务器端 区别总结: 1.效率:c/s效率高,某些内容已经安装在系统中了,b/s每次都要加载最新的数据 2.升级:b/s无缝升级,…...

12 结构:如何系统设计框架的整体目录?
到现在,我们已经将 Gin 集成到框架 hade 中,同时又引入了服务容器和服务提供者,明确框架的核心思想是面向服务编程,一切皆服务,所有服务都是基于协议。后续也会以服务的形式,封装一个个的服务,让…...

假如你知道这样的MySQL性能优化
1. 为查询缓存优化你的查询 大多数的 MySQL 服务器都开启了查询缓存。这是提高性最有效的方法之 一,而且这是被 MySQL 的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中,这样,后续的相同…...

79、ClimateNeRF: Physically-based Neural Rendering for Extreme Climate Synthesis
简介主页物理模拟可以很好地预测天气影响。神经辐射场产生SOTA场景模型。ClimateNeRF 允许我们渲染真实的天气效果,包括雾霾、雪和洪水 ,结果可以通过有物理意义的变量来控制,比如水位 ,这允许人们可视化气候变化的结果将对他们产…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...

三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
WEB3全栈开发——面试专业技能点P4数据库
一、mysql2 原生驱动及其连接机制 概念介绍 mysql2 是 Node.js 环境中广泛使用的 MySQL 客户端库,基于 mysql 库改进而来,具有更好的性能、Promise 支持、流式查询、二进制数据处理能力等。 主要特点: 支持 Promise / async-await…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...