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

【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】封装数字框组件

数量选择组件-基本结构 &#xff08;1&#xff09;准备基本结构 <script lang"ts" setup name"Numbox"> // </script> <template><div class"numbox"><div class"label">数量</div><div cla…...

C++-简述strcpy、sprintf 和 memcpy 的区别

回答如下&#xff1a; strcpy 函数&#xff1a;用于将一个字符串&#xff08;以 NULL 结尾&#xff09;从源地址复制到目标地址。函数原型为 char* strcpy(char* destination, const char* source)。需要注意的是&#xff0c;该函数会复制整个字符串&#xff0c;包括 NULL 终止…...

用CPU大法忽悠ChatGPT写前端,油猴子工具库+1

文章目录用CPU大法忽悠ChatGPT写前端&#xff0c;油猴子工具库1源起对话1. 作为一名天才js程序员&#xff0c;开发一个油猴子脚本&#xff0c;实现所有浏览器网页的自动下滑功能&#xff0c;每一个步骤都加上中文注释2. 加一个按钮&#xff0c;只有我点击了按钮才会开始自动下滑…...

初识虚拟DOM渲染器

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

工作日志day03

同时构建静态和动态库 //如果用这种方式&#xff0c;只会构建一个动态库&#xff0c;虽然静态库的后缀是.a ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC}) //修改静态库的名字&#xff0c;这样是可以的&#xff0c;但是我们往往希望他…...

【数据挖掘与商务智能分析】第三章 线性回归模型

一元线性回归 一元线性回归的代码实现 1. 绘制散点图 import matplotlib.pyplot as plt X = [[1], [2], [4], [5]] Y...

iOS开发之UIStackView基本运用

UIStackView UIStackView是基于自动布局AutoLayout&#xff0c;创建可以动态适应设备方向、屏幕尺寸和可用空间的任何变化的用户界面。UIStackView管理其ArrangedSubview属性中所有视图的布局。这些视图根据它们在数组中的顺序沿堆栈视图的轴排列。由axis, distribution, align…...

【java】为什么 main 方法是 public static void ?

main 方法是我们学习Java编程语言时知道的第一个方法&#xff0c;你是否曾经想过为什么 main 方法是 public、static、void 的。当然&#xff0c;很多人首先学的是C和C&#xff0c;但是在Java中main方法与前者有些细微的不同&#xff0c;它不会返回任何值&#xff0c;为什么 ma…...

最简单的线性回归模型-标量

首先考虑yyy为标量&#xff0c;www为标量的情况&#xff0c;那么我们的线性函数为ywxbywxbywxb。每批输入的量batch size 为111&#xff0c;每批输入的xxx为一个标量&#xff0c;设为x∗x^*x∗&#xff0c;标签yyy同样为一个标量&#xff0c;设为y∗y^*y∗。因此每批训练的损失…...

k8s-Kubernetes集群升级

文章目录前言一、集群升级1.部署cri-docker &#xff08;所有集群节点&#xff09;2.升级master节点3.升级worker节点前言 一、集群升级 https://v1-24.docs.kubernetes.io/zh-cn/docs/tasks/administer-cluster/kubeadm/kubeadm-upgrade/ 1.部署cri-docker &#xff08;所有…...

Linux25 -- 监听队列链接上限测试、命令uname、ulimit

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

idea:地址被占用

问题启动idea报&#xff1a;java.net.BindException: Address already in use: bind&#xff0c;具体截图如下&#xff1a;解决步骤1、首先想到的是改idea端口&#xff0c;但按网上方法试下了几个4位数和5位数的端口&#xff0c;没啥作用2、根据idea抛异常的弹出框提示&#xf…...

JavaScript常用小技巧(js优化)

JavaScript常用小技巧&#xff08;js优化&#xff09;常见JS操作1、解构交换两数2、短路赋值3、if 判断优化4、 switch 判断优化6、动态正则匹配Number1、幂运算2、安全计算String1、反转字符串、判断是否回文数2、数组求和3、初始化二维数组Object1、对象遍历2、冻结对象3、解…...

【项目实战】MySQL 5.7中的关键字与保留字详解

一、什么是关键字和保留字 关键字是指在SQL中有意义的字。 某些关键字&#xff08;例如SELECT&#xff0c;DELETE或BIGINT&#xff09;是保留的&#xff0c;需要特殊处理才能用作表和列名称等标识符。 这一点对于内置函数的名称也适用。 二、如何使用关键字和保留字 非保留关…...

Git图解-常用命令操作

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

LeetCode096不同的二叉搜索树(相关话题:卡特兰数)

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

软件测试7

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

12 结构:如何系统设计框架的整体目录?

到现在&#xff0c;我们已经将 Gin 集成到框架 hade 中&#xff0c;同时又引入了服务容器和服务提供者&#xff0c;明确框架的核心思想是面向服务编程&#xff0c;一切皆服务&#xff0c;所有服务都是基于协议。后续也会以服务的形式&#xff0c;封装一个个的服务&#xff0c;让…...

假如你知道这样的MySQL性能优化

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

79、ClimateNeRF: Physically-based Neural Rendering for Extreme Climate Synthesis

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

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

聊一聊接口测试的意义有哪些?

目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开&#xff0c;首…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

代理篇12|深入理解 Vite中的Proxy接口代理配置

在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

Mysql中select查询语句的执行过程

目录 1、介绍 1.1、组件介绍 1.2、Sql执行顺序 2、执行流程 2.1. 连接与认证 2.2. 查询缓存 2.3. 语法解析&#xff08;Parser&#xff09; 2.4、执行sql 1. 预处理&#xff08;Preprocessor&#xff09; 2. 查询优化器&#xff08;Optimizer&#xff09; 3. 执行器…...

计算机基础知识解析:从应用到架构的全面拆解

目录 前言 1、 计算机的应用领域&#xff1a;无处不在的数字助手 2、 计算机的进化史&#xff1a;从算盘到量子计算 3、计算机的分类&#xff1a;不止 “台式机和笔记本” 4、计算机的组件&#xff1a;硬件与软件的协同 4.1 硬件&#xff1a;五大核心部件 4.2 软件&#…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...