在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
一、概述
记录时间 [2024-12-26]
本文讲述如何在 Vue3 项目中使用计时器组件。具体包括开发环境的配置,Vite+Vue 项目的创建,Element Plus 插件的使用,以及计时器组件的创建和使用。
想要直接实现计时器组件,查看文章的第四部分。
文末附有项目的测试代码,可以直接上手哦。
1. 计时器效果图
计时停止状态

计时启动状态

开发工具及文档
- Node.js - 下载地址;Node.js 安装和配置 - 参考文章
- VS Code - 下载地址;写前端代码的软件,直接安装即可。或者通过压缩包解压缩安装。
- Vue3 - 文档
- Vite - 文档
- Element Plus - 文档
二、创建 + 配置项目
Vite 是一种新型前端构建工具,意在提供开箱即用的配置,能够显著提升前端开发体验。
1. 创建
在 cmd 中,通过 Vite,构建一个 Vite + Vue 项目。
自行指定项目存放位置。
# check npm, 检查 npm 版本
npm -v# 7.0 以上版本使用该语句
npm create vite@latest my-vue-app# choose vue + js
# 选择创建 Vue 项目,使用 JavaScript 语言# 执行以下命令即可运行该模板项目
cd my-vue-app # 跳转到项目路径
npm install # 安装依赖
npm run dev # 执行运行
2. 项目预览
通过浏览器,访问对应的 http 路径,就可以查看这个模板项目。
# 通过浏览器访问
Local: http://localhost:5173/# Ctrl + C 终止项目

3. 修改项目模板
使用 VS Code 打开项目 my-vue-app,观察左边四个文件。
- 删除
HelloWorld.vue,style.css; - 再把
App.vue,main.js里面没用的代码注释掉。

就剩下一个基本框架,方便我们后续写内容。

修改 v3 创建模板(可选)
文件路径:C:\Users\user\.vscode\extensions\sdras.vue-vscode-snippets\snippets\vue.json
修改 vbase-3-setup 模板,后续创建 vue 组件时会用到。
"Vue Single File Component Setup Composition API": {"prefix": "vbase-3-setup","body": ["<script setup>","","</script>","","<template>","","</template>","","<style scoped>","","</style>"],"description": "Base for Vue File Setup Composition API"},
修改后,vbase-3-setup 模板效果如下,输入 v3 即可使用。
重启 VS Code 生效。
<script setup></script><template></template><style scoped></style>
4. 安装前端组件
安装组件
Element Plus 是基于 Vue 3,面向设计师和开发者的组件库。里面有一些基础的前端组件样式,如布局、按钮、输入框等,可用于简化开发。
通过 npm 安装 Element Plus:
可以用 cmd,也可以通过 VS Code 中的终端 Terminal 来执行项目。后续 Terminal 用的比较多。
# Ctrl + C 终止项目# 安装 Element Plus
npm install element-plus --save
会安装在项目的 node_modules 目录下。
导入组件
然后在 main.js 中导入组件。
import { createApp } from 'vue'import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'import App from './App.vue'const app = createApp(App)app.use(ElementPlus)
app.mount('#app')
三、整体布局
1. 测试
经过上面的修改,运行项目后,我们在浏览器中看到的是一个空白的页面。
npm install # 安装依赖
npm run dev # 执行运行
在 App.vue 中写点内容测试一下:
<script setup>
</script><template><h3>test</h3>
</template><style scoped></style>
保存修改后的文件,然后刷新浏览器的页面。就可以观察到更新后的内容。
2. 栅格布局
使用 Element Plus,通过基础的 24 分栏,迅速简便地创建布局。
挑选一个左中右 3 分的布局。
在 App.vue 中实现这个效果。
HTML 显示
此时布局中,“左中右” 分布为 8:8:8(24),也就是均分,我们可以手动调整为 6:12:6(24),这样中间的空间多一些。
<template><el-row><!-- left --><el-col :span="8"><div class="grid-content ep-bg-purple" /><h1>left</h1></el-col><!-- center --><el-col :span="8"><div class="grid-content ep-bg-purple-light" /><h1>center</h1><h1>计时器组件</h1></el-col><!-- right --><el-col :span="8"><div class="grid-content ep-bg-purple" /><h1>right</h1></el-col></el-row>
</template>
CSS 样式
<style scoped>
h1 {text-align: center;
}.el-row {margin-bottom: 20px;
}.el-row:last-child {margin-bottom: 0;
}.el-col {border-radius: 4px;
}.grid-content {border-radius: 4px;min-height: 36px;
}
</style>
3. 效果预览
在浏览器中呈现的效果如下图所示。

四、计时器组件
1. 创建 + 导入组件
Vue 组件的创建位置一般在项目的 my-vue-app\src\components 目录下。
在该目录下,创建计时器组件 Timer.vue
<script setup></script><template><h3>计时器组件 Timer.vue 导入到 App.vue 中</h3>
</template><style scoped></style>
将计时器组件导入到 App.vue 中
- 在
<script>标签里导入; - 在
<template>中应用。
<script setup>
import Timer from './components/Timer.vue'
</script><template><!-- template 里面有其他代码的,Timer 放到对应位置即可 --><!-- 放到 center 布局里 --><Timer />
</template>
2. 计时器的布局
先在网页上绘制计时器的静态布局,就是先画出一个样子来。
- 内 / 外边框,按钮,使用 Element Plus 组件;
- “时分秒” 显示 2 位数,“毫秒” 显示 3 位数;
- 各种文字调整成合适大小。
效果预览

代码编写
外边框
外边框在 App.vue 中实现,在 <style> 中编写一个 css 样式,使用 Element Plus 组件。
.box {width: 90%;border: 2px solid var(--el-border-color);border-radius: 0;padding: 30px;
}
在 <template> 中使用:
<div class="box"><Timer1 />
</div>
其他布局在 Timer.vue 中编写代码。
内边框 + 边框内的文字 + 三个按钮
- 使用 Element Plus 边框组件,在一行中循环显示 4 个小边框。
- 边框内的文字分两部分:显示时间;时间单位。
- 使用 Element Plus 按钮组件,设置 “开始”,“暂停”,“重置” 3 个按钮。
<template><h1>计时器</h1><!-- display: inline; 让 div 在同一行 --><!-- 循环显示 4 个小边框 --><div v-for="i in 4" style="display: inline;"><div class="radius" :style="{borderRadius: 'small'? `var(--el-border-radius-small)`: '',}"><div class="show-size">00<span style="font-size: 20px;">小时</span><!-- 通过总耗时获取对应的时分秒 --><!-- {{ formatTime(elapsedTime, time[i - 1]) }} --><!-- 通过数组获取对应的时间单位 --><!-- <span style="font-size: 20px;">{{ timeShow[i - 1] }}</span> --></div></div></div><!-- 框 和 button 使用 element-plus --><div style="margin-top: 120px;"><el-button type="primary">开始</el-button><el-button type="info">暂停</el-button><el-button>重置</el-button></div>
</template><style scoped>
.show-size {font-size: 2em;margin: 10px 0;text-align: center;
}.radius {height: 60px;width: 20%;border: 1px solid var(--el-border-color);border-radius: 0;float: left;
}
</style>
3. 计时器的初步逻辑
接下来在 Timer.vue 中实现计时器的初步逻辑:
- 使用定时器函数累计耗时,确定时间概念(时分秒)。
- 能通过网页与计时器组件进行交互。
- 点击启动,计时器开始工作;点击暂停,计时器暂停工作;点击重置,计时器重置。
定时器函数
setInterval() 是 JavaScript 中的一个定时器函数,用于按照指定的时间间隔(以毫秒为单位)重复执行一段代码或函数。它会持续调用指定的函数,直到 clearInterval() 被调用或者页面被卸载。
setInterval() 会返回一个 intervalID,是正整数形式的标识符,可用于清除定时器。
参考用法(观察一下)
// intervalID: id
let intervalID = null;// 通过 id 启动定时器
// func: 每次定时器到期时要调用的函数或要执行的代码
// delay: 两次调用之间的时间间隔, 以毫秒为单位, 1s = 1000ms
intervalID = setInterval({func}, delay);// 通过 id 清除定时器
clearInterval(intervalId);
定时器:规定一段时间,每隔一段时间完成一个动作,比如执行一段代码;
计时器:统计累计消耗的时间。
定义变量
在 Timer.vue 中实现这个逻辑:
elapsedTime:累计耗时(以毫秒为单位);intervalId:定时器的ID;setInterval():启动定时器;clearInterval():清除定时器。isRunning:判断计时器是否启动的标志。(计时器和定时器同启同停)
当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。
在 <script> 标签中导入 ref,定义变量。
<script setup>
import { ref } from 'vue';// 计时器的启动状态 false 暂停计时;ture 正在计时
const isRunning = ref(false);// 计时器的耗时(以毫秒为单位)
const elapsedTime = ref(0);// 定时器的 id,用于调用定时器的函数,如 setInterval,clearInterval
let intervalId = null;// 循环获取数组的内容, 配合小边框使用, 用来渲染页面内容
const time = ['hours', 'minutes', 'seconds', 'millis'
];const timeShow = ['小时', '分钟', '秒', '毫秒'
];
</script>
启动计时器
编写方法 startTimer(),用于启动计时器。
- 判断计时器的启动状态,如果已经在计时,直接返回;
- 更新计时器的启动状态为
ture; - 通过
id启动定时器,累加耗时,从而相当于启动了计时器,每隔 5ms 在elapsedTime中更新累计耗时。
// 启动计时器
const startTimer = () => {// 如果已经在计时,直接返回if (isRunning.value) return;// 更新计时器的状态为 ture 正在计时isRunning.value = true;// 通过 id 启动定时器,累加耗时,从而相当于启动了计时器,1s = 1000ms,每 5ms 累加 5msintervalId = setInterval(() => {elapsedTime.value += 5;}, 5);
}
暂停计时器
编写方法 pauseTimer(),用于暂停计时器。
- 更新计时器的启动状态为
false; - 通过
id清除定时器,暂停耗时的累加,从而相当于暂停了计时器。
// 暂停计时器
const pauseTimer = () => {// 更新计时器的状态为 false 暂停计时isRunning.value = false;// 通过 id 清除定时器,暂停耗时的累加,从而相当于暂停了计时器clearInterval(intervalId);
}
重置计时器
编写方法 resetTimer(),用于重置计时器。
- 更新计时器的启动状态为
false; - 通过
id清除定时器,停止耗时的累加; - 将总耗时
elapsedTime的值清空。 - 停止耗时的累加,且清空总耗时,相当于重置了计时器。
// 重置计时器
const resetTimer = () => {// 更新计时器的状态为 falseisRunning.value = false;// 通过 id 清除定时器,暂停耗时的累加clearInterval(intervalId);// 将已耗时设置为 0elapsedTime.value = 0;// 重置起始时间// for (let i = 0; i < 4; i++) {// startTime.value[i] = 0;// }
}
耗时换算
我们通过 elapsedTime 累加耗时,它是以毫秒为单位的,我们要实现 “时,分,秒,毫秒” 分区显示。
需要通过简单的数学计算,来完成耗时换算。
1 s = 1000 m s 1 m i n = 60 s = ( 60 × 1000 ) m s 1 h = 60 m i n = ( 60 × 60 ) s = ( 60 × 60 × 1000 ) m s 1 s = 1000 ms \\ 1 min = 60 s = (60×1000) ms \\ 1 h = 60 min = (60×60) s = (60×60×1000) ms 1s=1000ms1min=60s=(60×1000)ms1h=60min=(60×60)s=(60×60×1000)ms
倒过来计算,通过毫秒换算成 “时,分,秒,毫秒” 显示。
注意:程序中整数做除法,会直接省略小数点后面的数值(3739220/1000 = 3739)
e g : t o t a l T i m e = 3739220 m s s h o w : m i l l i s = t o t a l T i m e % 1000 = 3739220 % 1000 = 220 m s s h o w : s e c o n d s = ( t o t a l T i m e / 1000 ) % 60 = 19 s s h o w : m i n u t e s = ( t o t a l T i m e / ( 1000 ∗ 60 ) ) % 60 = 2 m i n s h o w : h o u r s = ( t o t a l T i m e / ( 1000 ∗ 60 ∗ 60 ) ) % 24 = 1 h e n d S h o w : 1 h : 2 m i n : 19 s : 220 m s eg: totalTime = 3739220 ms \\ show: millis = totalTime \% 1000 = 3739220 \% 1000 = 220ms \\ show: seconds = (totalTime / 1000) \% 60 = 19s \\ show: minutes = (totalTime / (1000 * 60)) \% 60 = 2min \\ show: hours = (totalTime / (1000 * 60 * 60)) \% 24 = 1h \\ endShow:1h:2min:19s:220ms eg:totalTime=3739220msshow:millis=totalTime%1000=3739220%1000=220msshow:seconds=(totalTime/1000)%60=19sshow:minutes=(totalTime/(1000∗60))%60=2minshow:hours=(totalTime/(1000∗60∗60))%24=1hendShow:1h:2min:19s:220ms
在代码中编写耗时换算函数 formatTime:
// 时分秒分区显示
const formatTime = (milliseconds, timeString) => {const millis = Math.floor(milliseconds % 1000);const seconds = Math.floor((milliseconds / 1000) % 60);const minutes = Math.floor((milliseconds / (1000 * 60)) % 60);const hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24);// 配合数组 time 使用,确定获取的是 millis/seconds/minutes/hours 其中一部分// String(obj).padStart(3, '0') 格式化数据的显示,毫秒 3 位,其他 2 位if (timeString == 'millis') {return `${String(millis).padStart(3, '0')}`;} else if (timeString == 'seconds') {return `${String(seconds).padStart(2, '0')}`;} else if (timeString == 'minutes') {return `${String(minutes).padStart(2, '0')}`;} else if (timeString == 'hours') {return `${String(hours).padStart(2, '0')}`;}}
4. 更新页面渲染
动态显示
在 Timer.vue 的 <template> 标签中,使用插值表达式 {{}} 来完成页面内容的动态显示。
- 通过总耗时获取对应的 “时分秒”
<!-- i 用于循环遍历 -->
{{ formatTime(elapsedTime, time[i - 1]) }}
- 通过数组获取对应的时间单位
<!-- i 用于循环遍历 -->
{{ timeShow[i - 1] }}
- 绑定按钮点击事件和可点击状态
<!-- @click="startTimer", 点击按钮触发 startTimer() 方法 -->
<!-- :disabled="isRunning", 根据 isRunning 的值确定按钮是否被禁用, true 禁用, false 不禁用 --><el-button @click="startTimer" :disabled="isRunning" type="primary">开始</el-button><!-- 另外两个按钮同理 --><el-button @click="pauseTimer" :disabled="!isRunning" type="info">暂停</el-button>
<el-button @click="resetTimer">重置</el-button>
效果预览
点击启动,计时器开始工作;点击暂停,计时器暂停工作;点击重置,计时器重置。

计时器不动时,“暂停” 按钮不可点击;计时器运行时,“开始” 按钮不可点击。
(按钮被禁用时,颜色会变浅一些)

接下来开始优化计时器,增加设置起始时间功能,同时设置运行时特效。
5. 设置起始时间
效果预览
在计时器的下方,可以设置计时器的起始时间。
需要达到的效果:按照 “时分秒” 的格式设置起始时间,点击 “提交” 按钮后,上方计时器显示的起始时间,就是我们提交的时间。

逻辑实现
在 Timer.vue 的 <script> 标签中编写逻辑代码。
startTime:存放 “时分秒” 格式的初始时间的数组,默认为[0, 0, 0, 0];setStartTime():将提交的startTime换算成 “毫秒”,然后赋值给计时器的耗时elapsedTime;- 重置计时器的同时,将
startTime的值重置为[0, 0, 0, 0]。
// 起始时间
const startTime = ref([0, 0, 0, 0]);// 设置起始时间,换算成毫秒,赋值给计时器的耗时
const setStartTime = () => {elapsedTime.value = (((startTime.value[1] * 60) + startTime.value[2]) * 60 + startTime.value[3]) * 1000;
}// 重置计时器
const resetTimer = () => {// other codes...// 重置起始时间for (let i = 0; i < 4; i++) {startTime.value[i] = 0;}
}
样式设计
使用 Element Plus 组件,挑选 3 个下拉选项框,分别对应选择的 “时分秒”。
- 在下拉选项框中,使用
v-model与startTime数组内容双向绑定,这样会将选中的起始时间保存到这个数组中。 - 使用
:disabled绑定isRunning的值,来决定下拉选项框是否被禁用。在计时器启动时,禁用;计时器停止时,不禁用。
再使用一个 “提交” 按钮,点击按钮,就执行 setStartTime() 方法。
- “提交” 按钮的点击事件绑定
setStartTime()方法,将提交的startTime换算成 “毫秒”,然后赋值给计时器的耗时elapsedTime; - 由于使用了
ref,DOM会自动更新,也就是计时器上的时间会更新成所提交的起始时间。 - 使用
:disabled绑定isRunning的值,在计时器启动时,禁用 “提交” 按钮,不允许修改时间。
在 Timer.vue 的 <template> 标签中编写。
<!-- set Start Time --><h3>设置起始时间</h3><div v-for="i in 3" style="display: inline;"><el-select v-model="startTime[i]" :disabled="isRunning" placeholder="Select" class="select-box"><el-option v-for="item in 60" :key="item - 1" :label="`${item - 1} ${timeShow[i - 1]}`" :value="item - 1" /></el-select></div><!-- 计时器启动时不允许修改时间 --><el-button type="success" @click="setStartTime" :disabled="isRunning">提交</el-button>
给下拉选项框设置一个 css 样式,在 Timer.vue 的 <style> 标签中编写。
.select-box {width: 100px;margin-right: 10px;
}
6. 设置运行时特效
在计时器启动时,计时器上显示的时间会发生变化。在此时,我们给计时器设计一个特别的 css 样式。
- 在计时器暂停 / 停止时,计时器上显示的时间不动,颜色是默认的;
- 在计时器启动时,计时器上显示的时间会发生变化,颜色也发生变化,变成海棠红色。
效果预览
计时器启动时的效果。

代码编写
在 Timer.vue 的 <template> 标签中修改代码。该效果是使用 v-if 来实现的。
<!-- set running css v-if --><div class="show-size"><span v-if="isRunning" style="color:#db5a6b;"><!-- 通过总耗时获取对应的时分秒 -->{{ formatTime(elapsedTime, time[i - 1]) }}<!-- 通过数组获取对应的时间单位 --><span style="font-size: 20px;">{{ timeShow[i - 1] }}</span></span><span v-else>{{ formatTime(elapsedTime, time[i - 1]) }}<span style="font-size: 20px;">{{ timeShow[i - 1] }}</span></span></div>
五、运行项目
至此,在 Vue3 项目中使用计时器组件就成功实现了,点击 VS Code 左上角的 Terminal -> New Terminal,转到 powershell 中,执行以下命令,即可运行此项目。
npm install # 安装依赖
npm run dev # 执行运行# 通过浏览器访问
Local: http://localhost:5173/# Ctrl + C 终止项目
六、完整测试代码
1. create
# check npm
npm -v# npm 7+, 创建 Vite+Vue3 项目
npm create vite@latest my-vue-app# choose vue + js
# 选择创建 Vue 项目,使用 JavaScript 语言# 跳转到项目路径
cd my-vue-app# 安装 element-plus
npm install element-plus --savenpm install # 安装依赖
npm run dev # 执行运行# 通过浏览器访问
Local: http://localhost:5173/# Ctrl + C 终止项目
2. main.js
import { createApp } from 'vue'// 引入 element-plus
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'import App from './App.vue'const app = createApp(App)app.use(ElementPlus)
app.mount('#app')
3. App.vue
<script setup>
import Timer from './components/Timer.vue'
</script><template><el-row><!-- left --><el-col :span="6"><div class="grid-content ep-bg-purple" /></el-col><!-- center --><el-col :span="12"><div class="grid-content ep-bg-purple-light" /><div class="box"><Timer /></div></el-col><!-- right --><el-col :span="6"><div class="grid-content ep-bg-purple" /></el-col></el-row>
</template><style scoped>
h1 {text-align: center;
}.box {width: 90%;border: 2px solid var(--el-border-color);border-radius: 0;padding: 30px;
}.el-row {margin-bottom: 20px;
}.el-row:last-child {margin-bottom: 0;
}.el-col {border-radius: 4px;
}.grid-content {border-radius: 4px;min-height: 36px;
}
</style>
4. Timer.vue
<script setup>
import { ref } from 'vue';// 计时器的启动状态 false 暂停计时;ture 正在计时
const isRunning = ref(false);// 计时器的耗时(以毫秒为单位)
const elapsedTime = ref(0);// 定时器的 id,用于调用定时器的函数,如 setInterval,clearInterval
let intervalId = null;// 循环获取数组的内容, 配合小边框使用, 用来渲染页面内容
const time = ['hours', 'minutes', 'seconds', 'millis'
];const timeShow = ['小时', '分钟', '秒', '毫秒'
];// 起始时间
const startTime = ref([0, 0, 0, 0]);// 设置起始时间,换算成毫秒,赋值给计时器的耗时
const setStartTime = () => {elapsedTime.value = (((startTime.value[1] * 60) + startTime.value[2]) * 60 + startTime.value[3]) * 1000;
}// 时分秒分区显示
const formatTime = (milliseconds, timeString) => {const millis = Math.floor(milliseconds % 1000);const seconds = Math.floor((milliseconds / 1000) % 60);const minutes = Math.floor((milliseconds / (1000 * 60)) % 60);const hours = Math.floor((milliseconds / (1000 * 60 * 60)) % 24);// 配合数组 time 使用,确定获取的是 millis/seconds/minutes/hours 其中一部分// String(obj).padStart(3, '0') 格式化数据的显示,毫秒 3 位,其他 2 位if (timeString == 'millis') {return `${String(millis).padStart(3, '0')}`;} else if (timeString == 'seconds') {return `${String(seconds).padStart(2, '0')}`;} else if (timeString == 'minutes') {return `${String(minutes).padStart(2, '0')}`;} else if (timeString == 'hours') {return `${String(hours).padStart(2, '0')}`;}}// 启动计时器
const startTimer = () => {// 如果已经在计时,直接返回if (isRunning.value) return;// 更新计时器的状态为 ture 正在计时isRunning.value = true;// 通过 id 启动定时器,累加耗时,从而相当于启动了计时器,1s = 1000ms,每 5ms 累加 5msintervalId = setInterval(() => {elapsedTime.value += 5;}, 5);
}// 暂停计时器
const pauseTimer = () => {// 更新计时器的状态为 false 暂停计时isRunning.value = false;// 通过 id 清除定时器,暂停耗时的累加,从而相当于暂停了计时器clearInterval(intervalId);
}// 重置计时器
const resetTimer = () => {// 更新计时器的状态为 falseisRunning.value = false;// 通过 id 清除定时器,暂停耗时的累加clearInterval(intervalId);// 将已耗时设置为 0elapsedTime.value = 0;// 重置起始时间for (let i = 0; i < 4; i++) {startTime.value[i] = 0;}
}</script><template><h1>计时器</h1><!-- display: inline; 让 div 在同一行 --><!-- 循环取数 --><div v-for="i in 4" style="display: inline;"><div class="radius" :style="{borderRadius: 'small'? `var(--el-border-radius-small)`: '',}"><!-- set running css v-if --><div class="show-size"><span v-if="isRunning" style="color:#db5a6b;"><!-- 通过总耗时获取对应的时分秒 -->{{ formatTime(elapsedTime, time[i - 1]) }}<!-- 通过数组获取对应的时间单位 --><span style="font-size: 20px;">{{ timeShow[i - 1] }}</span></span><span v-else>{{ formatTime(elapsedTime, time[i - 1]) }}<span style="font-size: 20px;">{{ timeShow[i - 1] }}</span></span></div></div></div><!-- 框 和 button 使用 element-plus --><div style="margin-top: 120px;"><!-- @click 绑定按钮点击事件;:disabled 绑定按钮是否可以点击 --><el-button @click="startTimer" :disabled="isRunning" type="primary">开始</el-button><el-button @click="pauseTimer" :disabled="!isRunning" type="info">暂停</el-button><el-button @click="resetTimer">重置</el-button></div><!-- set Start Time --><h3>设置起始时间</h3><div v-for="i in 3" style="display: inline;"><el-select v-model="startTime[i]" :disabled="isRunning" placeholder="Select" class="select-box"><el-option v-for="item in 60" :key="item - 1" :label="`${item - 1} ${timeShow[i - 1]}`" :value="item - 1" /></el-select></div><!-- 计时器启动时不允许修改时间 --><el-button type="success" @click="setStartTime" :disabled="isRunning">提交</el-button>
</template><style scoped>
.show-size {font-size: 2em;margin: 10px 0;text-align: center;
}.radius {height: 60px;width: 20%;border: 1px solid var(--el-border-color);border-radius: 0;float: left;
}.select-box {width: 100px;margin-right: 10px;
}
</style>
参考资料
Vue3 文档:https://cn.vuejs.org/guide/introduction.html
Vite 文档:https://vitejs.cn/vite3-cn/guide/#scaffolding-your-first-vite-project
Element-plus 文档:https://element-plus.org/zh-CN/component/overview.html
色彩工具:https://tool.lu/index.php/color/palette.html?id=2
VS Code 官网:https://code.visualstudio.com/
Node.js 官网:https://nodejs.org/zh-cn/download/prebuilt-binaries
参考文章 - Node.js 安装和配置:https://blog.csdn.net/Sareur_1879/article/details/144729321
相关文章:
在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)
一、概述 记录时间 [2024-12-26] 本文讲述如何在 Vue3 项目中使用计时器组件。具体包括开发环境的配置,ViteVue 项目的创建,Element Plus 插件的使用,以及计时器组件的创建和使用。 想要直接实现计时器组件,查看文章的第四部分。…...
机器人C++开源库The Robotics Library (RL)使用手册(三)
进入VS工程,我们先看看这些功能函数及其依赖库的分布关系: rl命名空间下,主要有八大模块。 搞定VS后将逐个拆解。 1、编译运行 根据报错提示,配置相应错误的库(根据每个人安装位置不同而不同,我的路径如下:) 编译所有,Release版本耗时大约10分钟。 以rlPlan运动…...
Photoshop启动错误:找不到MSVCP140.dll的多步骤解决指南
在使用Adobe Photoshop(简称PS)进行创意设计或图像编辑时,有时会遇到软件启动报错的情况,其中“找不到MSVCP140.dll,无法继续执行代码”是一个常见的错误提示。这个错误通常意味着你的系统缺少了Microsoft Visual C Re…...
mac中idea菜单工具栏没有git图标了
1.右击菜单工具栏 2.选中VCS,点击添加 3.搜索你要的工具,选中点击确定就添加了 4.回到上面一个界面,选中你要放到工具栏的工具,点击应用就好了 5.修改图标,快捷键或者右击选中编辑图标 6.选择你要的图标就好了...
学习threejs,PerspectiveCamera透视相机和OrthographicCamera正交相机对比
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️THREE.PerspectiveCamera透…...
C#数学相关开发性能优化方法
本文Github地址:CSharp-MathOptimization.md 华为公司的C语言编程规范在开头就强调了: 一般情况下,代码的可阅读性高于性能,只有确定性能是瓶颈时,才应该主动优化。 本文讲述的方法没有经过大项目和大公司的检验&…...
【前沿 热点 顶会】AAAI 2025中与目标检测有关的论文
CP-DETR: Concept Prompt Guide DETR Toward Stronger Universal Object Detection(AAAI 2025) 最近关于通用物体检测的研究旨在将语言引入最先进的闭集检测器,然后通过构建大规模(文本区域)数据集进行训练࿰…...
APP投放的归因框架设计
一、归因相关概念回顾 在广告归因简介中我们介绍常见的归因模型和归因方法,我们先来回顾一下: 1. 背景 2. 设备标识 3. 归因模型 归因模型的多样性意味着每种模型都有其独特的优势和局限。关键在于选择一个与您的业务场景相匹配的模型,并且…...
职业生涯记录-1
机缘 普通人改命,要学会向上社交,能自然融入的圈子,多数是往下社交,没有多少价值,想要获取更多资源,但是有钱人只跟有钱人交朋友,不会带我们普通人玩,又错了,有钱人身边最不缺的就是有钱人,他们缺的是对他们有利用价值的朋友,往上社交的关键,你必须是个对他有利用价…...
江苏捷科云:可视化平台助力制造企业智能化管理
公司简介 江苏捷科云信息科技有限公司(以下简称“捷科”)是一家专注于云平台、云储存、云管理等产品领域的创新型企业,集研发、生产和销售于一体,致力于在网络技术领域打造尖端品牌。在推动制造业企业数字化转型的进程中…...
【ES6复习笔记】Promise对象详解(12)
1. 什么是 Promise? Promise 是 JavaScript 中处理异步操作的一种机制,它可以让异步操作更加容易管理和控制。Promise 对象代表一个异步操作的最终完成或失败,并提供了一种方式来处理操作的结果。 2. Promise 的基本语法 Promise 对象有三…...
01 Oracle 基本操作
Oracle 基本操作 初使用步骤 1.创建表空间 2.创建用户、设置密码、指定表空间 3.给用户授权 4.切换用户登录 5.创建表 注意点:oracle中管理表的基本单位是用户 文章目录 了解Oracle体系结构 1.创建表空间**2.删除表空间**3.创建用户4.给用户授权5.切换用户登录6.表操…...
C语言基础:指针(数组指针与指针数组)
数组指针与指针数组 数组指针 概念:数组指针是指向数组的指针,本质上还是指针 特点: 先有数组,后有指针 它指向的是一个完整的数组 一维数组指针: 语法: 数据类型 (*指针变量名)[行容量][列容量]; 案…...
本地部署 LLaMA-Factory
本地部署 LLaMA-Factory 1. 本地部署 LLaMA-Factory2. 下载模型3. 微调模型3-1. 下载数据集3-2. 配置参数3-3. 启动微调3-4. 模型评估3-5. 模型对话 1. 本地部署 LLaMA-Factory 下载代码, git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Facto…...
Web前端基础知识(三)
表单的应用非常丰富,可以说,每个网站都会用到表单。下面首先介绍表单中的form标签。 --------------------------------------------------------------------------------------------------------------------------------- <form></form&g…...
数据库设计问题记录
唯一性约束和逻辑删除的冲突 问题描述 如果一张表中,存在唯一性约束,比如一些数据中的code,且数据表使用逻辑删除。当删除某行数据的时候,以后再次插入相同code的数据,数据库会报错。 问题分析 在逻辑删除中&#…...
mac_录屏
参考: mac m1上系统内录方法BlackHole代替soundflower录音(附安装包) https://blog.csdn.net/boildoctor/article/details/122765119录屏后没声音?这应该是 Mac(苹果电脑) 内录声音最优雅的解决方案了 https://www.bilibili.com/…...
【Java-tesseract】OCR图片文本识别
文章目录 一、需求二、概述三、部署安装四、技术细节五、总结 一、需求 场景需求:是对识别常见的PNG,JPEG,TIFF,GIF图片识别,环境为离线内网。组件要求开源免费,并且可以集成Java生成接口服务。 二、概述 我不做选型对比了,我筛选测试了下Tesseract(v…...
redis cluster集群
华子目录 什么是redis集群redis cluster的体系架构什么是数据sharding?什么是hash tag集群中删除或新增节点,数据如何迁移?redis集群如何使用gossip通信?定义meet信息ping消息pong消息fail消息(不是用gossip协议实现的࿰…...
解锁高效密码:适当休息,让学习状态满格
一、“肝帝” 的困境 在当今竞争激烈的职场中,“肝帝” 现象屡见不鲜。超长工时仿佛成为了许多行业的 “标配”,从互联网企业的 “996”“007”,到传统制造业的轮班倒、无休无止的加班,员工们的工作时间被不断拉长。清晨ÿ…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
ElasticSearch搜索引擎之倒排索引及其底层算法
文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
视觉slam十四讲实践部分记录——ch2、ch3
ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
掌握 HTTP 请求:理解 cURL GET 语法
cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...
