二次封装element-plus的TableAndPage
首先梳理一下要用到那些东西:
1) vue: {
defineComponent, // 编写ts需要该方法包裹
openBlock, // 创建一个初始化一个块
createBlock, // 创建一个块
renderSlot, // 渲染slot, 他有四个参数:($slot, '插入的名': string, 传入的参数:object, fallback: () => VNodeArrayChildren, onSlotted: Boolean)
resolveComponent, // 解析组件, 他有俩参数: (组件名, maybeSelfReference: Boolean)
withDirectives, // 创建指令
resolveDirective, // 解析已有的指令,他有一个参数:(指令名:string)
withCtx, // 这个方法我也不是很懂,望大佬解答, 貌似用来记录插入的vnode
mergeProps, // 这个是用来继承属性的
}
2) element-plus: {
ElTable, 表格
ElPagination, // 分页
}
复制代码
定义一下组件需要的props:
props: {
/**
* 组件id
*/
idx: {
type: String,
default: 'diy-1',
require: true,
},
/**
* 获取数据的接口函数
*/
ajaxData: {
type: Function,
default: ()=> (() => Promise),
require: true,
},
/**
* Table 的最大高度。合法的值为数字或者单位为 px 的高度。
*/
maxHeight: {
type: Number || String,
},
/**
* Table 当前加载的分页
*/
currentPage: {
type: Number,
default: 1,
},
/**
* 是否需要loading
*/
isLoading: {
type: Boolean,
default: false
},
/**
* 获取数据接口的参数
*/
params: {
type: Object,
default: {
page: 1,
size: 20
},
require: true,
},
/**
* 接口返回数据列表的key
*/
requsetKey: {
type: Object,
default: () => ({
key1: 'data',
key2: 'list'
})
}
}
复制代码
定义一下组件需要的方法以及属性:
setup (props, context) {
const { ajaxData, params, requsetKey, currentPage, isLoading } = toRefs(props);
const list = reactive<Array<IOBJ>>([]);
const total = ref<number>(400);
const pageSizes = reactive<Array<number>>([1, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]);
const loading = ref<boolean>(false);
/*这个方法的递归获取列表*/
const indexKey = (keys: Array<string>, params: any, index: number = 0): any => {
if (Array.isArray(params)) return params;
params = params[requsetKey.value[keys[index]]]
index++;
return indexKey(keys, params, index);
};
const getList = async (pageNo?: number) => {
pageNo && (params.value.page = pageNo);
loading.value = isLoading.value;
const keys = Reflect.ownKeys(requsetKey.value) as Array<string>;
let res = await ajaxData.value(params.value);
const data = indexKey(keys, res)
list.splice(0);
list.push(...data);
total.value = res.data.total;
loading.value = false;
}
onMounted(() => {
!params.value.page && Object.assign(params.value, {page: 1, size: 20});
})
const handleSizeChange = (val: number) => {
params.value.size = val;
getList().catch();
}
const handleCurrentChange = (val: number) => {
params.value.page = val;
getList().catch();
}
return {
handleSizeChange,
handleCurrentChange,
total,
getList,
pageSizes,
loading,
list,
// id: 'table-'
}
}
复制代码
渲染函数:
let see = 1;
script.__file = 'src/components/TableAndPage/index.ts';
script.install = (App: IOBJ) => {
App.component(script.name, script);
}
script.render = (ctx: IOBJ, cache: Array<any>, $props: IOBJ, $setup: Function, $data: IOBJ, $options: IOBJ) => {
++see;
const componentElPagination = resolveComponent(ElPagination.name);
const componentElTable = resolveComponent(ElTable.name);
const directiveLoading = resolveDirective('loading') as Directive;
// console.log(ctx.idx, toDisplayString(ctx.idx));
return(openBlock(), createBlock('div', {
id: toDisplayString(ctx.idx),
className: '423423'
}, [
createVNode('div', {id: toDisplayString(ctx.idx)}, {
default: withCtx(() => [
renderSlot(ctx.$slots, 'default', {
list: ctx.list,
loading: ctx.loading,
maxHeight: ctx.maxHeight
}),
withDirectives(createVNode(componentElTable, mergeProps(ctx.$attrs,{
data: ctx.list,
border: true,
maxHeight: ctx.maxHeight,
}), {
inline: withCtx(() => [
renderSlot(ctx.$slots, 'inline')
], undefined)
}, 8/* PROPS */, ['data', 'border', 'maxHeight']), [
[directiveLoading, ctx.loading]
]),
], undefined)
}, 512 /*NEED_PATCH*/),
createVNode(componentElPagination, {
onSizeChange: ctx.handleSizeChange,
// currentPage: ctx.currentPage,
onCurrentChange: ctx.handleCurrentChange,
// 'onUpdate:currentPage': cache[0] || (cache[0] = ($event: number) => ctx.$emit('update:currentPage', $event)),
pageSizes: ctx.pageSizes,
pageSize: ctx.params.size,
layout: "total, sizes, prev, pager, next, jumper",
total: ctx.total,
}, null, 8, [
'onSizeChange',
// 'currentPage',
'onCurrentChange',
// 'onUpdate:currentPage',
'pageSizes',
'pageSize',
'total'
])
], 512 /* NEED_PATCH */))
}
export default script;
复制代码
使用
import {
defineComponent,
ref,
createBlock,
openBlock,
createVNode,
Transition,
reactive,
Fragment,
renderList,
withDirectives,
vModelText,
resolveComponent,
withCtx,
toDisplayString,
onMounted,
resolveDirective,
getCurrentInstance,
Directive, createTextVNode,
} from 'vue';
import {ElInput, ElButton, ElTable, ElTableColumn, ElRadioGroup, ElRadioButton} from 'element-plus';
import TableAndPage from '@/components/TableAndPage/index';
import { getLike } from '@/assets/api/song';
export default defineComponent({
components: {
'table-and-page': TableAndPage,
},
setup () {
const current = ref(6);
const TableAndPageRef = ref<IOBJ | null>(null);
const params = reactive<IOBJ>({})
onMounted(() => {
TableAndPageRef.value && TableAndPageRef.value.getList(1)
})
const componentTableAndPage = resolveComponent('table-and-page');
const directiveLoading = resolveDirective('loading') as Directive;
return (ctx: any, cache: any) => {
return (openBlock(), createBlock('div', {
id: 'my-favorites',
class: 'favorites',
}, [
createVNode(componentTableAndPage, {
ajaxData: getLike,
params: params,
id: 'table',
ref: TableAndPageRef,
isLoading: true,
// currentPage: current.value,
// 'onUpdate:currentPage': cache[3] || (cache[3] = ($event: number) => (current.value = $event)),
},
{
default: withCtx(({list, loading, maxHeight}: IOBJ) => [
withDirectives(createVNode(componentElTable, {
data: list,
maxHeight: maxHeight,
onLoading: loading,
}, [
createVNode(componentElTableColumn, {
prop:'song_name',
label: '音乐标题'
}),
createVNode(componentElTableColumn, {
prop: 'singer_name',
label: '歌手'
})
], 8, ['data', 'maxHeight']), [
[directiveLoading, loading]
]),
], undefined),
_: 1,
}, 520 /* PROPS, NEED_PATCH */, ['ajaxData', 'params', 'onUpdate:currentPage', 'currentPage', 'isLoading'])
], HOISTED));
}
},
})
复制代码
有的东西没讲那么详细 第一篇文章有
大功告成 哇哈哈哈 明天见
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END