Element-UI组件高级技术教程

举报
tea_year 发表于 2022/01/23 10:27:21 2022/01/23
【摘要】 上一章节我们学习了Element-UI的布局结构以及Form表单元素,今天来学习显示数据的table,pagination以及tree组件。15.1 Data组件Data组件的本质就是为了显示多条数据,同时可对数据进行筛选、排序、对比和其他自定义操作。常用的Data组件有Table,Pagination以及Tree组件。15.1.1 Table表格1、基础表格当el-table元素中注入da...

上一章节我们学习了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实现汽车管理页面。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。