vue3-vben-admin开发记录、知识点
vue3-vben-admin知识点
一、vue3写法
1、生命周期
setup-组件在创建时
onMounted-挂载在dom时运行
onUpdated-响应数据修改时运行
2、reactive
定义: 接收一个普通对象然后返回该普通对象的响应式代理。等同于 2.x 的 Vue.observable()
定义一个全局常量
let otherParam = reactive({
result: null as any, //设置类型,不设置则为never
title: '',
tabledata: [] as any[],
readid: null as any,
type: null as any,
data: null as any,
workflownumber: '',
});
TS声明文件,因为TS直接引用第三方JS库的时候,虽然可以用,但是是没有类型检查,所以我们需要做一个声明文件,来声明这些第三方库的类型,这样在使用第三方库的时候,就有类型了
declare module
3、父子组件相互调用
3.1父组件调用子组件
先引入组件页面:
import PersonTable from './PersonTable.vue';
在引入组件,并设置ref
<a-card title="所得荣誉" :bordered="false">
<PersonTable ref="tableRef" />
</a-card>
定义常量,引用方法:
const tableRef = ref<{ getDataSource: () => any; test } | null>(null);
调用:
console.log(tableRef.value.test(otherParam.data));
注意:
如果是通过ref调用子组件的方法并需要取其返回值,可能出现有时间差问题,点击部门列表进行筛选时,获取的返回值总是为上一次点击的,就是因为实际上获取的值是ref上一次存储的值,本次需要获取的值还没来得及更新。所以为了避免这个问题,可以使用VUE提供的 watch 特性来监视ref值的变更。
例子:vue-vben-admin-awards:D:\workspace\vscode\vue-vben-admin-awards\src\views\user\DeptTree.vue
watch(
() => treeRef.value?.getSelectedKeys()[0],
(newValue, oldValue) => {
if (newValue !== oldValue) {
// 在这里执行其他操作,例如触发事件或者调用其他函数
handleSelect();
}
},
);
function handleSelect() {
const key = treeRef.value?.getSelectedKeys()[0];
console.log(key);
emit('select', key);
}
3.2子组件调用父组件
可以在子组件使用emits定义事件,再在父组件中监听该事件,当监听到该事件时,出发相应的函数逻辑:
//子组件DeptTree
emits: ['select'], //定义select事件
setup(_, { emit }) {
const treeRef = ref<{ getSelectedKeys: () => any } | null>(null);
function handleSelect() {
const key = treeRef.value?.getSelectedKeys()[0];
emit('select', key); //触发select事件,并传递参数key
}
}
//父组件
<DeptTree class="w-1/4 xl:w-1/5" @select="handleSelect" /> //监听select事件,触发时执行handleSelect函数方法
function handleSelect(deptId = '') { //定义参数deptId,默认值为空,接收子组件传来的key
console.log(deptId);
searchInfo.code = deptId;
reload();
}
4、路由跳转
//引入
import { useRouter } from 'vue-router';
//获取对象
const router = useRouter();
//路由跳转并携带参数
router.push({
name: 'high',
//path:"/detail/high", //不要这个也行
params: {
value: record.pkid,
title: title,
},
});
//目的页面接收参数
let otherParam = reactive({
showA: false,
result: null as any, //设置类型,不设置则为never
title: '',
tabledata: [] as any[],
pkid: null as any,
type: null as any,
data: null as any,
});
const route = useRoute();
const getParams = () => {
return route.params;
};
// Composition API 生命周期写法
onMounted(() => {
console.log('mounted:' + getParams().value);
otherParam.title = '' + getParams().title;
otherParam.pkid = getParams().value;
});
5、表单工具FormSchema
ApiSelect类型的下拉框,formActionType获取整个表单的对象,更新表单的方法updateSchema([{}])
{
label: '角色',
field: 'roleName',
component: 'ApiSelect',
componentProps: ({ schema, tableAction, formActionType, formModel }) => {
return {
onChange: (e: ChangeEvent) => {
console.log('change' + e);
if ('' + e == 'Super') {
formActionType.updateSchema([
{
field: 'college',
ifShow: false,
},
]);
formActionType.updateSchema([
{
field: 'profession',
ifShow: false,
},
]);
formActionType.updateSchema([
{
field: 'tclass',
ifShow: false,
},
]);
} else if ('' + e == 'Department') {
formActionType.updateSchema([
{
field: 'college',
ifShow: true,
},
]);
formActionType.updateSchema([
{
field: 'profession',
ifShow: false,
},
]);
formActionType.updateSchema([
{
field: 'tclass',
ifShow: false,
},
]);
} else if ('' + e == 'student') {
formActionType.updateSchema([
{
field: 'college',
ifShow: true,
},
]);
formActionType.updateSchema([
{
field: 'profession',
ifShow: true,
},
]);
formActionType.updateSchema([
{
field: 'tclass',
ifShow: true,
},
]);
}
},
api: getdropdownselectList,
params: { type: 'roleName' },
labelField: 'roleName',
valueField: 'roleValue',
};
},
required: true,
},
6、获取用户对象数据
import { useUserStore } from '/@/store/modules/user';
const userStore = useUserStore();
const username = computed(() => userStore.getUserInfo.username || headerImg);
7、await Promise.all
1.await 可以获得多个promise 的返回结果
2.Promise.all 返回的也是promise,所以可以直接await Promise.all();
获取两个表单的数据:
const [register, { validate }] = useForm({
layout: 'vertical',
baseColProps: {
span: 6,
},
schemas: schemas,
showActionButtonGroup: false,
});
const [registerTask, { validate: validateTaskForm }] = useForm({
layout: 'vertical',
baseColProps: {
span: 6,
},
schemas: taskSchemas,
showActionButtonGroup: false,
});
const [values, taskValues] = await Promise.all([validate(), validateTaskForm()]);
console.log('form data:', values, taskValues);
8、ES6 扩展运算符 三个点(…)
es6中引入扩展运算符(…),它用于把一个数组转化为用逗号分隔的参数序列,它常用在不定参数个数时的函数调用,数组合并等情形。因为typeScript是es6的超集,所以typeScript也支持扩展运算符。
用法:
可变参数个数的函数调用
function push(array, ...items) {
array.push(...items);
}
function add(...vals){
let sum=0;
for(let i=0;i<vals.length;i++){
sum+=vals[i];
}
return sum;
}
let arr = [1,2,3,4,5,6];
let sum = add(...arr);
console.log(sum); //21
更便捷的数组合并
let arr1 = [1,2];
let arr2 = [5,6];
let newArr = [20];
//es5 旧写法
newArr = newArr.concat(arr1).concat(arr2); //[20,1,2,5,6]
console.log(newArr);
//es6 使用扩展运算符
newArr = [20,...arr1,...arr2]; //[20,1,2,5,6]
console.log(newArr);
替代es5的apply方法
// ES5 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f.apply(null, args);
// ES6 的写法
function f(x, y, z) {
// ...
}
var args = [0, 1, 2];
f(...args);
求最大值Math.max()
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
通过push函数,将一个数组添加到另一个数组的尾部
// ES5 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);
// ES6 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
新建Date类型
// ES5
new (Date.bind.apply(Date, [null, 2015, 1, 1]))
// ES6
new Date(...[2015, 1, 1]);
与解构赋值结合,生成新数组
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
下面是另外一些例子。
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []:
const [first, ...rest] = ["foo"];
first // "foo"
rest // []
将字符串转为真正的数组
[...'hello']
// [ "h", "e", "l", "l", "o" ]
将实现了 Iterator 接口的对象转为数组
var nodeList = document.querySelectorAll('div');
var array = [...nodeList];
//接第七点,解包values、taskValues两个对象
individualsubmit({ ...values, ...taskValues, mylist, ttype, wfnum }).then(function (response) {
console.log(response);
if (response == 'success') {
createMessage.success('提交成功!');
issubmit.value = !issubmit.value;
}
});
json对象做三元表达式判断
{
type: "refer",
key: "machineNumber",
label: "整机编号",
refinfo: "equipmentPool",
refName: "整机",
isReturnCode: true,
clientParam: {
EQ_isEnable: "1",
// EQ_agent: JSON.parse(localStorage.getItem('_A_P_customer')).id || ''
...(JSON.parse(localStorage.getItem('_A_P_customer')).id ? { EQ_agent: JSON.parse(localStorage.getItem('_A_P_customer')).id } : {})
},
二、各组件接口方法
1、侧边抽屉
<template>
<Drawer4 @register="register4" />
</template>
import Drawer4 from './Drawer4.vue';
export default defineComponent({
components: {
Drawer4,
},
setup() {
const [register4, { openDrawer: openDrawer4 }] = useDrawer();
function send() {
openDrawer4(true, {
data: 'content',
info: 'Info',
});
}
return {
send,
register4,
};
},
});
2、进度条
<div class="progress" style="width: 200px">
<Progress :percent="item.percent" status="active" />
</div>
3、分步步骤条
<Steps :current="item.current - 1" progress-dot size="small">
<Step :title="i.status" v-for="i in item.workflowlist" :key="i.id">
<template #description>
<div v-show="i.handler">由{{ i.handler }}-{{ i.handleaction }}</div>
<p>{{ i.handletime }}</p>
</template>
</Step>
<!-- <Step title="创建项目">
<template #description>
<div>Vben</div>
<p>2016-12-12 12:32</p>
</template>
</Step>
<Step title="部门初审">
<template #description>
<p>Chad</p>
</template>
</Step>
<Step title="财务复核" />
<Step title="完成" /> -->
</Steps>