Element-UI组件高级技术教程
上一章节我们学习了Element-UI的布局结构以及Form表单元素,今天来学习显示数据的table,pagination以及tree组件。
15.1 Data组件
Data组件的本质就是为了显示多条数据,同时可对数据进行筛选、排序、对比和其他自定义操作。常用的Data组件有Table,Pagination以及Tree组件。
15.1.1 Table表格
1、基础表格
当el-table元素中注入data对象数组后,在el-table-column中用prop属性来对应对象中的键名即可填入数据,用label属性来定义表格的列名。可以使用width属性来定义列宽。
示例代码如下:
<template>
<div id="app">
<el-table :data="tableData" style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄",
},
],
};
},
};
</script>
<style lang="" scoped>
</style>
代码运行,效果图下图:
图 15- 1 基础表格效果图
2、 带斑马纹表格
使用带斑马纹的表格,可以更容易区分出不同行的数据。stripe属性可以创建带斑马纹的表格。它接受一个Boolean,默认为false,设置为true即为启用。
核心代码如下:
<template>
<div id="app">
<el-table :data="tableData" style="width: 100%" stripe>
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
</div>
</template>
代码运行,效果如下图:
图 15- 2 带斑马纹效果
3、 带边框表格
默认情况下,Table 组件是不具有竖直方向的边框的,如果需要,可以使用border属性,它接受一个Boolean,设置为true即可启用。
核心代码如下:
<el-table :data="tableData" style="width: 100%" stripe border>
运行代码,效果如下图:
图 15- 3 带竖直边框的效果
4、 带状态表格
可将表格内容 highlight 显示,方便区分「成功、信息、警告、危险」等内容。可以通过指定 Table 组件的 row-class-name 属性来为 Table 中的某一行添加 class,表明该行处于某种状态。
核心代码如下:
<template>
<el-table
:data="tableData"
style="width: 100%"
:row-class-name="tableRowClassName">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</template>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
<script>
export default {
methods: {
tableRowClassName({row, rowIndex}) {
if (rowIndex === 1) {
return 'warning-row';
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
}
},
data() {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄',
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}]
}
}
}
</script>
代码运行,效果如下图:
图 15- 4 带状态效果
5、 固定表头
纵向内容过多时,可选择固定表头。只要在el-table元素中定义了height属性,即可实现固定表头的表格,而不需要额外的代码。height指的是内容是table显示内容得高度。
核心代码:
<el-table :data="tableData" height="300" border style="width: 100%">
<el-table-column prop="date" label="日期" width="180"> </el-table-column>
<el-table-column prop="name" label="姓名" width="180"> </el-table-column>
<el-table-column prop="address" label="地址"> </el-table-column>
</el-table>
运行程序,效果如下图:
图 15- 5 固定表头效果
6、 固定列
横向内容过多时,可选择固定列。
固定列需要使用fixed属性,它接受 Boolean 值或者left,right,表示左边固定还是右边固定。
核心代码:
<el-table-column fixed prop="date" label="日期" width="150">
</el-table-column>
<el-table-column fixed="right" label="操作" width="100">
<template slot-scope="scope">
<el-button @click="handleClick(scope.row)" type="text" size="small"
>查看</el-button
>
<el-button type="text" size="small">编辑</el-button>
</template>
</el-table-column>
代码运行,效果如下图:
图 15- 6 固定列效果图
7、 固定表头和列
横纵内容过多时,可选择固定列和表头。固定列和表头可以同时使用,只需要将上述两个属性分别设置好即可。
核心代码:
<el-table :data="tableData" border style="width: 100%" height="250">
<el-table-column fixed prop="date" label="日期" width="150">
</el-table-column>
.
.
.
.
</el-table>
8、 流体高度
当数据量动态变化时,可以为 Table 设置一个最大高度。通过设置max-height属性为 Table 指定最大高度。此时若表格所需的高度大于最大高度,则会显示一个滚动条。
9、 多级表头
数据结构比较复杂的时候,可使用多级表头来展现数据的层次关系。只需要在 el-table-column 里面嵌套 el-table-column,就可以实现多级表头。
核心代码:
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
width="150">
</el-table-column>
<el-table-column label="配送信息">
<el-table-column
prop="name"
label="姓名"
width="120">
</el-table-column>
<el-table-column label="地址">
<el-table-column
prop="province"
label="省份"
width="120">
</el-table-column>
<el-table-column
prop="city"
label="市区"
width="120">
</el-table-column>
<el-table-column
prop="address"
label="地址"
width="300">
</el-table-column>
<el-table-column
prop="zip"
label="邮编"
width="120">
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
程序运行,效果如下图:
图 15- 7 多级表头效果
10、 单选
选择单行数据时使用色块表示。Table 组件提供了单选的支持,只需要配置highlight-current-row属性即可实现单选。之后由current-change事件来管理选中时触发的事件,它会传入currentRow,oldCurrentRow。如果需要显示索引,可以增加一列el-table-column,设置type属性为index即可显示从 1 开始的索引号。
核心代码:
<template>
<div id="app">
<el-table
ref="singleTable"
:data="tableData"
highlight-current-row
@current-change="handleCurrentChange"
style="width: 100%"
>
<el-table-column type="index" width="50"> </el-table-column>
<el-table-column property="date" label="日期" width="120">
</el-table-column>
<el-table-column property="name" label="姓名" width="120">
</el-table-column>
<el-table-column property="address" label="地址"> </el-table-column>
</el-table>
<div style="margin-top: 20px">
<el-button @click="setCurrent(tableData[1])">选中第二行</el-button>
<el-button @click="setCurrent()">取消选择</el-button>
</div>
</div>
</template>
<style scoped>
.el-table .warning-row {
background: red;
}
.el-table .success-row {
background: green;
}
</style>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1518 弄",
zip: 200333,
},
{
date: "2016-05-04",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1519 弄",
zip: 200333,
},
{
date: "2016-05-03",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1516 弄",
zip: 200333,
},
],
currentRow: null,
};
},
methods: {
setCurrent(row) {
//setCurrentRow是用来设置选中行得方法,传过来得是行对象
this.$refs.singleTable.setCurrentRow(row);
},
handleCurrentChange(val) {
this.currentRow = val;
},
},
};
</script>
程序运行,效果如下图:
图 15- 8 单选效果图
11、 多选
选择多行数据时使用 Checkbox。实现多选非常简单: 手动添加一个el-table-column,设type属性为selection即可;默认情况下若内容过多会折行显示,若需要单行显示可以使用show-overflow-tooltip属性,它接受一个Boolean,为true时多余的内容会在 hover 时以 tooltip 的形式显示出来。
核心代码:
<template>
<div id="app">
<el-table
ref="multipleTable"
:data="tableData"
style="width: 600px"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column label="日期" width="120">
<template slot-scope="scope">{{ scope.row.date }}</template>
</el-table-column>
<el-table-column prop="name" label="姓名" width="120"> </el-table-column>
<el-table-column prop="address" label="地址" show-overflow-tooltip>
</el-table-column>
<el-table-column prop="province" label="省份" width="120">
</el-table-column>
<el-table-column prop="city" label="城市" width="120"> </el-table-column>
</el-table>
<div style="margin-top: 20px">
<el-button @click="toggleSelection([tableData[1], tableData[2]])"
>切换第二、第三行的选中状态</el-button
>
<el-button @click="toggleSelection()">取消选择</el-button>
</div>
</div>
</template>
<style scoped>
.el-table .warning-row {
background: red;
}
.el-table .success-row {
background: green;
}
</style>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1518 弄",
zip: 200333,
},
{
date: "2016-05-04",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1519 弄",
zip: 200333,
},
{
date: "2016-05-03",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1516 弄",
zip: 200333,
},
],
multipleSelection: [],
};
},
methods: {
toggleSelection(rows) {
if (rows) {
rows.forEach((row) => {
//toggleRowSelection设置选中行
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
//clearSelection清楚选中
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
},
};
</script>
程序运行,效果如下图:
图 15- 9 多选效果
不设置show-overflow-tooltip的效果:
图 15- 10 多行的效果
12、 排序
对表格进行排序,可快速查找或对比数据。在列中设置sortable属性即可实现以该列为基准的排序,接受一个Boolean,默认为false。可以通过 Table 的default-sort属性设置默认的排序列和排序顺序。可以使用sort-method或者sort-by使用自定义的排序规则。如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-change事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。在本例中,我们还使用了formatter属性,它用于格式化指定列的值,接受一个Function,会传入两个参数:row和column,可以根据自己的需求进行处理。
核心代码如下:
<template>
<div id="app">
<el-table
:data="tableData"
style="width: 100%"
:default-sort="{ prop: 'date', order: 'descending' }"
>
<el-table-column prop="date" label="日期" sortable width="180">
</el-table-column>
<el-table-column prop="name" label="姓名" sortable width="180">
</el-table-column>
<el-table-column prop="address" label="地址" :formatter="formatter">
</el-table-column>
</el-table>
</div>
</template>
<style scoped>
.el-table .warning-row {
background: red;
}
.el-table .success-row {
background: green;
}
</style>
<script>
export default {
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1518 弄",
zip: 200333,
},
{
date: "2016-05-04",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1519 弄",
zip: 200333,
},
{
date: "2016-05-03",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1516 弄",
zip: 200333,
},
],
multipleSelection: [],
};
},
methods: {
formatter(row, column) {
return row.address + "=====";
},
},
};
</script>
程序运行,效果如下图:
图 15- 11 排序效果
13、 筛选
对表格进行筛选,可快速查找到自己想看的数据。在列中设置filters,filter-method属性即可开启该列的筛选,filters 是一个数组,filter-method是一个方法,它用于决定某些数据是否显示,会传入三个参数:value, row 和 column。
核心代码如下:
<template>
<div id="app">
<el-button @click="resetDateFilter">清除日期过滤器</el-button>
<el-button @click="clearFilter">清除所有过滤器</el-button>
<el-table
ref="filterTable"
:data="tableData"
style="width: 100%"
:default-sort="{ prop: 'date', order: 'descending' }"
>
<el-table-column
prop="date"
label="日期"
sortable
column-key="date"
width="180"
:filters="dateAry"
:filter-method="filterHandler"
>
</el-table-column>
<el-table-column prop="name" label="姓名" sortable width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址"
:formatter="formatter"
column-key="address"
:filters="[{ text: 'AAA', value: 'AAA' }]"
:filter-method="filterAddr"
>
</el-table-column>
</el-table>
</div>
</template>
<style scoped>
.el-table .warning-row {
background: red;
}
.el-table .success-row {
background: green;
}
</style>
<script>
export default {
name: "App",
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1518 弄",
zip: 200333,
},
{
date: "2016-05-04",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1517 弄",
zip: 200333,
},
{
date: "2016-05-01",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市AAA普陀区金沙江路 1519 弄",
zip: 200333,
},
{
date: "2016-05-03",
name: "王小虎",
province: "上海",
city: "普陀区",
address: "上海市普陀区金沙江路 1516 弄",
zip: 200333,
},
],
dateAry: [
{ 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" },
],
};
},
methods: {
resetDateFilter() {
this.$refs.filterTable.clearFilter("date");
},
clearFilter() {
this.$refs.filterTable.clearFilter();
},
formatter(row, column) {
return row.address + "=========";
},
filterHandler(value, row, column) {
const property = column["property"];
return row[property] === value;
},
filterAddr(value, row, column) {
const property = column["property"];
console.log(22222222222, value);
console.log(111111111111, row[property]);
console.log(row[property].includes(value));
return row[property].includes(value);
},
},
};
</script>
程序运行,效果如下图:
图 15- 12 筛选效果图
从上例中可以看出,如果想要对一个列进行筛选,必须加三个元素:column-key,filters
,filter-method,其中column-key是用来给筛选器起名字的,方便后期删除该筛选器。
14、 自定义列模板
自定义列的显示内容,可组合其他组件使用。通过 Scoped slot 可以获取到 row, column, $index 和 store(table 内部的状态管理)的数据,用法参考如下代码。
<template>
<div id="app">
<el-table :data="tableData" style="width: 100%">
<el-table-column label="日期" width="180">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column label="姓名" width="180">
<template slot-scope="scope">
<el-popover trigger="hover" placement="top">
<p>姓名: {{ scope.row.name }}</p>
<p>住址: {{ scope.row.address }}</p>
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{ scope.row.name }}</el-tag>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
>编辑</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
<style scoped>
.el-table .warning-row {
background: red;
}
.el-table .success-row {
background: green;
}
</style>
<script>
export default {
name: "App",
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎",
address: "上海市普陀区金沙江路 1516 弄",
},
],
};
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
},
},
};
</script>
程序运行,效果如下图:
图 15- 13 自定义列模板效果图
15、 展开行
当行内容过多并且不想显示横向滚动条时,可以使用 Table 展开行功能。通过设置 type="expand" 和 Scoped slot 可以开启展开行功能,el-table-column 的模板会被渲染成为展开行的内容,展开行可访问的属性与使用自定义列模板时的 Scoped slot 相同。
<template>
<div id="app">
<el-table :data="tableData" style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="商品名称">
<span>{{ props.row.name }}</span>
</el-form-item>
<el-form-item label="所属店铺">
<span>{{ props.row.shop }}</span>
</el-form-item>
<el-form-item label="商品 ID">
<span>{{ props.row.id }}</span>
</el-form-item>
<el-form-item label="店铺 ID">
<span>{{ props.row.shopId }}</span>
</el-form-item>
<el-form-item label="商品分类">
<span>{{ props.row.category }}</span>
</el-form-item>
<el-form-item label="店铺地址">
<span>{{ props.row.address }}</span>
</el-form-item>
<el-form-item label="商品描述">
<span>{{ props.row.desc }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column label="商品 ID" prop="id"> </el-table-column>
<el-table-column label="商品名称" prop="name"> </el-table-column>
<el-table-column label="描述" prop="desc"> </el-table-column>
</el-table>
</div>
</template>
<style>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
</style>
<script>
export default {
name: "App",
data() {
return {
tableData: [
{
id: "12987122",
name: "好滋好味鸡蛋仔",
category: "江浙小吃、小吃零食",
desc: "荷兰优质淡奶,奶香浓而不腻",
address: "上海市普陀区真北路",
shop: "王小虎夫妻店",
shopId: "10333",
},
{
id: "12987123",
name: "好滋好味鸡蛋仔",
category: "江浙小吃、小吃零食",
desc: "荷兰优质淡奶,奶香浓而不腻",
address: "上海市普陀区真北路",
shop: "王小虎夫妻店",
shopId: "10333",
},
{
id: "12987125",
name: "好滋好味鸡蛋仔",
category: "江浙小吃、小吃零食",
desc: "荷兰优质淡奶,奶香浓而不腻",
address: "上海市普陀区真北路",
shop: "王小虎夫妻店",
shopId: "10333",
},
{
id: "12987126",
name: "好滋好味鸡蛋仔",
category: "江浙小吃、小吃零食",
desc: "荷兰优质淡奶,奶香浓而不腻",
address: "上海市普陀区真北路",
shop: "王小虎夫妻店",
shopId: "10333",
},
],
};
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
},
},
};
</script>
程序运行,效果如下图:
图 15- 14 展开行效果图
16、 自定义表头
通过设置 Scoped slot 来自定义表头。核心代码如下:
<template>
<div id="app">
<el-table
:data="
tableData.filter((data) =>
data.name.toLowerCase().includes(search.toLowerCase())
)
"
style="width: 100%"
>
<el-table-column label="Date" prop="date"> </el-table-column>
<el-table-column label="Name" prop="name"> </el-table-column>
<el-table-column align="right">
<template slot="header" slot-scope="scope">
<el-input v-model="search" size="mini" placeholder="输入关键字搜索" />
</template>
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
>Edit</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>Delete</el-button
>
</template>
</el-table-column>
</el-table>
</div>
</template>
<style>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
</style>
<script>
export default {
name: "App",
data() {
return {
tableData: [
{
date: "2016-05-02",
name: "王小虎",
address: "上海市普陀区金沙江路 1518 弄",
},
{
date: "2016-05-04",
name: "王小虎",
address: "上海市普陀区金沙江路 1517 弄",
},
{
date: "2016-05-01",
name: "王小虎",
address: "上海市普陀区金沙江路 1519 弄",
},
{
date: "2016-05-03",
name: "王小虎4",
address: "上海市普陀区金沙江路 1516 弄",
},
],
search: "",
};
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
},
},
};
</script>
程序运行,效果如下图:
图 15- 15 自定义表头
15.1.2 Pagination分页
当数据量过多时,使用分页分解数据。
1. 基础用法
设置layout,表示需要显示的内容,用逗号分隔,布局元素会依次显示。prev表示上一页,next为下一页,pager表示页码列表,除此以外还提供了jumper和total,size和特殊的布局符号->,->后的元素会靠右显示,jumper表示跳页元素,total表示总条目数,size用于设置每页显示的页码数量。默认size是10.
核心代码如下:
<template>
<div id="app">
<div class="block">
<span class="demonstration">页数较少时的效果</span>
<el-pagination layout="prev, pager, next" :total="50"> </el-pagination>
</div>
<div class="block">
<span class="demonstration">大于 7 页时的效果</span>
<el-pagination layout="prev, pager, next,jumper" :total="1000">
</el-pagination>
</div>
</div>
</template>
<style>
</style>
<script>
export default {};
</script>
运行代码,效果如下图:
图 15- 16 分页效果
2. 设置最大页码数
默认情况下,当总页数超过 7 页时,Pagination 会折叠多余的页码按钮。通过pager-count属性可以设置最大页码按钮数。
核心代码如下:
<el-pagination
:page-size="20"
:pager-count="11"
layout="prev, pager, next"
:total="1000">
</el-pagination>
运行代码,效果如下图:
图 15- 17 设置最大页码数效果图
3. 带背景色分页
设置background属性可以为分页按钮添加背景色。
核心代码如下:
<el-pagination background layout="prev, pager, next" :total="1000">
运行代码,效果如下图:
图 15- 18 带背景效果图
4. 小型分页
在空间有限的情况下,可以使用简单的小型分页。只需要一个small属性,它接受一个Boolean,默认为false,设为true即可启用。
核心代码如下:
<el-pagination
small
layout="prev, pager, next"
:total="50">
运行代码,效果如下图:
图 15- 19 小型分页
5. 附加功能
根据场景需要,可以添加其他功能模块。
此例是一个完整的用例,使用了size-change和current-change事件来处理页码大小和当前页变动时候触发的事件。page-sizes接受一个整型数组,数组元素为展示的选择每页显示个数的选项,[100, 200, 300, 400]表示四个选项,每页显示 100 个,200 个,300 个或者 400 个。
核心代码如下:
<template>
<div id="app">
<div class="block">
<span class="demonstration">显示总数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage1"
:page-size="100"
layout="total, prev, pager, next"
:total="1000"
>
</el-pagination>
</div>
<div class="block">
<span class="demonstration">调整每页显示条数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage2"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="sizes, prev, pager, next"
:total="1000"
>
</el-pagination>
</div>
<div class="block">
<span class="demonstration">直接前往</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage3"
:page-size="100"
layout="prev, pager, next, jumper"
:total="1000"
>
</el-pagination>
</div>
<div class="block">
<span class="demonstration">完整功能</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400"
>
</el-pagination>
</div>
</div>
</template>
<style>
</style>
<script>
export default {
methods: {
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
},
},
data() {
return {
currentPage1: 5,
currentPage2: 5,
currentPage3: 5,
currentPage4: 4,
};
},
};
</script>
运行代码,效果如下图:
图 15- 20 附加功能效果图
6. 只有一页时隐藏分页
当只有一页时,通过设置 hide-on-single-page 属性来隐藏分页。
核心代码如下:
<div>
<el-switch v-model="value">
</el-switch>
<el-pagination
:hide-on-single-page="value"
:total="5"
layout="prev, pager, next">
</el-pagination>
</div>
运行代码:效果图如下:
15.1.3 Tree树形控件
1、默认展开和默认选中
分别通过default-expanded-keys和default-checked-keys设置默认展开和默认选中的节点。需要注意的是,此时必须设置node-key,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的。
<template>
<div id="app">
<el-tree
:data="data"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]"
:props="defaultProps"
>
</el-tree>
</div>
</template>
<style>
</style>
<script>
export default {
data() {
return {
data: [
{
id: 1,
label: "一级 1",
children: [
{
id: 4,
label: "二级 1-1",
children: [
{
id: 9,
label: "三级 1-1-1",
},
{
id: 10,
label: "三级 1-1-2",
},
],
},
],
},
{
id: 2,
label: "一级 2",
children: [
{
id: 5,
label: "二级 2-1",
},
{
id: 6,
label: "二级 2-2",
},
],
},
{
id: 3,
label: "一级 3",
children: [
{
id: 7,
label: "二级 3-1",
},
{
id: 8,
label: "二级 3-2",
},
],
},
],
defaultProps: {
children: "children",
label: "label",
},
};
},
};
</script>
运行代码:效果图如下:
图 15- 21 树形效果
2、 禁用状态
可将 Tree 的某些节点设置为禁用状态。通过disabled设置禁用状态。
核心代码如下:
运行代码,效果如下图:
图 15- 22 禁用效果图
3、 树节点的选择
本例展示如何获取和设置选中节点。获取和设置各有两种方式:通过 node 或通过 key。如果需要通过 key 来获取或设置,则必须设置node-key。
运行代码,效果如下图:
<template>
<div id="app">
<el-tree
:data="data"
show-checkbox
default-expand-all
node-key="id"
ref="tree"
highlight-current
:props="defaultProps"
>
</el-tree>
<div class="buttons">
<el-button @click="getCheckedNodes">通过 node 获取</el-button>
<el-button @click="getCheckedKeys">通过 key 获取</el-button>
<el-button @click="setCheckedNodes">通过 node 设置</el-button>
<el-button @click="setCheckedKeys">通过 key 设置</el-button>
<el-button @click="resetChecked">清空</el-button>
</div>
</div>
</template>
<style>
</style>
<script>
export default {
data() {
return {
data: [
{
id: 1,
label: "一级 1",
children: [
{
id: 4,
label: "二级 1-1",
children: [
{
id: 9,
label: "三级 1-1-1",
},
{
id: 10,
label: "三级 1-1-2",
},
],
},
],
},
{
id: 2,
label: "一级 2",
children: [
{
id: 5,
label: "二级 2-1",
},
{
id: 6,
label: "二级 2-2",
},
],
},
{
id: 3,
label: "一级 3",
children: [
{
id: 7,
label: "二级 3-1",
},
{
id: 8,
label: "二级 3-2",
},
],
},
],
defaultProps: {
children: "children",
label: "label",
},
};
},
methods: {
getCheckedNodes() {
//获取选中的节点
console.log(this.$refs.tree.getCheckedNodes());
},
getCheckedKeys() {
//获取选中的菜单的id
console.log(this.$refs.tree.getCheckedKeys());
},
setCheckedNodes() {
//设置选中的节点
this.$refs.tree.setCheckedNodes([
{
id: 5,
label: "二级 2-1",
},
{
id: 9,
label: "三级 1-1-1",
},
]);
},
//设置选中的菜单的id
setCheckedKeys() {
this.$refs.tree.setCheckedKeys([3]);
},
//重置所有选中的菜单
resetChecked() {
this.$refs.tree.setCheckedKeys([]);
},
},
};
</script>
图 15- 23 获取或者设置节点
15.2实践案例应用
15.2.1 目的和效果
目的
1. 掌握element-ui的布局;
2. 掌握菜单的使用;
3. 掌握table组件的使用;
4. 掌握分页组件;
5. 掌握与后台交互的增删改查;
效果
图 15- 24 布局效果
图 15- 25 带条件的分页查询效果
图 15- 26 修改效果
15.2.2 实现步骤
第一步:建立数据源
DROP TABLE IF EXISTS `classinfo`;
CREATE TABLE `classinfo` (
`ClassID` int(11) NOT NULL AUTO_INCREMENT,
`ClassName` varchar(9) NOT NULL DEFAULT '',
`BeginTime` datetime NOT NULL,
`EndTime` datetime DEFAULT NULL,
`GradeID` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ClassID`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8 COMMENT='班级表';
-- ----------------------------
-- Records of classinfo
-- ----------------------------
INSERT INTO `classinfo` VALUES ('1', 'S101', '2011-05-07 00:00:00', '2011-09-10 00:00:00', '1');
INSERT INTO `classinfo` VALUES ('4', 'S103', '2011-05-20 00:00:00', '2011-10-10 00:00:00', '1');
INSERT INTO `classinfo` VALUES ('5', 'Y201', '2011-05-05 00:00:00', '2011-12-01 00:00:00', '2');
INSERT INTO `classinfo` VALUES ('7', 'S210', '2011-03-11 00:00:00', '2011-09-11 00:00:00', '2');
INSERT INTO `classinfo` VALUES ('8', 'A139', '2011-04-01 00:00:00', '2012-03-10 00:00:00', '3');
INSERT INTO `classinfo` VALUES ('9', 'S103', '2011-05-20 00:00:00', '2011-10-10 00:00:00', '1');
INSERT INTO `classinfo` VALUES ('10', 'A130', '2019-06-27 16:48:24', '2019-06-27 16:48:24', '1');
INSERT INTO `classinfo` VALUES ('11', 'A131', '2019-06-27 16:59:14', '2019-06-27 16:59:14', '3');
INSERT INTO `classinfo` VALUES ('12', 'A139', '2021-07-23 17:13:58', '2016-07-22 17:13:58', '3');
INSERT INTO `classinfo` VALUES ('18', 'A134', '2019-07-27 11:15:27', '2019-07-27 11:15:27', '3');
INSERT INTO `classinfo` VALUES ('20', 'A136', '2019-07-26 21:22:38', '2019-07-26 21:22:38', '1');
INSERT INTO `classinfo` VALUES ('21', 'SSSAAA', '2019-08-08 13:28:21', '2019-07-01 10:06:00', '3');
INSERT INTO `classinfo` VALUES ('22', 'hello', '2019-08-08 13:33:26', '2019-07-01 10:06:00', '1');
INSERT INTO `classinfo` VALUES ('24', 'A140', '2019-08-15 15:21:36', '2021-08-20 15:21:36', '1');
INSERT INTO `classinfo` VALUES ('32', 'AAA', '2019-08-11 20:54:53', '2019-08-11 20:54:53', '1');
INSERT INTO `classinfo` VALUES ('33', 'A126', '2019-08-11 20:58:21', '2019-08-11 20:58:21', '1');
INSERT INTO `classinfo` VALUES ('34', 'A156', '2019-05-06 00:00:00', '2021-05-06 00:00:00', '2');
INSERT INTO `classinfo` VALUES ('35', 'A156', '2019-05-06 00:00:00', '2021-05-06 00:00:00', '2');
DROP TABLE IF EXISTS `stus`;
CREATE TABLE `stus` (
`stu_id` int(11) NOT NULL AUTO_INCREMENT,
`stu_name` varchar(50) DEFAULT NULL,
`stu_sex` char(2) DEFAULT '1',
`stu_birth` date DEFAULT NULL,
`stu_class_id` int(11) DEFAULT NULL,
`stu_pic` varchar(100) DEFAULT NULL,
`stu_hob` varchar(100) DEFAULT NULL,
PRIMARY KEY (`stu_id`),
KEY `fk_class_id` (`stu_class_id`),
CONSTRAINT `fk_class_id` FOREIGN KEY (`stu_class_id`) REFERENCES `classinfo` (`ClassID`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of stus
-- ----------------------------
INSERT INTO `stus` VALUES ('1', '武松', '1', '2021-08-22', '1', '1619261999138.png', '唱歌,跳舞,看书');
INSERT INTO `stus` VALUES ('3', '杨幂', '2', '2021-08-03', '8', '1619261999138.png', '唱歌,跳舞');
INSERT INTO `stus` VALUES ('4', '刘恺威', '1', '2021-08-22', '8', '1619261999138.png', '唱歌');
INSERT INTO `stus` VALUES ('5', '葛优', '1', '2021-08-18', '5', '1619261999138.png', '跳舞');
INSERT INTO `stus` VALUES ('6', '袁隆平', '1', '2021-08-22', '9', '1619261999138.png', '唱歌');
INSERT INTO `stus` VALUES ('7', '张宏文', '1', '2021-08-22', '5', '1619261999138.png', '跳舞');
第二步:建立node后台
const router = require('koa-router')()
const db = require('../db_config.js');
const moment = require('moment');
const multer = require('koa-multer')
const path = require('path');
router.prefix('/stus')
//设置上传
let storage = multer.diskStorage({
destination: path.resolve('public/images'),
filename: (ctx, file, cb) => {
let num = file.originalname.lastIndexOf('.');
let suffix = file.originalname.substring(num);
cb(null, Date.now() + suffix);
}
});
let fileFilter = (ctx, file, cb) => {
//过滤上传的后缀为txt的文件
let num = file.originalname.lastIndexOf('.');
let suffix = file.originalname.substring(num);
if (!suffix in ['.jpg', '.png', '.jpeg', '.gif']) {
cb(null, false);
} else {
cb(null, true);
}
}
let upload = multer({ storage: storage, fileFilter: fileFilter });
router.get('/', async (ctx) => {
try {
let sql = `select stu_id,stu_name,stu_sex,stu_pic,stu_birth,stu_hob,c.ClassID,c.ClassName from stus s inner join classinfo c on s.stu_class_id = c.ClassID`;
let stus = await db(sql, []);
// status 是否成功的状态 0 成功 1 失败
ctx.body = {
status: 0,
message: stus
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
})
// //删除 get
router.get('/toDel/:stu_id', async (ctx, next) => {
try {
let { stu_id } = ctx.params;
let sql = "delete from stus where stu_id = ?";
let result = await db(sql, [stu_id]);
let rows = result.affectedRows;
if (rows > 0) {
ctx.body = {
status: 0,
message: rows
}
} else {
ctx.body = {
status: 1,
message: rows
}
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
})
router.post('/updateStu', upload.single('pic'), async (ctx) => {
let { stu_id, stu_name, stu_sex, stu_birth, stu_class_id, stu_hob, stu_pic } = ctx.req.body;
if (ctx.req.file !== undefined) {
stu_pic = ctx.req.file.filename;
}
let sql = "update stus set stu_name = ?,stu_sex=?,stu_birth=?,stu_pic=? ,stu_class_id=?,stu_hob=? where stu_id = ?";
let pms = [stu_name, stu_sex, stu_birth, stu_pic, stu_class_id, stu_hob, stu_id];
try {
let result = await db(sql, pms);
let rows = result.affectedRows;
if (rows > 0) {
ctx.body = {
status: 0,
message: rows
}
} else {
ctx.body = {
status: 1,
message: rows
}
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
});
router.get('/toAdd', async ctx => {
try {
let sql = "select classId,classname from classinfo";
let cs = await sqlQuery(sql, []);
ctx.body = {
status: 0,
message: cs
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
});
router.post('/addStu', upload.single('pic'), async ctx => {
let { stu_name, stu_sex, stu_birth, stu_class_id, stu_hob } = ctx.request.body;
let pic = ctx.req.file.filename;
try {
let sql = "insert into stus(stu_name,stu_sex,stu_birth,stu_class_id,stu_hob,stu_pic) values(?,?,?,?,?,?)";
let pms = [stu_name, stu_sex, stu_birth, stu_class_id, stu_hob, pic];
let result = await db(sql, pms);
let rows = result.affectedRows;
if (rows > 0) {
ctx.body = {
status: 0,
message: rows
}
} else {
ctx.body = {
status: 1,
message: rows
}
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
});
router.get('/csinfo', async (ctx) => {
try {
let sql = `select classId,classname from classinfo`;
let csinfo = await db(sql, []);
// status 是否成功的状态 0 成功 1 失败
ctx.body = {
status: 0,
message: csinfo
}
} catch (error) {
ctx.body = {
status: 1,
message: error
}
}
})
module.exports = router
第三步:实现查询
基本布局
在App.vue中使用布局容器,把页面分成合理结构;在左侧栏中加入导航菜单,在菜单的第一项使用路由导航,点击到达学生管理界面。
核心代码:App.vue
<template>
<div id="app">
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
>
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>基础数据</span>
</template>
<el-menu-item-group>
<el-menu-item index="1-1">
<router-link to="/stus">学生管理</router-link>
</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
<el-menu-item index="1-3">选项3</el-menu-item>
<el-menu-item index="1-4">选项4</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</el-menu-item>
<el-menu-item index="3" disabled>
<i class="el-icon-document"></i>
<span slot="title">导航三</span>
</el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting"></i>
<span slot="title">导航四</span>
</el-menu-item>
</el-menu>
</el-aside>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<style>
.el-container {
width: 100%;
height: 700px;
}
.el-header,
.el-footer {
background-color: #b3c0d1;
color: #333;
text-align: center;
line-height: 60px;
}
.el-aside {
background-color: #d3dce6;
color: #333;
text-align: center;
line-height: 100%;
}
.el-main {
background-color: #e9eef3;
color: #333;
text-align: center;
line-height: 100%;
}
body > .el-container {
margin-bottom: 40px;
}
.el-menu-item a {
text-decoration: none;
font-size: 14px;
color: white;
}
.el-menu-item .router-link-active {
color: red;
font-size: 20px;
font-weight: 800;
text-decoration: none;
}
</style>
<script>
export default {
data() {
return {};
},
methods: {},
};
</script>
基本查询
建立Student.vue,在该组件中使用自定义列的table组件,从node后台查询出所有的学生,然后按照table组件的显示规则,显示数据;
核心代码如下:
<div id="app">
<el-table
:data="restus.slice(start, end)"
@row-click="handleEdit"
style="width: 100%"
>
<el-table-column label="学生编号" prop="stu_id"> </el-table-column>
<el-table-column label="学生姓名" prop="stu_name"> </el-table-column>
<el-table-column label="性别" prop="stu_sex">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{
scope.row.stu_sex == 1 ? "男" : "女"
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="学生头像" prop="stu_pic">
<template slot-scope="scope">
<el-image
style="width: 50px; height: 50px; border-radius: 25px"
:src="'http://localhost:3000/images/' + scope.row.stu_pic"
:preview-src-list="[
'http://localhost:3000/images/' + scope.row.stu_pic,
]"
>
</el-image>
</template>
</el-table-column>
<el-table-column label="学生生日" prop="stu_birth">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{
scope.row.stu_birth | dateFormat
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="学生爱好" prop="stu_hob"> </el-table-column>
<el-table-column label="学生班级" prop="ClassName"> </el-table-column>
<el-table-column align="right">
<template slot="header" slot-scope="scope">
<el-input v-model="search" size="mini" placeholder="输入名字搜索" />
</template>
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
>Edit</el-button
>
<el-button
size="mini"
@click.stop="handleDelete(scope.$index, scope.row)"
type="danger"
>Delete</el-button
>
</template>
</el-table-column>
</el-table>
Script部分:
//查询所有
getAll() {
this.$ajax({
method: "get",
url: "/",
}).then((response) => {
this.stus = response.data.message;
this.restus = this.stus;
this.total = this.restus.length;
});
},
created() {
this.getAll();
},
分页查询
使用pagination分页组件与数据建立联系,通过查询出所有的数据,然后利用数组的slice方法,计算start,end,控制每页显示的数据:
核心代码如下:
data() {
return {
stus: [],
search: "",
pageNum: 1,
total: 0,
pageSize: 3,
restus: [],
};
},
//分页有关方法
handleSizeChange(val) {
this.pageSize = val;
},
handleCurrentChange(val) {
this.pageNum = val;
},
computed: {
start() {
return this.pageNum * this.pageSize - this.pageSize;
},
//截取的结束位置
end() {
return this.pageNum * this.pageSize;
},
},
条件查询
通过搜索文本框绑定data中的search,然后在数组中进行搜索,把搜索到的数据分页显示。
核心代码如下:
watch: {
search(val) {
this.restus = this.stus.filter((item) => {
return item.stu_name.includes(val);
});
this.total = this.restus.length;
},
},
第四步:实现修改
点击修改按钮,会把当前的行信息和索引作为参数传给方法,在方法中使用带参数的编程导航传到修改页面,核心代码如下:
handleEdit(index, row) {
let stu = {
stu_id: row.stu_id,
stu_name: row.stu_name,
stu_sex: row.stu_sex,
stu_birth: row.stu_birth,
stu_class_id: row.ClassID,
stu_hob: row.stu_hob.split(","),
stu_pic: row.stu_pic,
};
this.$router.push({ name: "studentUpdate", params: stu }); // 只能用 name
},
第五步:实现删除
点击删除按钮,同样把当前的行信息传递过来,通过id删除数据,核心代码如下:
handleDelete(index, row) {
let stu_id = row.stu_id;
this.$ajax({
method: "get",
url: "/toDel/" + stu_id,
}).then((response) => {
window.location.reload();
});
},
第六步:整体代码
Students.vue
<template>
<div id="app">
<el-table
:data="restus.slice(start, end)"
@row-click="handleEdit"
style="width: 100%"
>
<el-table-column label="学生编号" prop="stu_id"> </el-table-column>
<el-table-column label="学生姓名" prop="stu_name"> </el-table-column>
<el-table-column label="性别" prop="stu_sex">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{
scope.row.stu_sex == 1 ? "男" : "女"
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="学生头像" prop="stu_pic">
<template slot-scope="scope">
<el-image
style="width: 50px; height: 50px; border-radius: 25px"
:src="'http://localhost:3000/images/' + scope.row.stu_pic"
:preview-src-list="[
'http://localhost:3000/images/' + scope.row.stu_pic,
]"
>
</el-image>
</template>
</el-table-column>
<el-table-column label="学生生日" prop="stu_birth">
<template slot-scope="scope">
<div slot="reference" class="name-wrapper">
<el-tag size="medium">{{
scope.row.stu_birth | dateFormat
}}</el-tag>
</div>
</template>
</el-table-column>
<el-table-column label="学生爱好" prop="stu_hob"> </el-table-column>
<el-table-column label="学生班级" prop="ClassName"> </el-table-column>
<el-table-column align="right">
<template slot="header" slot-scope="scope">
<el-input v-model="search" size="mini" placeholder="输入名字搜索" />
</template>
<template slot-scope="scope">
<el-button size="mini" @click="handleEdit(scope.$index, scope.row)"
>Edit</el-button
>
<el-button
size="mini"
@click.stop="handleDelete(scope.$index, scope.row)"
type="danger"
>Delete</el-button
>
</template>
</el-table-column>
</el-table>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[3, 6, 9, 12, 15, 18, 21, 24, 27, 30]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
stus: [],
search: "",
pageNum: 1,
total: 0,
pageSize: 3,
restus: [],
};
},
methods: {
//查询所有
getAll() {
this.$ajax({
method: "get",
url: "/",
}).then((response) => {
this.stus = response.data.message;
this.restus = this.stus;
this.total = this.restus.length;
});
},
//分页有关方法
handleSizeChange(val) {
this.pageSize = val;
},
handleCurrentChange(val) {
this.pageNum = val;
},
handleEdit(index, row) {
let stu = {
stu_id: row.stu_id,
stu_name: row.stu_name,
stu_sex: row.stu_sex,
stu_birth: row.stu_birth,
stu_class_id: row.ClassID,
stu_hob: row.stu_hob.split(","),
stu_pic: row.stu_pic,
};
this.$router.push({ name: "studentUpdate", params: stu }); // 只能用 name
},
handleDelete(index, row) {
let stu_id = row.stu_id;
this.$ajax({
method: "get",
url: "/toDel/" + stu_id,
}).then((response) => {
window.location.reload();
});
},
},
created() {
this.getAll();
},
computed: {
start() {
return this.pageNum * this.pageSize - this.pageSize;
},
//截取的结束位置
end() {
return this.pageNum * this.pageSize;
},
},
watch: {
search(val) {
this.restus = this.stus.filter((item) => {
return item.stu_name.includes(val);
});
this.total = this.restus.length;
},
},
};
</script>
<style scoped>
</style>
Update.vue
<template>
<div id="app">
<div class="detail">
<el-page-header @back="goBack"> </el-page-header>
</div>
<div id="up">
<el-form
ref="form"
:model="stu"
label-width="80px"
label-position="right"
>
<el-form-item label="学生编号">
<el-input v-model="stu.stu_id"></el-input>
</el-form-item>
<el-form-item label="学生姓名">
<el-input v-model="stu.stu_name"></el-input>
</el-form-item>
<el-form-item label="班级">
<el-select
v-model="stu.stu_class_id"
placeholder="请选择班级"
clearable
>
<el-option
v-for="c in csinfo"
:key="c.classId"
:label="c.classname"
:value="c.classId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="学生生日">
<el-col>
<el-date-picker
type="date"
placeholder="选择日期"
v-model="stu.stu_birth"
style="width: 100%"
></el-date-picker>
</el-col>
</el-form-item>
<el-form-item label="爱好">
<el-checkbox-group v-model="stu.stu_hob">
<el-checkbox label="唱歌" name="type"></el-checkbox>
<el-checkbox label="跳舞" name="type"></el-checkbox>
<el-checkbox label="看书" name="type"></el-checkbox>
<el-checkbox label="球类运动" name="type"></el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="性别">
<el-radio-group v-model="stu.stu_sex">
<el-radio label="1">男</el-radio>
<el-radio label="2">女</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="头像">
<div class="demo-image__preview">
<el-image
style="width: 50px; height: 50px; border-radius: 25px"
:src="'http://localhost:3000/images/' + stu.stu_pic"
:preview-src-list="[
'http://localhost:3000/images/' + stu.stu_pic,
]"
>
</el-image>
</div>
<el-form-item label="修改头像">
<el-upload
class="avatar-uploader"
action="#"
:show-file-list="true"
:before-upload="beforeAvatarUpload"
:on-change="changeUpload"
>
<img v-if="imageUrl" :src="imageUrl" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
</el-form-item>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">修改</el-button>
<el-button>重置</el-button>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
import moment from "moment";
let ps = new FormData();
// stu_name, stu_sex, stu_birth, stu_class_id, stu_hob
export default {
data() {
return {
stu: {
stu_id: this.$route.params.stu_id,
stu_name: this.$route.params.stu_name,
stu_sex: this.$route.params.stu_sex,
stu_birth: this.$route.params.stu_birth,
stu_class_id: this.$route.params.stu_class_id,
stu_hob: this.$route.params.stu_hob,
stu_pic: this.$route.params.stu_pic,
},
csinfo: [],
imageUrl: "",
param: {},
};
},
methods: {
//查询所有班级
getAll() {
this.$ajax({
method: "get",
url: "/csinfo",
}).then((response) => {
this.csinfo = response.data.message;
});
},
beforeAvatarUpload(file) {
this.pic = file;
ps.append("pic", file, file.name);
return false;
},
changeUpload(file) {
this.imageUrl = URL.createObjectURL(file.raw);
},
goBack() {
this.$router.go(-1);
},
onSubmit() {
ps.append("stu_id", this.stu.stu_id);
ps.append("stu_name", this.stu.stu_name);
ps.append("stu_sex", this.stu.stu_sex);
ps.append("stu_birth", moment(this.stu.stu_birth).format("YYYY-MM-DD"));
ps.append("stu_class_id", this.stu.stu_class_id);
ps.append("stu_hob", this.stu.stu_hob.join(","));
ps.append("stu_pic", this.stu.stu_pic);
console.log(ps);
let config = {
headers: {
"Content-Type": "multipart/form-data",
},
};
this.$ajax({
method: "post",
url: "/updateStu",
data: ps,
}).then((response) => {
let msg = response.data.message;
this.$router.push({ name: "students" });
});
},
},
created() {
this.getAll();
},
};
</script>
<style scoped>
#up {
width: 500px;
height: auto;
margin: 10px auto;
}
.detail {
width: 100%;
height: 50px;
font-size: 14px;
color: rgb(27, 26, 26);
line-height: 50px;
}
.avatar-uploader .el-upload {
border: 2px dashed #f0ec0d;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar-uploader-icon[data-v-4b495b0e] {
background-color: white;
border: 2px yellow dotted;
width: 110px;
height: 110px;
border-radius: 50%;
line-height: 110px;
}
img.avatar {
width: 110px;
height: 110px;
border-radius: 50%;
}
</style>
注意:此案例是建立在vue-cli以及element-ui整合的基础上的。
15.3 本章小结
• Table组件使用data以及列中的prop可以方便的绑定和展示数据。
• 使用pagination分页组件很方便后期数据的分页处理,注意size-change和current-change的使用。
• Tree组件分别通过default-expanded-keys和default-checked-keys设置默认展开和默认选中的节点。需要注意的是,此时必须设置node-key,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的。
• 通过项目案例灵活使用element-ui的form组件,table组件以及分页组件。
15.4 理论试题与实践练习
1.填空题
1.%2 Table表格使用 属性绑定数据。
2.%2 禁用Tree菜单的属性是 。
3.%2 分页组件当前页码繁盛变化的方法是 。
2.编程题
2.1 完成案例中的添加功能。
2.2 使用element-ui实现汽车管理页面。
- 点赞
- 收藏
- 关注作者
评论(0)