vue3.0常用方法-GA ※※※※※※※※※※
vue3.0常用的函数及方法:
数组操作常用方法.map filter forEach find findIndex includes some every
map 用于数组 一般map适用于对于数组中的数据需要重新处理,也就是需要return出一个新数组的时候。
solutionPlaces.value = res.data.result.trainingSolutionPlaces.map(obj=>{
return {
id:obj.trainingPlaceId,
name:obj.trainingPlaceName,
trainingSolutionId:obj.trainingSolutionId
}
})
filter 用于数组
function shower(){
let arr = [5,8,98,15,4];
let str = "abcde";
let arrBool = arr.filter(item=>item>8)
console.log(arrBool,"arr");//输出结果 [98,15]
}
shower()
forEach 循环数组,里面可以写函数。forEach 方法没有返回值,它只是遍历数组并执行回调函数,不会生成新的数组。因此,forEach 通常用于处理数据,而不是创建新的数据结构。
find 用于数组 查找到了就返回当前item组成的数组,没查找到就返回空数组
findIndex 用于数组 查找到了就返回当前item的下标(从左往右,有满足条件的就立即返回并且不会再往下查找了),没查找到就返回-1
includes 既能用于数组有能用于字符串 includes表示“包含有”的意思,第一个参数是要查找的内容,第二个参数是从什么位置开始查找,查找到了就返回true,没查找到就返回false
indexOf 用于数组 字符串 ,第一个参数是要查找的内容,第二个参数是从什么位置开始查找,查找到了就返回下标,没查找到就返回-1
some 用于数组不能用于字符串,some表示“有”的意思,只要数组中有满足条件的item就会返回true,但数组中所有元素都不满足才会返回false
every 用于数组不能用于字符串,every表示“每一个”的意思,要求数组中所有元素满足条件才返回true,数组中有元素都不满足判断条件就会返回false
https://blog.csdn.net/2202_75509848/article/details/130502834
sort数组排序:
const numbers = [4, 2, 9, 3, 5, 1];
numbers.sort((a, b) => a - b);
console.log(numbers); // 输出: [1, 2, 3, 4, 5, 9]
====================================================
==================================================
路由meta的使用
{
path: "/stageLayout",
name: "stageLayout",
component: () => import("../layout/stageLayout/stageLayout.vue"),
children: [
{
path: "/stageIndex",
name: "stageIndex",
meta: {
allowUser: ["JWCGLY", "XBGLY", "XSDGLY", "XSJDGLY"],
title: "方案",
icon: "Menu",
},
component: () => import("../views/stageIndex.vue"),
}
]
}
页面引用
import { ref } from 'vue';
import { useRoute } from 'vue-router';
const route: any = useRoute();
console.log(route.meta);
<el-icon color="#fff">
<component :is="route.meta.navIcon" :style="{ color: '#fff', fontSize: '20px' }" />
</el-icon>
{{route.meta.navTitle}}
==================================================
全选/不全选
selectPlace是选中的数据带有id
selectPlaceAll是所有数据 都不带id
let placeIds = selectPlace.value.map(obj => { return obj.trainingPlaceId }) // 获取已选择的所有id
if(selectPlaceAll.value.length>0){
selectPlaceAll.value.forEach(obj => {
if (!placeIds.includes(obj.trainingPlaceId)) { // 判断是否包含,把不包含的全面push进已选择的数组里面
selectPlace.value.push(obj)
}
})
}else{
selectPlace.value=[]
}
console.log("selectPlace222", selectPlace.value) //全选时,选中的数组中包括已经勾选的有id和所有未勾选的无id的都综合在一起
=========================================
导出接口
window.location.href='PM/ExportWorkLogs?isAll='+formData.value.isAll+'&startDate='+formData.value.date[0]+'&endDate='+formData.value.date[1]
=========================================
callBack回调函数
const getReleaseDepartmentSolutionsForSelect = (query,callBack?) => {
loading.value = true
let data = {
queryStr: query
}
GetReleaseDepartmentSolutionsForSelect(data).then(res => {
if (res.data.results) {
solutionList.value = res.data.results;
stageList.value = res.data.results.trainingStages;
trainingSolutionId.value = res.data.results[0].id;
if(callBack){
callBack()
}
}
}).finally(() => {
loading.value = false;
})
}
const getlogData = () => {}
getReleaseDepartmentSolutionsForSelect('',getlogData);
=============================================
数据格式转换:
trainingSolutionBattalions: trainingSolutionBattalionsList.value.map(obj=>{ //先转换字段名称 再过滤
return {
battalionId:obj.id,
battalionName:obj.name,
trainingSolutionId:obj.trainingSolutionId
}
}).filter(obj=>{
if (obj.battalionId == planData.value.trainingSolutionBattalionsId) {
return obj;
}
}),
===================================
//日期超出范围禁用
<el-date-picker v-model="planData.stageTime" type="daterange" range-separator="至" start-placeholder="开始时间"
end-placeholder="结束时间" :disabled="readonly" :disabled-date="disabledDate" />
//限制日期时间范围
const disabledDate = (time: Date) => {
return time.getTime() < Date.parse(trainingSolution.value.startDate) || time.getTime() > Date.parse(trainingSolution.value.endDate)
}
========================================
css文字带格式换行:
white-space: pre-wrap;
===============弹窗====================
父组件:
<overallSolution :showDialog="showDialog" :readonly="false" @close="showDialog = false"></overallSolution>
const showDialog = ref(false)
const addPlan = () => {
showDialog.value = true;
console.log("新增计划");
}
子组件:
<el-dialog v-model="dialogVisible" title="教务处方案" width="1000" :destroy-on-close="true" :close-on-click-modal="false" :show-close="true" @close="closeDialog" top="8vh">
<el-form ref="formRef" :layout="'vertical'" :model="planData" label-position="top" size="default" class="formRef" >
<el-form-item label="方案名称" prop="title" :rules="[{ required: true, message: '请选填写方案名称', trigger: ['blur'] }]">
<el-input v-model="planData.title" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button size="default" @click="closeDialog">取消</el-button>
<el-button size="default" type="primary" @click="submitForm(formRef)">确定</el-button>
</div>
</template>
</el-dialog>
const props = defineProps({
// 只读
readonly: {
type: Boolean,
default: false
},
showDialog: {
type: Boolean,
default: false
}
})
const dialogVisible = ref(false)
watch(() => props.showDialog, (newVal, oldVal) => {
dialogVisible.value = newVal;
}, {
deep: true,
})
//关闭弹窗
const emit = defineEmits();
const closeDialog = () => {
console.log("dddd")
dialogVisible.value = false;
emit('close', dialogVisible.value)
}
const formRef = ref()
const planData: any = ref({
trainingSolutionEvaluationSystem:''
})
const modelValue = ref([])
//确认
const submitForm = async (formEl) => {
console.log('planData',planData.value)
let data={
...planData.value,
startDate:planData.value.rangeTime[0],
endDate:planData.value.rangeTime[1],
}
console.log('data',data)
// SaveTrainingSolution
if (!formEl) return
await formEl.validate((valid, fields) => {
if (valid) {
console.log('submit!')
} else {
console.log('error submit!', fields)
}
})
}
//重置
const resetForm = (formEl) => {
if (!formEl) return
formEl.resetFields()
}
==============================
弹窗编辑
//默认值
const formData: any = ref({
id: '',
enable: true,
percentage: '1'
})
当点击事件后,三点运算符将对象进行浅拷贝,这样修改时不会修改的原来的数据。
const editMajor = (item) => {
majorEditDialog.value = true;
formData.value = {
...item
};
}
=============================
组件通过v-model:实现数据双向绑定,更新的时候通过emit("update:XXXX")向外抛出数据,即可被v-model绑定。
<emergencyLevelSelector v-model:emergency-level="taskData.emergencyLevel" />
const props = defineProps({
emergencyLevel: {
type: String,
},
})
const emit = defineEmits(["update:emergencyLevel"]);
const emergencyLevelChange = () => {
emit("update:emergencyLevel", emergencyLevelItem.value)
}
=================================
时间日期格式化 中文文档:https://momentjs.cn/
import moment from 'moment';
{{ moment(project.startDate).format("YYYY年MM月DD日") }} - {{ moment(project.endDate).format("YYYY年MM月DD日")}}
data.minDate = moment(modeDate.value).format('YYYY-MM-DD HH:mm:ss');
data.maxDate = moment(modeDate.value).endOf('day').format('YYYY-MM-DD HH:mm:ss');
data.minDate = moment(modeDate.value).startOf('week').add(1, "days").format('YYYY-MM-DD HH:mm:ss');
data.maxDate = moment(modeDate.value).endOf('week').add(1, "days").format('YYYY-MM-DD HH:mm:ss');
范围日期转换
planData.value.rangeTime = [trainingSolution.value.startDate, trainingSolution.value.endDate];
startDate: moment(planData.value.stageTime[0]).format("YYYY-MM-DD"),
endDate: moment(planData.value.stageTime[1]).format("YYYY-MM-DD"),
data: moment().format("YYYY-MM-DD"), 当天
week: moment().format("YYYY-ww"), 当周
start: moment().startOf('week').format('YYYY-MM-DD'), 当前周开始
end: moment().endOf('week').format('YYYY-MM-DD') 当前周结束
weekQuery.value.week = moment(weekQuery.value.week).subtract(1, 'weeks').format("YYYY-MM-DD"); //上周开始的第一天
weekQuery.value.week = moment(weekQuery.value.week).add(1, 'weeks').format("YYYY-MM-DD"); //下周开始的第一天
moment().valueOf() //当前时间日期转时间戳
date: [moment().startOf('month').format("YYYY/MM/DD"), moment().endOf('month').format("YYYY/MM/DD")] 当月第一天到当月最后一天
workPlanTime:[moment().startOf('year').format("YYYY/MM/DD"), moment().endOf('year').format("YYYY/MM/DD")] 当年第一天到当年最后一天
===================================
公共方法的写法
gench.projectmanage.pc\src\util\util.ts
export default class colorUtil {
// public randomColors = ["#f5222d", "#fa541c", "#fa8c16", "#faad14", "#fadb14", "#a0d911", "#52c41a", "#13c2c2", "#1677ff", "#2f54eb", "#722ed1", "#eb2f96"]
public randomColors = ["#13c2c2"]
//随机颜色
public getRandomColor() {
return this.randomColors[Math.floor(Math.random() * this.randomColors.length)];
}
}
组件里的使用:
import colorUtil from "../util/util";
<a-avatar :style="{ backgroundColor: colorUtils.getRandomColor() }">
{{ charge.fapUserName[0] }}
</a-avatar>
===========================================
//关闭标签
const closeTag = (item) => {
let fapTagIndex = selecTag.value.findIndex(obj => obj.id === item.id);
if (fapTagIndex !== -1) { //如果已经有,则删除
selecTag.value.splice(fapTagIndex, 1);
} else {
selecTag.value.push({ ...item }); //如果没有,则增加
}
workPlanTagName.value = selecTag.value.map(item => item.name).join(',')
reload();
}
==============================================
:style="'background-color:'+record.color"
style="height: calc(100vh - 230px);" //全屏高度设置
ref定义的要用.vule赋值,适用于数字、字符串
reactive定义的数组不需要用vule,适用于数组、对象
===============工作项目========================
判断多选框是否选中 gench.projectmanage.pc
<CheckOutlined style="color: #1677ff;font-size: 18px;" v-if="isSelectd(item.id)" />
const isSelectd = (id) => {
let fapTagIndex = selecTag.value.findIndex(obj => obj.id === id);
return fapTagIndex !== -1
}
=========================================
访问子组件的方法
父组件访问子组件方法 gench.projectmanage.pc
父组件:
<selectTag ref="selectTagComponent" :target-objects="workPlanData.targetObjects" @submitTargets="checkTargets"/>
const selectTagComponent = ref(null)
const selectTags = () => {
selectTagComponent.value.onSubmit(); //父组件访问子组件的方法
tagShow.value = false;
};
子组件内容:
const onSubmit = () => {
emit("submitTargets", selecTag.value)
}
defineExpose({
onSubmit //子组件
});
============================================
路由跳转:useuseRouter 函数用于获取当前的路由器实例
import { useRouter } from "vue-router";
const router: any = useRouter();
router.push({
path: "/repairDetail",
});
===========================================
获取路由id useRoute 函数用于获取当前的路由信息
import { useRouter } from "vue-router";
const router: any = useRouter();
路由传参
router.push({
path: "/stageIndex",
query: { id: '123' }
});
import { useRoute } from 'vue-router';
const route = useRoute();
获取路由参数
route.query.id
=============================================
开始结束时间: planData.value.rangeTime = [trainingSolution.value.startDate,trainingSolution.value.endDate]
let data={
...planData.value,
startDate:planData.value.rangeTime[0],
endDate:planData.value.rangeTime[1]
}
==========================================
const stepDict = reactive([
{ text: "已提交", value: 0, },
{ text: "已受理", value: 1, },
{ text: "已派单", value: 2, },
{ text: "已处理", value: 3, },
{ text: "已评价", value: 4, },
])
===========================================
const getRepairInfo = () => {
dataLoading.value = true
GetRepairInfo(route.query.id).then((res: any) => {
repairData.value = res.data.result
}).catch((err) => {
console.log(err);
}).finally(() => {
dataLoading.value = false
})
}
onMounted(() => {
getRepairInfo()
})
================================================
相当于swiper
<el-carousel height="200px" motion-blur>
<el-carousel-item v-for="item in 4" :key="item">
<h3 class="small justify-center" text="2xl">{{ item }}</h3>
</el-carousel-item>
</el-carousel>
scoped内部修改组件的样式
::v-deep .el-carousel__container{
height: 500px;
}
/deep/ .el-checkbox__inner{
background-color: #fff;
border: #ff943e 1px solid;
}
北京或者文字半透明
background: rgba(255, 255, , 255, , 0.8);
colorrgba(0, 0, 0, 0.5);
================================
时间日期格式化:moment.js
import moment from 'moment';
{{ moment(item.createDate).format("YYYY-MM-DD HH:mm:ss")}}
//拼接报修分类
const getRepairCategories = (repairCategories) => {
return repairCategories?.map(obj => obj.category.name).join("、")
}
//******根据id筛选数据 *******
const getWorkPlanCharge = () => {
let findWorkPlan = chargesList.value.find(obj => obj.id == taskData.value.projectId)
return findWorkPlan ? findWorkPlan.charges : []
}
==========================================================
接口配置:
E:\shimily\project\gench.projectmanage\gench.projectmanage.pc\src\api
单个字段传值:
//通过建筑物获取房屋
export const GetRoomsForSelect = (buildingId: any) => {
return request.get("Repair/GetRoomsForSelect", {
params: {
buildingId: buildingId,
},
}
);
};
多字段传值:
//分页获取报修单
export const GetRepairInfos = (data: any) => {
return request.get("Repair/GetRepairInfos", {
params: {
...data,
},
});
};
接口请求:
SaveRepairInfo(data).then((res: any) => {
if (res.data.result) {
showSuccessToast("上报成功");
router.push({
path: "/repairList",
});
}
}).catch((err) => {
console.log(err)
}).finally(() => {
sumbitLoading.value = false
})
//带确认按钮的弹窗
ElMessageBox.confirm(
'确定要删除该负责人吗?',
'温馨提示',
{
confirmButtonText: '确认删除',
cancelButtonText: '取消',
type: 'warning',
}
).then(() => {
ElMessage({
type: 'success',
message: '删除成功',
})
}) .catch(() => {
ElMessage({
type: 'info',
message: '取消成功',
})
})
//弹窗消息提示
ElMessageBox.alert('This is a message', 'Title', {
// if you want to disable its autofocus
// autofocus: false,
confirmButtonText: 'OK',
callback: (action: Action) => {
ElMessage({
type: 'info',
message: `action: ${action}`,
})
},
})
提示弹窗
//成功弹窗
ElMessage({
message: '成功',
type: 'success',
})
//错误弹窗
ElMessage({
message: '失败',
type: 'warning',
})
===================
父组件调用子组件的方法 sing()
<Child ref="child"/>
this.$refs.child.sing();
===================
<el-checkbox-group v-model="repairHandlers">
<!-- <el-checkbox :label="charges.chargePeopleName" :value="charges.id" v-for="(charges,indx) in item.category.categoryCharges" :key="indx" /> --> //repairHandlers里的值为:'55464654654'
<el-checkbox :label="charges.chargePeopleName" :value="{categoryId:charges.id}" v-for="(charges,indx) in item.category.categoryCharges" :key="indx" /> //repairHandlers里的值为:categoryId:'55464654654'
<!-- <el-checkbox :label="charges.chargePeopleName" :value="charges" v-for="(charges,indx) in item.category.categoryCharges" :key="indx" /> --> //repairHandlers里的值为对象
</el-checkbox-group>
==========================
弹窗收集data,要通过合并对象的方式,防止双向绑定
Object.assign(formData.value,row)
//手机号验证
import { isPhone } from "../../src/util/until";
if (!isPhone(value))
callback(new Error(translateTitle("密码不能少于6位")));
else callback();
==========================
暂无数据:
<el-empty description="暂无数据" :image-size="200" v-else />
//返回对象内部某个属性
const data = {
repairInfoId: id,
repairHandlers: repairHandlers.value.map(obj =>{
return {
repairInfoId: id,
categoryChargeId:obj.id,
}
})
}
//紧急情况 颜色 前端根据颜色或者step获取属性值
const colorList = ["#1677ff", "#52c41a", "#fadb14", "#fa8c16", "#f5222d"]
const getEmergencyLevelColorByKey = (value) => {
let findObj = dict.emergencyLevelTypes.find(obj => obj.value == value)
console.log('findObj',findObj)
return findObj ? colorList[value] : "#dadada"
}
使用方法: <a-tag :color="getEmergencyLevelColorByKey(task.emergencyLevel)" class="radius10"> {{ getEmergencyLevelLabelByKey(task.emergencyLevel) }}</a-tag>
时间格式转换
import moment from 'moment';
moment(repairData.createDate).format("YYYY-MM-DD HH:mm:ss")
//监听数据变化watch,然后再赋值或者执行
watch(()=> props.status,(newVal,oldVal)=>{
console.log("监听",newVal,oldVal)
getStatus();
})
emit检索数据向外抛出
const selectFapUser = () => {
emit("update:charges", [...selectUsers.value].map(obj => {
return {
fapUserId: obj.fapUserId,
fapUserName: obj.fapUserName,
}
})
)
对象合并
Object.assign({},obj1,logList.value);
给已经有的数组里新增前端需要的属性
logList.value = res.data.results;
logList.value.map(obj => {
obj.more=false
obj.moreTxt='显示更多'
console.log("obj",obj)
})
const currentYear = new Date().getFullYear();
// 获取当年第一天
const firstDayOfYear = new Date(currentYear, 0, 1);
// 获取当年最后一天
console.log(moment(firstDayOfYear).format("YYYY/MM/DD"), moment(lastDayOfYear).format("YYYY/MM/DD"))
const lastDayOfYear = new Date(currentYear, 11, 31);
console.log("moment1", moment().startOf('year').format("YYYY/MM/DD"))
console.log("moment2", moment().endOf('year').format("YYYY/MM/DD"))
========================================
返回上页
const goBack = () => {
window.history.go(-1);
}
==================================================================
选人控件:
<a-row gutter="24">
<a-col span="24">
<a-form-item label="参与者" name="charges"
:rules="[{ type: 'array', required: true, message: '请选择参与者', trigger: ['blur'] }]">
<selectChargeCheckBox v-model:charges="workPlanData.charges" :project-charges-list="getWorkPlanCharge()" />
</a-form-item>
</a-col>
</a-row>
const getWorkPlanCharge = () => {
let findWorkPlan = workPlanList.value.find(obj => obj.id == workPlanData.value.workPlanId)
console.log('参与人1',findWorkPlan)
return findWorkPlan ? findWorkPlan.charges : []
}
<template>
<div style="display: flex;gap:5px;align-items: center">
<a-empty :image="simpleImage" v-if="userList.length == 0" style="width: 100%">
<template #description>
<span>
暂无人员选择
</span>
</template>
</a-empty>
<a-checkbox-group v-model:value="selectUsers" style="width: 100%" @change="userChange()" v-else>
<a-checkbox :key="index" :value="item.fapUserId" v-for="(item, index) in userList">
{{ item.fapUserName }}
</a-checkbox>
</a-checkbox-group>
</div>
</template>
<script setup lang="ts">
import { Empty } from 'ant-design-vue';
import { ref, watch } from 'vue'
const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE;
const props = defineProps({
charges: {
type: Array<any>,
default: []
},
projectChargesList: {
type: Array<any>,
default: [],
},
})
watch(() => props.projectChargesList, (newVal, oldVal) => {
userList.value = newVal;
}, {
deep: true,
})
watch(() => props.charges, (newVal, oldVal) => {
selectUsers.value = newVal.map(obj => {
return obj.fapUserId
});
}, {
deep: true,
})
const emit = defineEmits(["update:charges"])
const userList: any = ref([...props.projectChargesList])
const selectUsers: any = ref([])
const userChange = () => {
emit("update:charges", selectUsers.value.map(obj => { //charges更新的是父级里的 v-model:charges 里的数据内容
return {
fapUserId: obj,
fapUserName: userList.value.find(item => item.fapUserId == obj).fapUserName,
}
})
);
}
</script>
<style>
</style>
==========================================================
修改数据结构:
项目管理系统projectEdit.vue
checkbox选择出来的是targetObjects=['124234234','2342423423']数组,但我们需要的是
targetObjects=[
0:{targetId:'124234234',targetName:'沈方园',objectId:'1222222222222'}
1:{targetId:'2342423423',targetName:'学生处',objectId:'123333333333'}
]
dt.targetObjects = relativeTagList.value.filter((tag)=>{
return dt.targetObjects.includes(tag.id)
}).map(item => {
return {
objectId: dt.id,
targetId: item.id,
targetName: item.name
}
})
===========================================================
弹窗列表数据不更新问题 E:\shimily\project\gench.projectmanage\gench.projectmanage.mobile\src\views\logItem.vue
解决方案:通过computed计算属性
//日志列表弹窗
const logShow = ref(false)
const listLoading = ref(false)
const logList: any = computed(() => {
if (logSelectDate != null) {
let result = logResult.value.find(obj => obj.dateStr == logSelectDate.value)
console.log(result)
if (result) {
listLoading.value = true;
setTimeout(() => {
listLoading.value = false;
}, 200)
return result.workLogs;
} else {
logShow.value = false;
return [{}];
}
} else {
return [{}]
}
})
const logSelectDate = ref(null)
const showList = (dateStr) => {
logSelectDate.value = dateStr;
logShow.value = true;
}
=========vue2.0==========================
时间格式化
{{scope.row.jinXiao.jinXiaoQianDaoQueRen?formatDate(scope.row.jinXiao.jinXiaoQianDaoQueRen,"YYYY-MM-DD HH:mm"):""}}
watch: {
confirmVisible: {
handler: function (val, oldVal) {
this.$emit("changed", this.confirmVisible)
},
deep: true
},
},