Code前端首页关于Code前端联系我们

Vue3项目里怎么快速上手Cron表达式组件?选什么库?踩坑怎么办?

terry 38分钟前 阅读数 12 #Vue

现在做后台管理、定时任务调度这些业务,Cron组件几乎是刚需,特别是用Vue3重构或者新开项目的时候,不能再照搬Vue2的老库旧写法了,最近刚好帮朋友的团队做了个工单自动分配的定时功能,踩了不少坑也摸出了顺手的方案,今天就把这些经验全说透。

选Vue3 Cron库前先搞懂两个前提

选库不能只看Star数多,得先想清楚自己的项目需求和环境,不然装完就傻眼。 第一个前提是你的项目用的是Vue3的Composition API还是Options API? 其实现在大部分Vue3库都是优先适配Composition API的,但有些旧的兼容库还是只留了Options的API调用方式,写代码的时候会很别扭,所以尽量选主推Composition API的库。 第二个前提是你的业务对Cron的精度、语言有什么要求? 有些业务只要到分钟级,有些精确到秒级甚至毫秒(不过标准Cron一般是秒可选的6-7位,毫秒要自己加逻辑);语言的话,国内项目大部分要中文,有些国际化项目得支持中英切换,要不要预设常用的Cron表达式?要不要支持可视化拖拽?要不要生成Cron的时候实时显示执行时间预览?这些都是选型的关键。

目前好用的Vue3 Cron可视化组件有哪些?

翻了一圈现在的开源库和商业组件,给大家筛选出三个最实用的:

vue3-cron-editor(适合轻量级国内项目)

这个库是国内开发者维护的,主打一个轻量、中文友好、上手快,Star数在GitHub上也有1k+,还算稳定,它默认支持到秒级的6位Cron,可视化界面分了“秒、分、时、日、月、周”几个标签页,每个标签页都有很直观的复选框、下拉框,不用懂Cron语法也能选,它还内置了“每日执行”“每周一三五执行”“每月最后一天执行”这种常用的预设模板,新手用起来毫无压力,它支持Composition API的v-model绑定,和Vue3的生态契合度很高,没有额外的依赖,安装完就能用。 不过它也有小缺点,就是UI是默认的Element Plus风格吗?不对,它是纯原生CSS的,稍微有点朴素,如果你的项目有自己的设计规范,需要自己覆盖样式;还有就是它不支持周几的数字范围(比如周一到周五的2-4是周几?哦对,不同的Cron解析器周几的起始不一样,这个后面会说坑),只能选固定的某一天或某几天,这点对有些复杂的定时任务可能不太够用。

@element-plus/cron(适合用Element Plus的中大型项目)

如果你项目里已经用了Element Plus作为UI组件库,那直接选这个官方社区维护的组件准没错,它完全贴合Element Plus的设计规范,不用额外改样式,UI也很精致,它支持秒级的6位Cron,可视化标签页的逻辑更清晰,比如周标签页里不仅可以选固定的某一天,还可以选“第N个周X”“最后一个周X”这种复杂的规则;预设模板也更丰富,除了常用的,还有“每月第N个工作日执行”这种结合了逻辑判断的(不过工作日要自己定义节假日吗?好像没有内置,得自己处理),它也支持Composition API的v-model绑定,还有on-change事件可以监听Cron的变化,方便做实时预览。 小缺点就是它依赖Element Plus,如果你项目里没装这个库,单独装的话会增加项目的体积;还有就是国际化只支持中文和英文,其他语言得自己加翻译文件。

vxe-cron(适合有复杂定时需求的项目)

这个库是vxe-table团队维护的,功能非常强大,适合做那种企业级的定时任务调度系统,它支持到毫秒级的7位Cron(不过毫秒解析的话得自己选对应的解析库,后面会说),可视化界面除了基础的标签页,还有“高级模式”可以直接输入自定义的Cron表达式;周几的起始可以自己设置(比如周一或周日),也可以设置周几的数字范围;预设模板支持自定义,还可以保存常用的模板到本地存储;实时预览的执行时间可以显示未来10次、20次甚至更多次,还可以设置预览的起始时间,它不仅支持Vue3的Composition API,还支持Options API,也可以作为独立的组件嵌入到其他框架里,不过UI是vxe风格的,需要自己适配。 功能多意味着体积也大,如果你的项目只是简单的定时任务,用这个有点杀鸡用牛刀。

从零开始搭建vue3-cron-editor的示例,5分钟就能跑通

刚才说了vue3-cron-editor最适合轻量级国内项目,那就拿它来做个示例,给大家演示一下怎么快速上手。 你得有一个Vue3的项目,如果没有的话,可以用Vite快速创建一个:

npm create vite@latest my-vue3-cron-demo -- --template vue
cd my-vue3-cron-demo
npm install

安装vue3-cron-editor:

npm install vue3-cron-editor --save

打开src/App.vue文件,把里面的内容替换成下面的代码:

<template>
  <div class="app-container">
    <h2>Vue3 Cron 快速上手示例</h2>
    <div class="cron-wrapper">
      <!-- 绑定v-model,双向绑定Cron表达式 -->
      <vue3-cron-editor v-model="cronExpression" />
    </div>
    <div class="result-wrapper">
      <h3>当前Cron表达式:</h3>
      <p>{{ cronExpression }}</p>
      <!-- 这里可以自己加执行时间预览的逻辑 -->
      <h3>未来5次执行时间:</h3>
      <ul>
        <li v-for="(time, index) in nextExecutions" :key="index">{{ time }}</li>
      </ul>
    </div>
  </div>
</template>
<script setup>
import { ref, watch } from 'vue';
// 引入vue3-cron-editor组件和它的样式
import Vue3CronEditor from 'vue3-cron-editor';
import 'vue3-cron-editor/lib/vue3-cron-editor.css';
// 引入cron-parser库来解析Cron表达式,生成执行时间预览
import parser from 'cron-parser';
// 初始化Cron表达式,默认是每分钟执行一次
const cronExpression = ref('0 * * * * ?');
// 初始化未来5次执行时间
const nextExecutions = ref([]);
// 监听Cron表达式的变化,更新执行时间预览
watch(cronExpression, (newVal) => {
  try {
    // 解析Cron表达式,注意周几的起始设置为1(周一),因为国内项目一般都是这么用的
    const interval = parser.parseExpression(newVal, {
      currentDate: new Date(),
      endDate: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000), // 只解析未来30天的
      tz: 'Asia/Shanghai', // 设置时区为上海
      weekdayStart: 1 // 周几的起始为周一
    });
    // 清空之前的执行时间
    nextExecutions.value = [];
    // 获取未来5次执行时间
    for (let i = 0; i < 5; i++) {
      nextExecutions.value.push(interval.next().toString());
    }
  } catch (err) {
    // 如果Cron表达式解析失败,清空执行时间并显示错误信息
    nextExecutions.value = ['Cron表达式无效,请检查!'];
    console.error(err);
  }
}, { immediate: true }); // immediate: true 表示组件初始化的时候就执行一次
</script>
<style scoped>
.app-container {
  max-width: 1200px;
  margin: 50px auto;
  padding: 0 20px;
}
.cron-wrapper {
  margin: 20px 0;
}
.result-wrapper {
  background-color: #f5f7fa;
  padding: 20px;
  border-radius: 8px;
}
</style>

安装cron-parser库来解析Cron表达式,生成执行时间预览:

npm install cron-parser --save

然后运行项目:

npm run dev

打开浏览器访问http://localhost:5173,你就能看到一个完整的Vue3 Cron组件示例了!可视化界面选好参数,上面的Cron表达式会自动更新,下面的未来5次执行时间也会实时变化,非常好用。

用Vue3 Cron组件最容易踩的5个坑,我帮你踩过了

刚才的示例看起来很简单,但实际开发中还是会遇到不少坑,今天就把我踩过的5个最常见的坑说出来,帮大家避避:

周几的起始不一致导致解析错误

这个坑是最常见的!不同的Cron解析器(比如Linux的crontab、Spring Task、Quartz、cron-parser)周几的起始不一样,有些是0=周日,有些是1=周日,有些是1=周一,有些是7=周日,比如刚才的示例里,vue3-cron-editor默认的周几起始是1=周一,cron-parser默认的是0=周日,所以如果不设置cron-parser的weekdayStart: 1,生成的执行时间就会错一天。 解决方法:不管用什么库,都要统一周几的起始!最好在项目里定义一个全局的配置,所有用到Cron的地方都用同一个配置,建议大家用Quartz的标准,也就是6位或7位Cron,周几的起始是1=周日,7=周六?不对不对,刚才的示例里我设置的是1=周一,因为国内项目一般都是这么用的,这个得根据你的后端解析器来定,一定要和后端开发沟通好!

秒级和毫秒级Cron的兼容性问题

标准的Linux crontab是5位Cron(分、时、日、月、周),Spring Task默认是6位(秒、分、时、日、月、周),Quartz是7位(秒、分、时、日、月、周、年),有些库还支持毫秒级的8位(毫秒、秒、分、时、日、月、周、年),如果你的前端生成的是7位Cron,而后端只支持6位,就会解析错误。 解决方法:和后端开发沟通好,确定项目用的Cron位数和精度,然后在前端组件里设置对应的位数,比如刚才的vue3-cron-editor默认是6位(秒、分、时、日、月、周),如果后端不需要秒,可以在组件里加个no-second属性隐藏秒标签页。

每月最后一天的Cron表达式写法

每月最后一天的Cron表达式写法很容易错,比如有些新手会写0 0 0 31 ?,但不是每个月都有31天;还有些会写0 0 0 L ?,但这个L的用法有些解析器不支持。 解决方法:尽量用可视化组件里的“每月最后一天”预设模板,不要自己手写;如果必须手写,要确保后端的解析器支持L(Last)、W(Weekday)、#(第N个周X)这些特殊字符,刚才的vue3-cron-editor和@element-plus/cron、vxe-cron都支持这些特殊字符,大家可以放心用。

时区问题导致执行时间不对

如果你的项目是部署在海外服务器上,或者用户分布在不同的时区,时区问题就会很严重,比如前端在上海生成的是每天早上8点执行的Cron表达式,服务器部署在美国纽约,执行时间就会变成纽约时间早上8点,也就是上海时间晚上8点。 解决方法:尽量统一时区,比如前端和后端都用UTC时间,或者都用上海时间;如果必须支持不同的时区,可以在前端组件里加个时区选择器,然后把时区和Cron表达式一起传给后端,刚才的示例里我用了cron-parser的tz属性设置了上海时间,大家可以参考一下。

自定义样式覆盖无效

刚才说了,vue3-cron-editor是纯原生CSS的,UI稍微有点朴素,如果你项目里有自己的设计规范,需要自己覆盖样式,但有时候会发现覆盖无效。 解决方法:因为Vue3的scoped样式是通过data-v-xxx属性实现的,而vue3-cron-editor的组件是全局的,没有data-v-xxx属性,所以直接在scoped样式里覆盖是无效的,解决方法有两个:一个是去掉style标签的scoped属性(但这样会污染全局样式,不推荐);另一个是用:deep()深度选择器(Vue3.2+支持::v-deep(),deep()也兼容),比如想把vue3-cron-editor的标签页背景色改成蓝色,可以这样写:

<style scoped>
.cron-wrapper :deep(.el-tabs__item) { /* 哦不对,vue3-cron-editor的标签页是原生的div,不是Element Plus的,刚才看错了,它的标签页类名是cron-tab-item */
.cron-wrapper :deep(.cron-tab-item) {
  background-color: #409eff;
  color: #fff;
}
</style>

除了可视化组件,还有没有其他方法生成Vue3 Cron表达式?

当然有!如果你的业务不需要可视化界面,只需要简单的预设模板,或者需要自己手写Cron表达式,可以用以下两种方法:

用预设模板数组

可以在项目里定义一个预设模板数组,每个模板包含模板名称和对应的Cron表达式,然后用下拉框或者单选框让用户选择。

const cronPresets = [
  { label: '每分钟执行一次', value: '0 * * * * ?' },
  { label: '每小时执行一次', value: '0 0 * * * ?' },
  { label: '每天早上8点执行', value: '0 0 8 * * ?' },
  { label: '每周一三五早上8点执行', value: '0 0 8 ? * 1,3,5' },
  { label: '每月最后一天早上8点执行', value: '0 0 8 L * ?' }
];

用Cron表达式生成工具函数

可以在项目里封装一些Cron表达式生成工具函数,比如生成“每天指定时间执行”“每周指定周几指定时间执行”“每月指定日期指定时间执行”的函数,比如生成每天指定时间执行的函数:

/**
 * 生成每天指定时间执行的Cron表达式
 * @param {number} hour - 小时(0-23)
 * @param {number} minute - 分钟(0-59)
 * @param {number} second - 秒(0-59),可选,默认0
 * @returns {string} - Cron表达式
 */
const generateDailyCron = (hour, minute, second = 0) => {
  return `${second} ${minute} ${hour} * * ?`;
};

好啦,今天的分享就到这里!希望这篇文章能帮到正在做Vue3 Cron定时任务的你,如果还有其他问题,欢迎在评论区留言讨论!

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

热门