基于vue3的Crontab组件
网上找的没有满意的,决定从
若依前后端分离
其前端vue2中的crontab进行转换,先上效果
若依:
改后:
v2转v3没什么难度,其中有大量的将 this.*** 替换为 ***.value,笔者写了个正则替换,希望可以帮助大家
this.(\w+) $1.value
需要注意的有,在v2中【this.$refs[refName].cycle01 = indexArr[0]】这样写
在v3中要转换一下,在子组件中用【defineExpose】抛出一个setData方法,然后【proxy.$refs[refName].setData("cycle01", Number(indexArr[0]))】赋值
贴出核心Crontab.vue的代码,其子组件就不一一贴了,需要的可以自己下若依代码进行转换
<template> <div class="crontab"> <el-tabs type="border-card"> <el-tab-pane label="秒"> <CrontabSecond
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronsecond" /> </el-tab-pane> <el-tab-pane label="分钟"> <CrontabMin
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronmin" /> </el-tab-pane> <el-tab-pane label="小时"> <CrontabHour
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronhour" /> </el-tab-pane> <el-tab-pane label="日"> <CrontabDay
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronday" /> </el-tab-pane> <el-tab-pane label="月"> <CrontabMonth
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronmonth" /> </el-tab-pane> <el-tab-pane label="周"> <CrontabWeek
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronweek" /> </el-tab-pane> <el-tab-pane label="年"> <CrontabYear
@update="updateCrontabValue"v-model:check="checkNumber"v-model:cron="crontabValueObj"ref="cronyear" /> </el-tab-pane> </el-tabs> <div class="crontab-main"> <div class="crontab-main-table"> <table> <thead> <th v-for="item of tabTitles" width="40" :key="item">{{item}}</th> <!-- <th>Cron 表达式</th> --> </thead> <tbody> <td> <span>{{crontabValueObj.second}}</span> </td> <td> <span>{{crontabValueObj.min}}</span> </td> <td> <span>{{crontabValueObj.hour}}</span> </td> <td> <span>{{crontabValueObj.day}}</span> </td> <td> <span>{{crontabValueObj.month}}</span> </td> <td> <span>{{crontabValueObj.week}}</span> </td> <td> <span>{{crontabValueObj.year}}</span> </td> <!-- <td> <span>{{crontabValueString}}</span> </td> --> </tbody> </table> <table> <thead> <th>Cron 表达式</th> </thead> <tbody> <td> <span>{{crontabValueString}}</span> </td> </tbody> </table> </div> <div class="crontab-main-result"> <CrontabResult v-model:ex="crontabValueString"></CrontabResult> </div> </div> </div> </template> <script setup name="Crontab">import CrontabSecond from"./crontab/CrontabSecond.vue";
import CrontabMin from"./crontab/CrontabMin.vue";
import CrontabHour from"./crontab/CrontabHour.vue";
import CrontabDay from"./crontab/CrontabDay.vue";
import CrontabMonth from"./crontab/CrontabMonth.vue";
import CrontabWeek from"./crontab/CrontabWeek.vue";
import CrontabYear from"./crontab/CrontabYear.vue";
import CrontabResult from"./crontab/CrontabResult.vue";
const { proxy }=getCurrentInstance();
const emits= defineEmits(["hide", "fill"]);
const props=defineProps({
expression: {type: String,default: ""}
})
const tabTitles= ref(["秒", "分钟", "小时", "日", "月", "周", "年"])
const tabActive= ref(0)
const crontabValueObj=ref({
second:"*",
min:"*",
hour:"*",
day:"*",
month:"*",
week:"?",
year:"",
})
const crontabValueString= computed(() =>{
let obj=crontabValueObj.value;
let str=obj.second+ " " +obj.min+ " " +obj.hour+ " " +obj.day+ " " +obj.month+ " " +obj.week+(obj.year== "" ? "" : " " +obj.year);returnstr;
})
onMounted(()=>{
resolveExp();
})
watch(()=> props.expression, (v) =>{
resolveExp();
});functionresolveExp() {//反解析 表达式 if(props.expression) {
let arr= props.expression.split(" ");if (arr.length >= 6) {//6 位以上是合法表达式 let obj ={
second: arr[0],
min: arr[1],
hour: arr[2],
day: arr[3],
month: arr[4],
week: arr[5],
year: arr[6] ? arr[6] : "",
};
crontabValueObj.value={
...obj,
};for (let i inobj) {if(obj[i]) changeRadio(i, obj[i]);
}
}
}else{//没有传入的表达式 则还原 clearCron();
}
}//tab切换值 functiontabCheck(index) {
tabActive.value=index;
}//由子组件触发,更改表达式组成的字段值 functionupdateCrontabValue(name, value, from) {//"updateCrontabValue", name, value, from; crontabValueObj.value[name] =value;if (from && from !==name) {
console.log(`来自组件 ${from} 改变了 ${name} ${value}`);
changeRadio(name, value);
}
}//赋值到组件 functionchangeRadio(name, value) {
let arr= ["second", "min", "hour", "month"]
let refName= "cron" +name
let insValue;if (!proxy.$refs[refName]) return;if(arr.includes(name)) {if (value === "*") {
insValue= 1;
}else if (value.indexOf("-") > -1) {
let indexArr= value.split("-");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("cycle01", 0))
: (proxy.$refs[refName].setData("cycle01", Number(indexArr[0])));
proxy.$refs[refName].setData("cycle02", Number(indexArr[1]));
insValue= 2;
}else if (value.indexOf("/") > -1) {
let indexArr= value.split("/");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("average01", 0))
: (proxy.$refs[refName].setData("average01", Number(indexArr[0])));
proxy.$refs[refName].setData("average02", Number(indexArr[1]));
insValue= 3;
}else{
insValue= 4;
let list= value.split(",");for(let item of list){
item=String(item)
}
proxy.$refs[refName].setData("checkboxList", list);
}
}else if (name == "day") {if (value === "*") {
insValue= 1;
}else if (value == "?") {
insValue= 2;
}else if (value.indexOf("-") > -1) {
let indexArr= value.split("-");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("cycle01", 0))
: (proxy.$refs[refName].setData("cycle01", Number(indexArr[0])));
proxy.$refs[refName].setData("cycle02", Number(indexArr[1]));
insValue= 3;
}else if (value.indexOf("/") > -1) {
let indexArr= value.split("/");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("average01", 0))
: (proxy.$refs[refName].setData("average01", Number(indexArr[0])));
proxy.$refs[refName].setData("average02", Number(indexArr[1]));
insValue= 4;
}else if (value.indexOf("W") > -1) {
let indexArr= value.split("W");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("workday", 0))
: (proxy.$refs[refName].setData("workday", Number(indexArr[0])));
insValue= 5;
}else if (value === "L") {
insValue= 6;
}else{
let list= value.split(",");for(let item of list){
item=String(item)
}
proxy.$refs[refName].setData("checkboxList", list);
insValue= 7;
}
}else if (name == "week") {if (value === "*") {
insValue= 1;
}else if (value == "?") {
insValue= 2;
}else if (value.indexOf("-") > -1) {
let indexArr= value.split("-");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("cycle01", "0"))
: (proxy.$refs[refName].setData("cycle01", String(indexArr[0])));
proxy.$refs[refName].setData("cycle02", String(indexArr[1]));
insValue= 3;
}else if (value.indexOf("#") > -1) {
let indexArr= value.split("#");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("average01", 1))
: (proxy.$refs[refName].setData("average01", Number(indexArr[0])));
proxy.$refs[refName].setData("average02", String(indexArr[1]));
insValue= 4;
}else if (value.indexOf("L") > -1) {
let indexArr= value.split("L");
isNaN(indexArr[0])? (proxy.$refs[refName].setData("weekday", "1"))
: (proxy.$refs[refName].setData("weekday", String(indexArr[0])));
insValue= 5;
}else{
let list= value.split(",");for(let item of list){
item=String(item)
}
proxy.$refs[refName].setData("checkboxList", list);
insValue= 6;
}
}else if (name == "year") {if (value == "") {
insValue= 1;
}else if (value == "*") {
insValue= 2;
}else if (value.indexOf("-") > -1) {
insValue= 3;
}else if (value.indexOf("/") > -1) {
insValue= 4;
}else{
let list= value.split(",");for(let item of list){
item=String(item)
}
proxy.$refs[refName].setData("checkboxList", list);
insValue= 5;
}
}
proxy.$refs[refName].setData("radioValue", insValue);
}//表单选项的子组件校验数字格式(通过-props传递) functioncheckNumber(value, minLimit, maxLimit) {//检查必须为整数 value =Math.floor(Number(value));if (value <minLimit) {
value=minLimit;
}else if (value >maxLimit) {
value=maxLimit;
}returnvalue;
}//隐藏弹窗 functionhidePopup() {
emits("hide");
}//填充表达式 functionsubmitFill() {
emits("fill", crontabValueString);
hidePopup();
}functionclearCron() {//还原选择项 ("准备还原");
crontabValueObj.value={
second:"*",
min:"*",
hour:"*",
day:"*",
month:"*",
week:"?",
year:"",
};for (let j incrontabValueObj.value) {
changeRadio(j, crontabValueObj.value[j]);
}
}
defineExpose({
submitFill, clearCron
})</script> <style scoped>.crontab{
flex:1;
height:100%;
display: flex;
flex-direction: column;
}
.crontab-main {
flex:1;
width:100%;
margin: 10px auto;
background: #fff;
border-radius: 5px;
font-size: 12px;
border: 1px solid #ccc;
box-sizing: border-box;
line-height: 24px;
padding: 5px 10px 5px;
display: flex;
justify-content: space-between;
overflow-y: auto;
}
.crontab-main-table {
box-sizing: border-box;
line-height: 24px;
padding: 5px 10px 5px;
width:50%;
display: flex;
flex-direction: column;
justify-content: space-around;
table {
text-align: center;
width:100%;
margin:0;
span {
display: block;
width:100%;
font-family: arial;
line-height: 30px;
height: 30px;
white-space: nowrap;
overflow: hidden;
border: 1px solid #e8e8e8;
}
}
}
.crontab-main-result {
box-sizing: border-box;
padding: 5px 10px 5px;
background-color: #f1f1f1;
background-size: cover;
width:48%;
display: flex;
flex-direction: column;
.crontab-result-title{
padding: 5px;
}
:deep(.crontab-result-scroll) {
font-size: 12px;
line-height: 24px;
margin:0 !important;
padding-left: 80px;
}
}
.crontab-footer {
text-align: right;
height: 25px;
padding: 5px 20px;
}</style>
将原来组件的按钮移到引用存,引用样例
<el-dialog title="Cron表达式生成器" v-model="formCrontabOpen" append-to-body destroy-on-close class="nine-tanchuang-001"> <!-- <crontab @change="cronChange" v-model:value="formData.cronExpression" /> --> <Crontab ref="crontabRef" @hide="formCrontabOpen=false" @fill="crontabFill" v-model:expression="formData.cronExpression"></Crontab> <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="formCrontSubmit">确 定</el-button> <el-button type="warning" @click="formCrontReset">重 置</el-button> <el-button @click="formCrontabOpen=false">取 消</el-button> </div> </template> </el-dialog>