? ? ? ? 这是一个多用途的基于element-plus 封装的表格组件,基本上elemnet-plus 官网涉及到的使用场景,都可以,而且使用上来说会简单许多,配置上类似与vxe-table 的使用,下面逐一展示各种场景的使用方式,基本上与el-table 使用方式类似,上手成本低。
? ? ? ? 在我门公司的项目中,遇到很多地方会使用到表格,而我们使用的是element-plus 官方的表格组件,各个地方使用的都会多少有点差异,比如有的表格需要border, 有的地方不需要border,有的地方需要多选批量操作】有的地方需要斑马线等等,所以这里统一封装了一下,基本可以兼容上述所有使用场景,且使用,大部分与原elemnet-plus 类似,也有参考vxe-table的使用方式,下面开始逐一介绍各种使用场景,表格组件封装的源码,会放到最后。
配置表格有哪些列
const columns = [
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
},
];
表格数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
];
?表格组件组使用的地方(当然记得在使用我们表格组件的时候 import 引入一下)
<MxeTableVue :data="tableData" :columns="columns" @getList="getList" />
注意:getList 是在实际使用的时候,需要调用后端接口请求表格数据时用到的,这里没用到可以不写,接下来的表格中也是如此?
其实只需要更改一下,使用表格的地方的代码即可
<MxeTableVue
:data="tableData"
:columns="columns"
stripe
@getList="getList"
/>
这样使用是不是就和 我们使用el-table 的时候,配置一样 stripe 属性直接放到组件上面即可
列配置与数据跟基础表格一致
<MxeTableVue
:data="tableData"
:columns="columns"
border
@getList="getList"
/>
?这样使用是不是就和 我们使用el-table 的时候,配置一样 stripe 属性直接放到组件上面即可
在项目的主css文件中添加你想要的状态样式,我是直接拿element-plus 官网的来做例子的,也可以自己定义
?表格组件使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
:row-class-name="tableRowClassName"
@getList="getList"
/>
script 下增加
const tableRowClassName = ({ row, rowIndex }) => {
if (rowIndex === 1) {
return "warning-row";
} else if (rowIndex === 3) {
return "success-row";
}
return "";
};
?使用表格组件的地方
<MxeTableVue :data="tableData" :columns="columns" @getList="getList" />
列配置
const columns = [
{
label: "Date",
prop: "date",
},
{
label: "Delivery Info",
children: [
{
label: "Name",
prop: "name",
},
{
label: "Address Info",
children: [
{
label: "State",
prop: "state",
},
{
label: "City",
prop: "city",
},
{
label: "Address",
prop: "address",
},
{
label: "Zip",
prop: "zip",
},
],
},
],
},
];
tableData 数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-02",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-04",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-01",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-08",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-06",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
{
date: "2016-05-07",
name: "Tom",
state: "California",
city: "Los Angeles",
address: "No. 189, Grove St, Los Angeles",
zip: "CA 90036",
},
];
?表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
highlight-current-row
@current-change="handleCurrentChange"
/>
列定义
const columns = [
{
type: "index",
label: "序号",
width: 80,
},
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
},
];
?表格数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
];
需要在需要增加一个?handleCurrentChange 当点击表格行时触发,这里主要是显示点击行数据,具体要做啥逻辑得根据自己业务来细化
const handleCurrentChange = (val) => {
// 获取当前行数据
console.log(val);
};
?表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
@selection-change="handleSelectionChange"
/>
列定义
const columns = [
{
type: "selection",
label: "序号",
width: 80,
},
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
},
];
?表格数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
];
需要在需要增加一个?handleCurrentChange 当点击表格行时触发,这里主要是显示点击行数据,具体要做啥逻辑得根据自己业务来细化
const handleSelectionChange = (val) => {
console.log(val);
};
?表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
>
<template #tag="scope">
<el-tag
:type="scope.row.tag === 'Home' ? '' : 'success'"
disable-transitions
>{{ scope.row.tag }}</el-tag>
</template>
</MxeTableVue>
列配置
const columns = [
{
label: "Date",
prop: "date",
columnKey: "date",
// 排序
sortable: true,
// 供筛选的内容,可以根据实际需要配置
filters: [
{ text: "2016-05-01", value: "2016-05-01" },
{ text: "2016-05-02", value: "2016-05-02" },
{ text: "2016-05-03", value: "2016-05-03" },
{ text: "2016-05-04", value: "2016-05-04" },
],
filterMethod: (value, row, column) => {
const property = column["property"];
return row[property] === value;
},
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
// 使用插槽自定义列内容
slots: {
default: "tag",
},
filters: [
{ text: "Home", value: "Home" },
{ text: "Office", value: "Office" },
],
filterMethod: (value, row) => {
return row.tag === value;
},
// 控制筛选框出现的位置
filterPlacement: "bottom-end",
},
];
?tableData 数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
tag: "Home",
},
{
date: "2016-05-02",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
tag: "Office",
},
{
date: "2016-05-04",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
tag: "Home",
},
{
date: "2016-05-01",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
tag: "Office",
},
];
表格使用的地方
<MxeTableVue :data="tableData" :columns="columns">
<template #expand="scope">
<div m="4">
<p m="t-0 b-2">State: {{ scope.row.state }}</p>
<p m="t-0 b-2">City: {{ scope.row.city }}</p>
<p m="t-0 b-2">Address: {{ scope.row.address }}</p>
<p m="t-0 b-2">Zip: {{ scope.row.zip }}</p>
<h3>Family</h3>
<el-table :data="scope.row.family">
<el-table-column label="Name" prop="name" />
<el-table-column label="State" prop="state" />
<el-table-column label="City" prop="city" />
<el-table-column label="Address" prop="address" />
<el-table-column label="Zip" prop="zip" />
</el-table>
</div>
</template>
</MxeTableVue>
列配置
const columns = [
{
type: "expand",
width: 50,
slots: {
default: "expand",
},
},
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
];
tableData 数据?
const tableData = [
{
date: "2016-05-03",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-02",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-04",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-01",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-08",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-06",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
{
date: "2016-05-07",
name: "Tom",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
family: [
{
name: "Jerry",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Spike",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
{
name: "Tyke",
state: "California",
city: "San Francisco",
address: "3650 21st St, San Francisco",
zip: "CA 94114",
},
],
},
];
使用表格的地方
<MxeTableVue :data="tableData" :columns="columns">
<template #opera-header="scope">
<el-input size="small" placeholder="Type to search" />
</template>
<template #opera>
<el-button size="small">Edit</el-button>
<el-button size="small" type="danger">Delete</el-button>
</template>
</MxeTableVue>
列配置
const columns = [
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
slots: {
header: "opera-header",
default: "opera",
},
},
];
tableData 数据
const tableData = [
{
date: "2016-05-03",
name: "Tom",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-02",
name: "John",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-04",
name: "Morgan",
address: "No. 189, Grove St, Los Angeles",
},
{
date: "2016-05-01",
name: "Jessy",
address: "No. 189, Grove St, Los Angeles",
},
];
表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
row-key="id"
border
default-expand-all
/>
列配置
const columns = [
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
},
];
tableData 数据(属性表格,就是根据数据具有 children 展示的)
const tableData = [
{
id: 1,
date: "2016-05-02",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
children: [
{
id: 2,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
children: [
{
id: 3,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 4,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
],
},
{
id: 5,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
children: [
{
id: 6,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 7,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
],
},
],
},
{
id: 8,
date: "2016-05-04",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
children: [
{
id: 9,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 10,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
],
},
{
id: 11,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
children: [
{
id: 12,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 13,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
],
},
];
表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
row-key="id"
border
lazy
:load="load"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
/>
列配置
const columns = [
{
label: "Date",
prop: "date",
},
{
label: "Name",
prop: "name",
},
{
label: "Address",
prop: "address",
},
];
?tableData 数据
const tableData = [
{
id: 1,
date: "2016-05-02",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 2,
date: "2016-05-04",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 3,
date: "2016-05-01",
name: "wangxiaohu",
hasChildren: true,
address: "No. 189, Grove St, Los Angeles",
},
{
id: 4,
date: "2016-05-03",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
];
load 方法
const load = (row, treeNode, resolve) => {
// 模拟请求后端数据
setTimeout(() => {
resolve([
{
id: 31,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
{
id: 32,
date: "2016-05-01",
name: "wangxiaohu",
address: "No. 189, Grove St, Los Angeles",
},
]);
}, 1000);
};
表格使用的地方
<MxeTableVue :data="tableData" :columns="columns" show-summary />
列配置
const columns = [
{
label: "ID",
prop: "id",
},
{
label: "Name",
prop: "name",
},
{
label: "Amount 1",
prop: "amount1",
sortable: true,
},
{
label: "Amount 2",
prop: "amount2",
sortable: true,
},
{
label: "Amount 3",
prop: "amount3",
sortable: true,
},
];
tableData 数据
const tableData = [
{
id: "12987122",
name: "Tom",
amount1: "234",
amount2: "3.2",
amount3: 10,
},
{
id: "12987123",
name: "Tom",
amount1: "165",
amount2: "4.43",
amount3: 12,
},
{
id: "12987124",
name: "Tom",
amount1: "324",
amount2: "1.9",
amount3: 9,
},
{
id: "12987125",
name: "Tom",
amount1: "621",
amount2: "2.2",
amount3: 17,
},
{
id: "12987126",
name: "Tom",
amount1: "539",
amount2: "4.1",
amount3: 15,
},
];
表格使用的地方
<MxeTableVue
:data="tableData"
:columns="columns"
:span-method="arraySpanMethod"
border
/>
列配置
const columns = [
{
label: "ID",
prop: "id",
},
{
label: "Name",
prop: "name",
},
{
label: "Amount 1",
prop: "amount1",
},
{
label: "Amount 2",
prop: "amount2",
},
{
label: "Amount 3",
prop: "amount3",
},
];
?tableData 表格数据
const tableData = [
{
id: "12987122",
name: "Tom",
amount1: "234",
amount2: "3.2",
amount3: 10,
},
{
id: "12987123",
name: "Tom",
amount1: "165",
amount2: "4.43",
amount3: 12,
},
{
id: "12987124",
name: "Tom",
amount1: "324",
amount2: "1.9",
amount3: 9,
},
{
id: "12987125",
name: "Tom",
amount1: "621",
amount2: "2.2",
amount3: 17,
},
{
id: "12987126",
name: "Tom",
amount1: "539",
amount2: "4.1",
amount3: 15,
},
];
表格使用的地方
// 注意这里total 要根据实际数据来,这里写死800只是为了展示而已
<MxeTableVue
:data="tableData"
:columns="columns"
v-model:pageIndex="page.pageIndex"
v-model:pageSize="page.pageSize"
:total="800"
@getList="getList"
/>
?列配置
const columns = [
{
label: "ID",
prop: "id",
},
{
label: "Name",
prop: "name",
},
{
label: "Amount 1",
prop: "amount1",
},
{
label: "Amount 2",
prop: "amount2",
},
{
label: "Amount 3",
prop: "amount3",
},
];
tableData 表格数据
const tableData = [
{
id: "12987122",
name: "Tom",
amount1: "234",
amount2: "3.2",
amount3: 10,
},
{
id: "12987123",
name: "Tom",
amount1: "165",
amount2: "4.43",
amount3: 12,
},
{
id: "12987124",
name: "Tom",
amount1: "324",
amount2: "1.9",
amount3: 9,
},
{
id: "12987125",
name: "Tom",
amount1: "621",
amount2: "2.2",
amount3: 17,
},
{
id: "12987126",
name: "Tom",
amount1: "539",
amount2: "4.1",
amount3: 15,
},
];
封装的这个表格,基本可以覆盖 element-plus 官网,所有表格使用demo, 所有可以放到 el-table 的属性方法都可以放到?MxeTableVue 组件上,所有可以放到 el-column 的属性, 都可以放到列表配置中的每个对象上。
?
mxe-table.vue组件 (解释上面使用的时候是 MxeTableVue 加了个Vue后缀是因为,项目组要求与普通Html做区分,所以在引入组件的时候是这样引入的 import MxeTableVue? from 'xx/xxx/xx')
<script setup>
import { ref, computed } from "vue";
import MxeTableColumn from "./mxe-table-column.vue";
const props = defineProps({
data: {
type: Array,
default: () => [],
},
columns: {
type: Array,
default: () => [],
},
pageIndex: {
type: Number,
},
pageSize: {
type: Number,
},
total: {
type: Number,
},
});
const emits = defineEmits(["update:pageIndex", "update:pageSize", "getList"]);
const page = ref({
pageIndex: computed({
get: () => props.pageIndex,
set(pageIndex) {
emits("update:pageIndex", pageIndex);
},
}),
pageSize: computed({
get: () => props.pageSize,
set(pageSize) {
emits("update:pageSize", pageSize);
},
}),
});
const handleSizeChange = () => {
page.value.pageIndex = 1;
emits("getList");
};
</script>
<template>
<!-- v-bind="$attrs" 将不被props接收的参数都绑定到 el-table -->
<div class="table-and-pager">
<div class="table-box">
<el-table :data="data" style="width: 100%; height: 100%" v-bind="$attrs">
<MxeTableColumn :columns="columns">
<!-- 插槽透传, 不然, 如果是多级表头, 里层接收不到 -->
<!-- $slots 是所有传进来的插槽的信息 -->
<template
v-for="name in Object.keys($slots)"
:key="name"
#[name]="scope"
>
<slot :name="name" v-bind="scope" />
</template>
</MxeTableColumn>
<template #empty>
<!-- 给一个空组件 -->
<div>空空如也{{ $slots }}</div>
</template>
</el-table>
</div>
<div class="pager-box" v-if="props.pageIndex && props.pageSize">
<el-pagination
v-model:current-page="page.pageIndex"
v-model:page-size="page.pageSize"
:page-sizes="[100, 200, 300, 400]"
layout="total, prev, pager, next, sizes, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="emits('getList')"
/>
</div>
</div>
</template>
<style scoped lang="less">
.table-and-pager {
width: 100%;
height: 100%;
.table-box {
width: 100%;
height: calc(100% - 50px);
// 当有表位有合计行时, 改变其背景颜色, 使用与表格主体颜色统一一点
:deep(.el-table tfoot td.el-table__cell) {
background: #fff;
}
}
.pager-box {
width: 100%;
height: 50px;
display: flex;
justify-content: flex-end;
align-items: center;
}
}
</style>
mxe-table-column.vue
<script setup>
import { omit } from "lodash-es";
const props = defineProps({
columns: {
type: Array,
default: () => [],
},
});
</script>
<template>
<el-table-column
v-for="column in columns"
v-bind="omit(column, ['children'])"
>
<template #default="scope">
<slot
v-if="column?.slots?.default && !column.children?.length"
:name="column.slots.default"
v-bind="scope"
/>
<template v-else-if="column.children?.length">
<!-- 递归调用, .vue文件名 是非index的,可以直接使用文件名调用自己 -->
<MxeTableColumn :columns="column.children">
<template
v-for="name in Object.keys($slots)"
:key="name"
#[name]="scope"
>
<slot :name="name" v-bind="scope" />
</template>
</MxeTableColumn>
</template>
</template>
<template #header="scope">
<slot
v-if="column?.slots?.header"
:name="column.slots.header"
v-bind="scope"
/>
</template>
</el-table-column>
</template>
<style scoped></style>
????????好了,这就是基本所有内容了,欢迎各位大佬批评指正,讨论交流,如能对此提出更好的优化意见就再好不过了,后续有时间,也会结合项目实践,继续优化,扩展。