封面来源:本文封面来源于Element UI 官网,如有侵权,请联系删除。

参考视频:适合后端编程人员的 ElementUI教程,结合SpringBoot项目案例,已完结!!!

1. Element UI的引言

The world’s most popular Vue UI framework

Element UI 是一个 Vue UI 框架,因此在学习的时候需要有一定的 Vue 基础(包括 Vue 脚手架),相关文章可在本站搜索【Vue2.0 快速入门】一文进行阅读。

Element UI 官网:Element UI

Element UI 国内官网站点:Element UI zh

根据官网得知:Element UI 是一个 网站快速成型工具,一套为开发者、设计师和产品经理准备的基于 Vue 2.0 的 桌面端组件库

现在 Element UI 已经支持 Vue 3.0 了,但 在本文我们依旧使用 Vue 2.0 与 Element UI 进行讲解。

本文 只做 常用组件与 思路的讲解,详细内容可以参考官方文档。

对 Element UI 下一个定义:Element UI 就是一个基于 Vue 的 UI 框架,它基于 Vue 开发了很多相关组件,方便我们快速开发页面。

Element UI 的由来

Element UI 是 饿了么前端团队 基于 Vue 进行开发并开源的框架,Element UI 中提供的全部都是封装好的组件。

2. 快速开始

2.1 基本安装

安装方式

官方文档中,提供了两种安装方式,一种是基于 Vue 脚手架的,一种是基于 CDN 加速的:

NPM:

1
npm i element-ui -S

CDN:

1
2
3
4
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>

在如今的环境下,我们的项目都是前后端分离的,因此不再选用 CDN 的方式进行安装,选择 NPM 的方式进行安装。

安装步骤

那么我们就需要先通过 Vue 脚手架创建一个名为 element 的项目:

1
vue init webpack element

等待项目创建完毕后,前往项目根目录执行以下命令,来启动一下创建的项目:

1
npm start

如果可以启动成功,证明我们的创建没有问题。

然后在项目的根目录中执行以下命令,安装 Element UI:

1
npm i element-ui -S

等待安装完毕后,指定当前项目中使用 Element UI。前往项目的 src 目录下,找到 main.js 文件,在这个文件中添加以下代码:

1
2
3
4
5
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

// 在 Vue 脚手架中使用 Element UI
Vue.use(ElementUI);

到此,Element UI 就安装成功了!

2.2 第一个 Demo

初探按钮组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<template>
<div>
<!-- 使用默认按钮组件 -->
<el-row>
<el-button>默认按钮</el-button>
<el-button type="primary">主要按钮</el-button>
<el-button type="success">成功按钮</el-button>
<el-button type="info">信息按钮</el-button>
<el-button type="warning">警告按钮</el-button>
<el-button type="danger">危险按钮</el-button>
</el-row>
<br>

<!-- 使用简洁按钮 -->
<el-row>
<el-button plain>朴素按钮</el-button>
<el-button type="primary" plain>主要按钮</el-button>
<el-button type="success" plain>成功按钮</el-button>
<el-button type="info" plain>信息按钮</el-button>
<el-button type="warning" plain>警告按钮</el-button>
<el-button type="danger" plain>危险按钮</el-button>
</el-row>
<br>

<!-- 使用圆角按钮 -->
<el-row>
<el-button round>圆角按钮</el-button>
<el-button type="primary" round>主要按钮</el-button>
<el-button type="success" round>成功按钮</el-button>
<el-button type="info" round>信息按钮</el-button>
<el-button type="warning" round>警告按钮</el-button>
<el-button type="danger" round>危险按钮</el-button>
</el-row>
<br>

<!-- 使用图标按钮 -->
<el-row>
<el-button icon="el-icon-search" circle></el-button>
<el-button type="primary" icon="el-icon-edit" circle></el-button>
<el-button type="success" icon="el-icon-check" circle></el-button>
<el-button type="info" icon="el-icon-message" circle></el-button>
<el-button type="warning" icon="el-icon-star-off" circle></el-button>
<el-button type="danger" icon="el-icon-delete" circle></el-button>
</el-row>
</div>
</template>

3. 基本组件的使用

总结: 日后使用 Element UI 的相关组件时,所有组件都是通过 el-组件名称 进行使用!

3.1 Button 按钮

创建按钮

1
<el-button>默认按钮</el-button>

按钮属性的使用

1
2
3
4
<el-button type="primary" size="mini" :plain="true" round>primary</el-button>
<el-button type="success" size="small" :plain="true" round>success</el-button>
<el-button type="warning" size="medium" :plain="true" round>warning</el-button>
<el-button type="danger " size="medium" icon="el-icon-delete" circle></el-button>

总结: 在 Element UI 中组件属性的使用都是直接按照 属性名=属性值 的方式写在对应的组件标签上!

在 Element UI 中:

1、如果一个属性的类型是 boolean 且默认值是 false,那么可以直接在标签上使用这个属性,而不指定值,这时候的值是 true

2、如果一个属性的类型是 boolean,且默认值是 true,如果想要指定它的值为 false,那么需要使用 Vue 的绑定语法,即: :属性名="false"

使用按钮的属性

按钮有很多属性,具体参考 Button Attributes

按钮组与图标按钮

1
2
3
4
<el-button-group>
<el-button type="primary" icon="el-icon-arrow-left">上一页</el-button>
<el-button type="primary">下一页<i class="el-icon-arrow-right el-icon--right"></i></el-button>
</el-button-group>

按钮组与图表按钮

创建文字链接

1
<el-link href="https://mofan212.github.io" target="_blank">默认链接</el-link>

文字链接属性的使用

1
2
3
4
5
<el-link type="primary" :underline="false">主要链接</el-link>
<el-link type="success">成功链接</el-link>
<el-link type="warning" disabled>警告链接</el-link>
<el-link type="danger">危险链接</el-link>
<el-link type="info" icon="el-icon-platform-eleme">信息链接</el-link>

文字链接属性的使用

Link 文字链接的属性,具体参考 Link Attributes

3.3 Layout (栅格)布局

在官网的 Layout 布局 上有这样一句话:通过基础的 24 分栏,迅速简便地创建布局。

就是说: 在 Element UI 中的布局组件将页面划分为多个行 row,每行最多分为 24 栏(列)。

使用 Layout 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<template>
<div>
<h1>Layout布局组件的使用</h1>
<el-row>
<el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
</el-row>
<br>
<el-row>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
</div>
</template>

<style>
.bg-purple-dark {
background: #99a9bf;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
</style>

Layout布局组件的使用

注意:

1、在一个布局组件中,是由 rowcol 组合而成的。

2、在使用时需要区分 row 的属性和 col 的属性。

行属性的使用

1
2
3
4
5
6
<el-row :gutter="50" tag="span">
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>

Layout布局组件中行属性的使用

基本上常用的也就 guttertag 两个属性,其他属性可参考:Row Attributes

列属性的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h1>Layout组件中使用偏移</h1>
<el-row>
<el-col :span="12" :offset="6"><div class="grid-content bg-purple"></div></el-col>
</el-row>
<br>
<el-row>
<el-col :span="12" :offset="6"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="12" :offset="6"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
<br>
<el-row>
<el-col :span="12" :offset="6" :push="3"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="6"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>

Layout组件中使用偏移

注意 spanoffset 属性的区别!

其他属性可参考:Col Attributes

3.4 Container 布局容器

官网的说明

官网链接:Container 布局容器

用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>:外层容器。当子元素中包含 <el-header><el-footer> 时,全部子元素会垂直上下排列,否则会水平左右排列。

<el-header>:顶栏容器。

<el-aside>:侧边栏容器。

<el-main>:主要区域容器。

<el-footer>:底栏容器。

注意: 以上组件采用了 flex 布局,使用前请确定目标浏览器是否兼容。此外,<el-container> 的子元素只能是后四者,后四者的父元素也只能是 <el-container>

容器的基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<template>
<div>
<h1>布局容器的使用</h1>
<!-- 创建容器 -->
<el-container>
<!-- header -->
<el-header><div><span>我是标题</span></div></el-header>
<!-- 容器的嵌套使用 -->
<el-container>
<!-- aside -->
<el-aside><div><span>我是菜单</span></div></el-aside>
<!-- main -->
<el-main><div><span>我是中心内容</span></div></el-main>
</el-container>
<el-footer><div><span>我是页脚</span></div></el-footer>
</el-container>
</div>
</template>

<style>
.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: 200px;
}

.el-main {
background-color: #E9EEF3;
color: #333;
text-align: center;
line-height: 160px;
}

body > .el-container {
margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
line-height: 320px;
}
</style>

布局容器的使用

水平容器与垂直容器

<el-container> 有只有一个属性:

参数 说明 类型 可选值 默认值
direction 子元素的排列方向 string horizontal / vertical 子元素中有 el-headerel-footer 时为 vertical,否则为 horizontal
1
2
3
4
5
6
7
8
9
10
11
12
<!-- 创建容器 -->
<el-container direction="horizontal">
<!-- header -->
<el-header><div><span>我是标题</span></div></el-header>
<el-container direction="vertical">
<!-- aside -->
<el-aside><div><span>我是菜单</span></div></el-aside>
<!-- main -->
<el-main><div><span>我是中心内容</span></div></el-main>
</el-container>
<el-footer><div><span>我是页脚</span></div></el-footer>
</el-container>

水平容器与垂直容器

容器其他属性的使用

Header Attributes:

参数 说明 类型 可选值 默认值
height 顶栏高度 string 60px

Aside Attributes:

参数 说明 类型 可选值 默认值
width 侧边栏宽度 string 300px

Footer Attributes:

参数 说明 类型 可选值 默认值
height 底栏高度 string 60px

代码示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
<h1>容器其他属性的使用</h1>
<!-- 创建容器 -->
<el-container>
<!-- header -->
<el-header height="80px"><div><h1>我是标题</h1></div></el-header>
<el-container>
<!-- aside -->
<el-aside width="200px"><div><h1>我是菜单</h1></div></el-aside>
<!-- main -->
<el-main><div><h1>我是中心内容</h1></div></el-main>
</el-container>
<el-footer height="100px"><div><h1>我是页脚</h1></div></el-footer>
</el-container>

容器其他属性的使用

4. 表单组件的使用

4.1 Radio 单选按钮

创建 Radio 单选按钮

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<h1>Radio的使用</h1>
<el-radio v-model="label" label="男">男</el-radio>
<el-radio v-model="label" label="女">女</el-radio>
</div>
</template>

<script>
export default {
name: 'Radio',
data() {
return {
label: '男'
}
}
}
</script>

Radio的使用

要使用 Radio 组件,只需要设置 v-model 绑定变量,选中意味着变量的值为相应 Radio label 属性的值,label 可以是 StringNumberBoolean

注意: 在使用 Radio 单选按钮的时候,至少要加入 v-modellabel 两个属性。

Radio 按钮属性的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<h1>Radio按钮属性的使用</h1>
<el-radio v-model="radio" label="1" name="radio" size="mini" border>备选项1</el-radio>
<el-radio v-model="radio" label="2" name="radio" size="small" disabled border>备选项2</el-radio>
<el-radio v-model="radio" label="3" name="radio" size="mudium" border>备选项3</el-radio>

<script>
export default {
name: 'Radio',
data() {
return {
radio: '1'
}
}
}
</script>

Radio按钮属性的使用

name 属性就是原生的 name 属性,用于向后端传递值时使用。

size 属性表示 Radio 的尺寸,仅在 border 属性为 true 时有效,其值只有三种可选。

属性的使用还是按照 属性名=属性值 的方式直接卸载对应的组件标签上。

Radio 属性具体的使用参考:Radio Attributes

Radio 事件的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<h1>Radio绑定事件的使用</h1>
<el-radio v-model="event" label="1" @change="changeValue">选项1</el-radio>
<el-radio v-model="event" label="2" @change="changeValue">选项2</el-radio>

<script>
export default {
name: 'Radio',
data() {
return {
event: '1'
}
},
methods: {
changeValue() {
alert("事件触发 ==>" + this.event);
}
}
}
</script>

Radio事件的使用

总结:

1、事件的使用也是和属性的使用是一样的,都是直接写在对应的组件标签上。

2、事件在使用时必须使用 Vue 中绑定事件的方式进行使用,如:@事件名=事件处理函数(绑定在 Vue 组件中对应函数)

Radio 按钮组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<h1>单选按钮组</h1>
<el-radio-group v-model="radio" >
<el-radio label="3" border>备选项3</el-radio>
<el-radio label="6" border>备选项6</el-radio>
<el-radio label="9" border>备选项9</el-radio>
</el-radio-group>

<script>
export default {
name: 'Radio',
data() {
return {
radio: '3',
}
},
}
</script>

使用 Radio 按钮组,只需要绑定一次数据,而无需每次都绑定。

按钮组也有自己的属性,具体可以查看:Radio-group Attributes

同样,按钮组也有自己的事件,和单个 Radio 类似,就不在此赘述了,可以参考:Radio-group Events

只需要把 el-radio 元素换成 el-radio-button 元素就可以实现按钮样式的单选组合。其属性可以参考:Radio-button Attributes

按钮样式的单选组合

4.2 Checkbox 多选框

多选框的基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<h1>Checkbox组件的使用</h1>
<el-checkbox v-model="checked" true-label="北京">北京</el-checkbox>
<el-checkbox v-model="checked" true-label="上海">上海</el-checkbox>
<el-checkbox v-model="checked" true-label="广州">广州</el-checkbox>
<el-checkbox border checked true-label="杭州">杭州</el-checkbox>
</div>
</template>

<script>
export default {
name: 'Checkbox',
data() {
return{
checked: "北京"
}
}
};
</script>

Checkbox组件的使用

与 Radio 单选按钮一样,Checkbox 也有自己的属性,两者都差不多,具体可以参考:Checkbox Attributes

同样的,Checkbox 也有属于自己的事件,其事件也是当绑定值变化时触发的事件,事件名称为 change,其回调参数是更新后的值。

多选框组的使用

上述案例中,Checkbox 似乎与单选按钮一样,根本无法实现多选,那是因为要使用多选框组才能实现多选。

多选框组适用于多个勾选框绑定到同一个数组的情景,通过是否勾选来表示这一组选项中选中的项。

checkbox-group 元素能把多个 Checkbox 管理为一组,只需要在 Group 中使用 v-model 绑定 Array 类型的变量即可。 el-checkboxlabel 属性是该 Checkbox 对应的值,若该标签中无内容,则该属性也充当 Checkbox 按钮后的介绍。label 与数组中的元素值相对应,如果存在指定的值则为选中状态,否则为不选中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<el-checkbox-group v-model="checkList" min="1">
<el-checkbox label="复选框 A"></el-checkbox>
<el-checkbox label="复选框 B"></el-checkbox>
<el-checkbox label="复选框 C"></el-checkbox>
<el-checkbox label="禁用" disabled></el-checkbox>
<el-checkbox label="选中且禁用" disabled></el-checkbox>
</el-checkbox-group>

<script>
export default {
name: 'Checkbox',
data() {
return{
checkList: ['选中且禁用','复选框 A']
}
}
};
</script>

多选框组的使用

多选框组也有自己的属性,可以指定被勾选的 Checkbox 的最大 / 小数量,具体可以参考:Checkbox-group Attributes

多选框组也有属于自己的事件,和单个 Checkbox 一样,其事件也是当绑定值变化时触发的事件,事件名称为 change,其回调参数是更新后的值。

除此之外,还有 Checkbox-Button 可以使用,就和 Radio-Button 一样,具体可以参考:按钮样式Checkbox-button Attributes

4.3 Input 输入框

注意:

1、Input 为受控组件,它 总会显示 Vue 绑定值

2、通常情况下,应当处理 input 事件,并更新组件的绑定值(或使用v-model)。否则,输入框内显示的值将不会改变。

3、Input 不支持 v-model 修饰符。

创建 Input 输入框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<h1>Input组件的使用</h1>
<el-input placeholder="请输入内容" v-model="name"></el-input>

</div>
</template>

<script>
export default {
name: 'Input',
data() {
return {
name: 'mofan'
}
}
}
</script>

Input组件的使用

Input 的常用属性

Input 的属性有很多,完整属性列表可参考 Input Attributes,常用属性如下表所示:

参数 说明 类型 可选值 默认值
type 类型 string text,textarea 和其他原生 input 的 type 值 text
value / v-model 绑定值 string / number
maxlength 原生属性,最大输入长度 number
minlength 原生属性,最小输入长度 number
show-word-limit 是否显示输入字数统计,只在 type = "text"type = "textarea" 时有效 boolean false
placeholder 输入框占位文本 string
clearable 是否可清空 boolean false
show-password 是否显示切换密码图标 boolean false
disabled 禁用 boolean false
size 输入框尺寸,只在 type!="textarea" 时有效 string medium / small / mini
prefix-icon 输入框头部图标 string
suffix-icon 输入框尾部图标 string
rows 输入框行数,只对 type="textarea" 有效 number 2
autosize 自适应内容高度,只对 type="textarea" 有效,可传入对象,如,{ minRows: 2, maxRows: 6 } boolean / object false
autocomplete 原生属性,自动补全 string on, off off
name 原生属性 string
readonly 原生属性,是否只读 boolean false
max 原生属性,设置最大值
min 原生属性,设置最小值
form 原生属性 string
label 输入框关联的label文字 string

注意: 要想 Input 输入框能够键入值,<el-Input> 必须有 v-model 属性!

Input 事件的使用

根据 Element UI 的官网,Input 输入框有以下事件:

事件名称 说明 回调参数
blur 在 Input 失去焦点时触发 (event: Event)
focus 在 Input 获得焦点时触发 (event: Event)
change 仅在输入框失去焦点或用户按下回车时触发 (value: string | number)
input 在 Input 值改变时触发 (value: string | number)
clear 在点击由 clearable 属性生成的清空按钮时触发

对于 change 事件来说,当我们在输入框内输入一次数据后,当输入框失去焦点或按下回车就会触发该事件。如果输入框内的数据没有发生改变,那么就算输入框再失去焦点或者再按下回车都 不出 触发该该事件,直到输入框内的数据发生改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<h1>Input事件的使用</h1>
<el-input v-model="username" @blur="aaa" @focus="bbb"></el-input>
<br>
<br>
<el-input v-model="change" @input="ccc" placeholder="input事件的使用"></el-input>

<script>
export default {
name: 'Input',
data() {
return {
username: '',
change: '',
}
},
methods: {
aaa() {
console.log("失去焦点");
},
bbb() {
console.log("获得焦点");
},
ccc(value) {
console.log("输入框内的值: " + value);
}
}
}
</script>

注意: 当我们使用组件的事件并指定触发事件后执行的方法时,在组件上只需要书写方法名即可,不要书写括号或者参数。比如下面这种书写方式是错误的:

1
<el-input v-model="change" @input="ccc()" placeholder="input事件的使用"></el-input>

下面这种也是错误的:

1
<el-input v-model="change" @input="ccc(value)" placeholder="input事件的使用"></el-input>

Input 方法的使用

跟着官方文档继续走,会发现 Input 组件还有名为 Input Methods 的东西,那这是啥?

需要明白的是, 在 Element UI 中所有组件都存在属性、事件和方法:

  • (Attributes)属性 是用来定义组件初始的状态。直接写在对应的组件标签上,按照 属性名=属性值 的方式进行使用。
  • (Events)事件 是在组件发生某种状态变化时,触发组件特定的事件。直接使用 Vue 绑定事件方式写在对应组件标签上,按照 @事件名=Vue中事件处理函数名 的方式进行使用。
  • (Methods)方法 是用来改变组件的默认状态。使用时需要先在对应组件标签上使用 ref=组件别名,然后通过 this.$refs.组件别名.方法名() 的方式进行调用。

对于 Input 输入框来说,官方提供了一下几种方法:

方法名 说明 参数
focus 使 input 获取焦点
blur 使 input 失去焦点
select 选中 input 中的文字
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<h1>Input方法的使用</h1>
<el-input v-model="method" ref="input"></el-input>
<br>
<br>
<el-button @click="focusInputs">focus</el-button>
<el-button @click="blurInputs">blur</el-button>

<script>
export default {
name: 'Input',
data() {
return {
method: ''
}
},
methods: {
// 调用focus方法
focusInputs() {
this.$refs.input.focus();
},
// 调用blur方法
blurInputs() {
this.$refs.input.blur();
}
}
}
</script>

Input方法的使用

总结:

1、当我们使用组件的方法时,需要在对应的组件上加入 ref=组件别名,这样就会将当前组件绑定给 Vue 实例

2、在调用组件方法(Methods)时,可以直接使用 this.$refs.组件别名.组件方法名(); 的形式调用组件方法。

4.4 Select 选择器

当选项过多时,使用下拉菜单展示并选择内容。

创建 Select 选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<template>
<div>
<h1>Select选择器的使用</h1>
<!-- 数据写死在页面上 -->
<el-select v-model="language" placeholder="请选择语言">
<el-option value="Java">Java</el-option>
<el-option value="C">C</el-option>
<el-option value="C++">C++</el-option>
</el-select>
<!-- 动态地获取数据 -->
<el-select v-model="dept" placeholder="请选择部门">
<el-option
v-for="option in options"
:label="option.name"
:value="option.id"
:key="option.id"
></el-option>
</el-select>
</div>
</template>

<script>
export default {
name: "Select",
data() {
return {
options: [
{ id: "1", name: "研发" },
{ id: "2", name: "中台" },
{ id: "3", name: "财务" },
{ id: "4", name: "人事" },
],
dept: '',
language: '',
};
},
};
</script>

Select选择器的使用

注意: 在下拉列表中,<el-option>必须存在 value 属性值;在 <el-select> 必须存在 v-model 属性以进行数据绑定。

如果我们需要从数据库中获取数据,那么只需要在 Vue 生命周期的 created 中通过 Axios 获取数据即可。后续会有案例讲解,别慌。 😎

Select 的常用属性

如果 Select 的绑定值为对象类型,请务必指定 value-key 作为它的唯一性标识。

Input 的属性有很多,完整属性列表可参考 Select Attributes,常用属性如下表所示:

参数 说明 类型 可选值 默认值
value / v-model 绑定值 boolean / string / number
multiple 是否多选 boolean false
disabled 是否禁用 boolean false
value-key 作为 value 唯一标识的键名,绑定值为对象类型时必填 string value
size 输入框尺寸 string medium/small/mini
clearable 是否可以清空选项 boolean false
collapse-tags 多选时是否将选中值按文字的形式展示 boolean false
multiple-limit 多选时用户最多可以选择的项目数,为 0 则不限制 number 0
name select input 的 name 属性 string
placeholder 占位符 string 请选择
filterable 是否可搜索 boolean false
no-match-text 搜索条件无匹配时显示的文字,也可以使用slot="empty"设置 string 无匹配数据
no-data-text 选项为空时显示的文字,也可以使用slot="empty"设置 string 无数据
popper-class Select 下拉框的类名 string

Select 事件的使用

对于 Select 选择器来说,Element UI 提供了以下几种事件:

事件名称 说明 回调参数
change 选中值发生变化时触发 目前的选中值
visible-change 下拉框出现/隐藏时触发 出现则为 true,隐藏则为 false
remove-tag 多选模式下移除tag时触发 移除的tag值
clear 可清空的单选模式下用户点击清空按钮时触发
blur 当 input 失去焦点时触发 (event: Event)
focus 当 input 获得焦点时触发 (event: Event)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<el-select v-model="dept" multiple placeholder="请选择部门" @change="aaa">
<el-option
v-for="option in options"
:label="option.name"
:value="option.id"
:key="option.id"
></el-option>
</el-select>

<script>
export default {
name: "Select",
data() {
return {
options: [
{ id: "1", name: "研发" },
{ id: "2", name: "中台" },
{ id: "3", name: "财务" },
{ id: "4", name: "人事" },
],
dept: '',
};
},
methods: {
aaa(value) {
console.log(value);
}
}
};
</script>

Select 方法的使用

Select 选择器也有自己的方法,它有以下两个方法:

方法名 说明 参数
focus 使 input 获取焦点 -
blur 使 input 失去焦点,并隐藏下拉框 -

4.5 Switch 开关

表示两种相互对立的状态间的切换,多用于触发「开/关」。

创建 Switch 开关

在学习该组件时,需要创建一个名为 Switch.vue 的文件,但是这个时候浏览器可能会产生警告,虽然不影响使用,可看着也不舒服。这是因为定义的组件名和 Element UI 中的组件名一致了,只需要将组件名改为 Switchs.vue 即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<h1>Switch开关的使用</h1>
<el-switch
v-model="value"
active-color="#13ce66"
inactive-color="#ff4949"
active-text="打开"
:active-value="true"
inactive-text="关闭"
:inactive-value="false">
</el-switch>
</div>
</template>

<script>
export default {
name: 'Switchs',
data() {
return {
value: true
}
}
}
</script>

Switch开关的使用

Switch 的所有属性

参数 说明 类型 可选值 默认值
value / v-model 绑定值 boolean / string / number
disabled 是否禁用 boolean false
width switch 的宽度(像素) number 40
active-icon-class switch 打开时所显示图标的类名,设置此项会忽略 active-text string
inactive-icon-class switch 关闭时所显示图标的类名,设置此项会忽略 inactive-text string
active-text switch 打开时的文字描述 string
inactive-text switch 关闭时的文字描述 string
active-value switch 打开时的值 boolean / string / number true
inactive-value switch 关闭时的值 boolean / string / number false
active-color switch 打开时的背景色 string #409EFF
inactive-color switch 关闭时的背景色 string #C0CCDA
name switch 对应的 name 属性 string
validate-event 改变 switch 状态时是否触发表单的校验 boolean - true

Switch 的事件和方法

事件:

事件名称 说明 回调参数
change switch 状态发生变化时的回调函数 新状态的值

方法:

方法名 说明 参数
focus 使 Switch 获取焦点 -
1
2
3
4
5
6
7
8
9
<h1>Switch事件与方法</h1>
<el-switch
v-model="aaa"
@change="bb"
active-value="on"
inactive-value="off"
ref="sw">
</el-switch>
<el-button @click="cc">调用方法</el-button>

Switch事件与方法

4.6 DatePicker 日期选择器

用于选择或输入日期。

在 Element UI 中,提供了三种与时间日期相关的选择器,分别是:TimePicker(时间选择器)、DatePicker(日期选择器)和 DateTimePicker(日期时间选择器)。我们常用的是日期选择器,因此在此就介绍一些日期选择器。

创建 DatePicker 日期选择器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<h1>DatePicker日期选择器的使用</h1>
<el-date-picker
v-model="createTime">
</el-date-picker>
</div>
</template>

<script>
export default {
name: 'DatePicker',
data() {
return {
createTime:''
}
}
}
</script>

DatePicker日期选择器的使用

DatePicker 的属性

DatePicker 的属性有很多,完整属性列表可参考 DatePicker Attributes,常用属性如下表所示:

参数 说明 类型 可选值 默认值
value / v-model 绑定值 date(DatePicker) / array(DateRangePicker)
readonly 完全只读 boolean false
disabled 禁用 boolean false
editable 文本框可输入 boolean true
clearable 是否显示清除按钮 boolean true
size 输入框尺寸 string large, small, mini
placeholder 非范围选择时的占位内容 string
start-placeholder 范围选择时开始日期的占位内容 string
end-placeholder 范围选择时结束日期的占位内容 string
type 显示类型 string year/month/date/dates/ week/datetime/datetimerange/ daterange/monthrange date
format 显示在输入框中的格式 string 日期格式 yyyy-MM-dd
align 对齐方式 string left, center, right left
value-format 可选,绑定值的格式。不指定则绑定值为 Date 对象 string 日期格式

注意: 当我们使用 <el-date-picker> 组件时,尽量指定 value-format 属性,同时,对应属性在数据库的字段类型设置成 timestamp,否则可能会造成添加的时间日期与真正存储的时间日期不一致。

readonlydisabled 最大的区别在于设置前者时,数据 会随着表单的提交而提交;而设置后者时,数据并 不会随着表单的提交而提交

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<h1>DatePicker日期选择器的使用</h1>
<el-date-picker
v-model="createTime"
:editable="false"
:clearable="false"
type="daterange"
start-placeholder="请输入开始时间"
end-placeholder="请输入结束时间"
format="yyyy/MM/dd">
</el-date-picker>
</div>
</template>

<script>
export default {
name: 'DatePicker',
data() {
return {
createTime:''
}
}
}
</script>

DatePicker的属性

Picker Options 和 Shortcuts

Picker Options:用来对日期控件做自定义配置

参数 说明 类型 可选值 默认值
shortcuts 设置快捷选项,需要传入 { text, onClick } 对象用法参考 demo 或下表 Object[]
disabledDate 设置禁用状态,参数为当前日期,要求返回 Boolean Function
cellClassName 设置日期的 className Function(Date)
firstDayOfWeek 周起始日 Number 1 到 7 7
onPick 选中日期后会执行的回调,只有当 daterangedatetimerange 才生效 Function({ maxDate, minDate })

Shortcuts:用来增加日期组件的快捷面板

参数 说明 类型 可选值 默认值
text 标题文本 string
onClick 选中后的回调函数,参数是 vm,可通过触发 ‘pick’ 事件设置选择器的值。例如 vm.$emit(‘pick’, new Date()) function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<h1>日期配置</h1>
<el-date-picker
v-model="createTime"
type="date"
placeholder="请输入时间"
:picker-options="pickerOptions">
</el-date-picker>

<script>
export default {
name: 'DatePicker',
data() {
return {
createTime:'',
pickerOptions: {
disabledDate(time) { // 对选择的日期进行配置
return time.getTime() > Date.now(); // 只能选择今天及以前
},
shortcuts: [{ // 定义的shortcuts
text: '今天',
onClick(picker) {
picker.$emit('pick', new Date());
}
}, {
text: '昨天',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit('pick', date);
}
}, {
text: '一周前',
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit('pick', date);
}
}]
},
}
}
}
</script>
日期配置

DatePicker 的事件

事件名称 说明 回调参数
change 用户确认选定的值时触发 组件绑定值。格式与绑定值一致,可受 value-format 控制
blur 当 input 失去焦点时触发 组件实例
focus 当 input 获得焦点时触发 组件实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<el-date-picker
v-model="createTime"
@change="aaa">
</el-date-picker>

<script>
export default {
name: 'DatePicker',
data() {
return {
createTime:'',
}
},
methods: {
aaa(value) {
console.log(value);
}
}
}
</script>

4.7 Upload 上传

通过点击或者拖拽上传文件。

对应官方文档:Upload 上传

创建 Upload 上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<h1>Upload组件的使用</h1>
<el-upload action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png文件,且不超过500kb
</div>
</el-upload>
</div>
</template>

<script>
export default {
name: "Uploads",
data() {
return {
fileList: [{name: 'food.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}, {name: 'food2.jpeg', url: 'https://fuss10.elemecdn.com/3/63/4e7f3a15429bfda99bce42a18cdd1jpeg.jpeg?imageMogr2/thumbnail/360x360/format/webp/quality/100'}]
};
},
};
</script>

Upload组件的使用

注意: 在使用 <el-upload> 组件时,必须设置 action 属性,action 属性为必要参数且不能省略。

如果想实现拖拽上传,可以:

1
2
3
4
5
6
7
8
9
10
<h1>Upload拖拽上传</h1>
<el-upload
class="upload-demo"
drag
action="https://jsonplaceholder.typicode.com/posts/"
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip" slot="tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>

Upload拖拽上传

Upload 的所有属性

参数 说明 类型 可选值 默认值
action 必选参数,上传的地址 string
headers 设置上传的请求头部 object
multiple 是否支持多选文件 boolean
data 上传时附带的额外参数 object
name 上传的文件字段名 string file
with-credentials 支持发送 cookie 凭证信息 boolean false
show-file-list 是否显示已上传文件列表 boolean true
drag 是否启用拖拽上传 boolean false
accept 接受上传的文件类型(thumbnail-mode 模式下此参数无效) string
on-preview 点击文件列表中已上传的文件时的钩子 function(file)
on-remove 文件列表移除文件时的钩子 function(file, fileList)
on-success 文件上传成功时的钩子 function(response, file, fileList)
on-error 文件上传失败时的钩子 function(err, file, fileList)
on-progress 文件上传时的钩子 function(event, file, fileList)
on-change 文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用 function(file, fileList)
before-upload 上传文件之前的钩子,参数为上传的文件,若返回 false 或者返回 Promise 且被 reject,则停止上传。 function(file)
before-remove 删除文件之前的钩子,参数为上传的文件和文件列表,若返回 false 或者返回 Promise 且被 reject,则停止删除。 function(file, fileList)
list-type 文件列表的类型 string text/picture/picture-card text
auto-upload 是否在选取文件后立即进行上传 boolean true
file-list 上传的文件列表, 例如: [{name: ‘food.jpg’, url: ‘https://xxx.cdn.com/xxx.jpg’}] array []
http-request 覆盖默认的上传行为,可以自定义上传的实现 function
disabled 是否禁用 boolean false
limit 最大允许上传个数 number
on-exceed 文件超出个数限制时的钩子 function(files, fileList) -

注意:

1、在使用 on-exceed 属性时,要结合 limit 属性使用。

2、在使用钩子时,需要使用 v-bind: 或者 : 进行绑定。

3、在使用 <el-upload> 组件时,没有 event 事件,所有事件都是属性事件。

Upload 的方法

方法名 说明 参数
clearFiles 清空已上传的文件列表(该方法不支持在 before-upload 中调用)
abort 取消上传请求 (file: fileList 中的 file 对象)
submit 手动上传文件列表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<el-upload ref="uploads" ......>
......
</el-upload>
<el-button @click="clearFiles">清空文件</el-button>

<script>
export default {
name: "Uploads",
// ...
methods: {
clearFiles() {
this.$refs.uploads.clearFiles();
}
}
};
</script>

4.8 Form 表单

由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据。

对应官方文档:Form 表单

创建 Form 表单

根据官方文档的案例,经典的表单包括各种表单项,比如输入框、选择器、开关、单选框、多选框等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<template>
<div>
<h1>Form组件的使用</h1>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="活动名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="form.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker
type="date"
placeholder="选择日期"
v-model="form.date1"
style="width: 100%"
></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker
placeholder="选择时间"
v-model="form.date2"
style="width: 100%"
></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="即时配送">
<el-switch v-model="form.delivery"></el-switch>
</el-form-item>
<el-form-item label="活动性质">
<el-checkbox-group v-model="form.type">
<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="form.resource">
<el-radio label="线上品牌商赞助"></el-radio>
<el-radio label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="活动形式">
<el-input type="textarea" v-model="form.desc"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</template>

<script>
export default {
name: "Forms",
data() {
return {
form: {
name: "",
region: "",
date1: "",
date2: "",
delivery: false,
type: [],
resource: "",
desc: "",
},
};
},
methods: {
onSubmit() {
console.log("submit!");
},
},
};
</script>

<style>
</style>
Form组件的使用

在 Form 组件中,每一个表单域由一个 Form-Item 组件构成,表单域中可以放置各种类型的表单控件,包括 Input、Select、Checkbox、Radio、Switch、DatePicker、TimePicker 等组件。

如果想要创建内联表单,那么只需要将 <el-form>inline 属性设置为 true 即可。如:

1
2
3
<el-form ref="form" :inline="true" :model="form" label-width="80px">
......
</el-form>

Form 的属性

参数 说明 类型 可选值 默认值
model 表单数据对象 object
rules 表单验证规则 object
inline 行内表单模式 boolean false
label-position 表单域标签的位置,如果值为 left 或者 right 时,则需要设置 label-width string right/left/top right
label-width 表单域标签的宽度,例如 ‘50px’。作为 Form 直接子元素的 form-item 会继承该值。支持 auto string
label-suffix 表单域标签的后缀 string
hide-required-asterisk 是否显示必填字段的标签旁边的红色星号 boolean false
show-message 是否显示校验错误信息 boolean true
inline-message 是否以行内形式展示校验信息 boolean false
status-icon 是否在输入框中显示校验结果反馈图标 boolean false
validate-on-rule-change 是否在 rules 属性改变后立即触发一次验证 boolean true
size 用于控制该表单内组件的尺寸 string medium / small / mini
disabled 是否禁用该表单内的所有组件。若设置为 true,则表单内组件上的 disabled 属性不再生效 boolean false

表单的验证

Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可。

表单验证包括两种情况:一是失去焦点就进行验证,另一种是表单提交调用表单组件的验证方法验证。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<el-form ref="form" :rules="rules" :model="form" label-width="80px">
<el-form-item label="活动名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit('form')">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>

<script>
export default {
name: "Forms",
data() {
return {
form: {
name: "",
},
rules: {
name: [
{ required: true, message: "请输入活动名称", trigger: "blur" },
{ min: 3, max: 5, message: "长度在 3 到 5 个字符", trigger: "blur" },
],
},
};
},
methods: {
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
},
};
</script>

表单的验证

自定义验证规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<h1>自定义验证规则</h1>
<el-form :model="ruleForm" status-icon :rules="rules" ref="ruleForm" label-width="80px" label-position="left">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm.pass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm.checkPass" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="年龄" prop="age">
<el-input v-model.number="ruleForm.age"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')">提交</el-button>
<el-button @click="resetForm('ruleForm')">重置</el-button>
</el-form-item>
</el-form>
<script>
export default {
data() {
var checkAge = (rule, value, callback) => {
if (!value) {
return callback(new Error('年龄不能为空'));
}
setTimeout(() => {
if (!Number.isInteger(value)) {
callback(new Error('请输入数字值'));
} else {
if (value < 18) {
callback(new Error('必须年满18岁'));
} else {
callback();
}
}
}, 1000);
};
var validatePass = (rule, value, callback) => {
if (value === '') {
callback(new Error('请输入密码'));
} else {
if (this.ruleForm.checkPass !== '') {
this.$refs.ruleForm.validateField('checkPass');
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === '') {
callback(new Error('请再次输入密码'));
} else if (value !== this.ruleForm.pass) {
callback(new Error('两次输入密码不一致!'));
} else {
callback();
}
};
return {
ruleForm: {
pass: '',
checkPass: '',
age: ''
},
rules: {
pass: [
{ validator: validatePass, trigger: 'blur' }
],
checkPass: [
{ validator: validatePass2, trigger: 'blur' }
],
age: [
{ validator: checkAge, trigger: 'blur' }
]
}
};
},
methods: {
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
}
}
}
</script>

自定义校验 callback 必须被调用。

自定义验证规则

5. 消息提示组件的使用

在 Element UI 中,消息提示组件的使用比较简单,建议参考官网文档进行编写。

5.1 Alert 警告

用于页面中展示重要的提示信息。

对应官方文档:Alert 警告

Alert 警告的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
<h1>Alert组件的使用</h1>
<el-alert title="成功提示信息" type="success" description="我是辅助信息1号" :closable="false"></el-alert>
<br>
<el-alert title="消息提示信息" type="info" close-text="知道了" show-icon>
<div slot>我是辅助信息2号</div>
</el-alert>
<br>
<el-alert title="警告提示信息" type="warning" effect="dark" @close="hello" center></el-alert>
<br>
<el-alert title="错误提示信息" type="error" effect="light" show-icon center></el-alert>
</div>
</template>

<script>
export default {
name: 'Alerts',
methods: {
hello() {
alert('Hello World!');
}
}
}
</script>

<style>
</style>

Alert组件的使用

5.2 Message 消息提示

常用于主动操作后的反馈提示。

对应官方文档:Message 消息提示

与 Notification 的区别是后者更多用于系统级通知的被动提醒。

但在这我们并不介绍 Notification,可以自行查看官方文档:Notification 通知

Message 消息提示的使用

注意: 这个组件的创建无须在页面中书写任何标签,它是一个 JS 插件,在需要展示消息提示的位置直接调用提供的 JS 插件即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<template>
<div>
<h1>Message组件的使用</h1>
<el-button type="success" @click="open2">成功</el-button>
<el-button type="warning" :plain="true" @click="open3">警告</el-button>
<el-button type="primary" :plain="true" @click="open1">消息</el-button>
<el-button type="danger" @click="open4">错误</el-button>
<el-button :plain="true" ref="close" @click="closeMsg">调用关闭提示方法</el-button>
</div>
</template>

<script>
export default {
name: "Messages",
methods: {
open1() {
this.$message("这是一条消息提示")
},
open2() {
const h = this.$createElement;
this.$message({
message: h("p", null, [
h("span", null, "内容可以是 "),
h("i", { style: "color: teal" }, "Success"),
]),
type: "success",
duration: 0,
});
},
open3() {
this.$message({
showClose: "true",
message: "警告哦,这是一条警告消息",
type: "warning",
center: "true",
});
},
open4() {
this.$message.error("错了哦,这是一条错误消息");
},
closeMsg() { // 关闭所有消息提示
this.$message.closeAll();
}
},
};
</script>

<style>
</style>

Message组件的使用-1

Message组件的使用-2

Element UI 注册了一个$message方法用于调用,Message 可以接收一个字符串或一个 VNode 作为参数,它会被显示为正文内容。

当需要自定义更多属性时,Message 也可以接收一个对象为参数。比如,设置 type 字段可以定义不同的状态,默认为 info。此时正文内容以 message 的值传入。同时,我们也为 Message 的各种 type 注册了方法,可以在不传入 type 字段的情况下像 open4 那样直接调用。

默认的 Message 是不可以被人工关闭的,如果需要可手动关闭的 Message,可以使用 showClose 字段。此外,和 Notification 一样,Message 拥有可控的 duration,设置 0 为不会被自动关闭,默认为 3000 毫秒。

其他属性:

参数 说明 类型 可选值 默认值
type 主题 string success/warning/info/error info
iconClass 自定义图标的类名,会覆盖 type string
dangerouslyUseHTMLString 是否将 message 属性作为 HTML 片段处理 boolean false
customClass 自定义类名 string
onClose 关闭时的回调函数, 参数为被关闭的 message 实例 function
offset Message 距离窗口顶部的偏移量 number 20

Message 的完整属性参考:Options

dangerouslyUseHTMLString属性设置为 true,message 就会被当作 HTML 片段处理。参考:Message 使用 HTML 片段

注意: message 属性虽然支持传入 HTML 片段,但是在网站上动态渲染任意 HTML 是非常危险的,因为容易导致 XSS 攻击。因此在 dangerouslyUseHTMLString 打开的情况下,请确保 message 的内容是可信的,永远不要 将用户提交的内容赋值给 message 属性。 简单来说,最好别用这玩意。 😓

6. Table 表格

用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。

Table 表格组件是作为 Data 数据组件的一项,数据组件中还有很多其他的组件,比如分页、树形控件等。表格组件在日常开发中会经常使用到,因此单独提出来进行讲解。

6.1 创建 Table 表格

创建一个表格需要使用到 <el-table> 组件。当 el-table 元素中注入 data 对象数组后,在 el-table-column 中用 prop 属性来对应对象中的键名即可填入数据,用 label 属性来定义表格的列名。可以使用 width 属性来定义列宽。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
<div>
<h1>Table组件的使用</h1>
<el-table :data="tableData">
<el-table-column prop="id" label="编号"></el-table-column>
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
</el-table>
</div>
</template>

<script>
export default {
name: 'Tables',
data() {
return {
tableData: [
{id: 1, name: "mofan", age: 18, email: "cy.mofan@qq.com"},
{id: 2, name: "默烦", age: 20, email: "cy.mofan@qq.com"},
]
}
}
}
</script>

创建Table表格

6.2 表格的列属性

表格的完整列属性参看:Table-column Attributes

参数 说明 类型 可选值 默认值
width 对应列的宽度 string
fixed 列是否固定在左侧或者右侧,true 表示固定在左侧 string, boolean true, left, right
align 对齐方式 String left/center/right left
header-align 表头对齐方式,若不设置该项,则使用表格的对齐方式 String left/center/right
sortable 对应列是否可以排序,如果设置为 ‘custom’,则代表用户希望远程排序,需要监听 Table 的 sort-change 事件 boolean, string true, false, ‘custom’ false
sort-method 对数据进行排序的时候使用的方法,仅当 sortable 设置为 true 的时候有效,需返回一个数字,和 Array.sort 表现一致 Function(a, b)
resizable 对应列是否可以通过拖动改变宽度(需要在 el-table 上设置 border 属性为真) boolean true
formatter 用来格式化内容 Function(row, column, cellValue, index)

对于 fixed 属性可以理解为自适应,当其设置为 left 时,还会取决于 width 属性值,但是设置为 right 时,不会取决于 width 属性值。

align 可以设置列中内容的对齐方式,包括表头和表内数据。如果只想设置表内数据的对齐方式,可以使用 header-align 设置表头的对齐方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<template>
<div>
<h1>Table组件的使用</h1>
<el-table :data="tableData" border>
<el-table-column
prop="id"
:resizable="false"
header-align="left"
align="center"
label="编号"
width="200px"
></el-table-column>
<el-table-column prop="name" label="姓名"></el-table-column>
<el-table-column
prop="age"
label="年龄"
:sort-method="sorts"
sortable
></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column
prop="dept.name"
:formatter="showDept"
label="部门"
></el-table-column>
</el-table>
</div>
</template>

<script>
export default {
name: "Tables",
data() {
return {
tableData: [
{
id: 1,
name: "mofan",
age: 18,
email: "cy.mofan@qq.com",
dept: {
id: 1,
name: "研发",
},
},
{
id: 2,
name: "默烦",
age: 20,
email: "cy.mofan@qq.com",
dept: {
id: 2,
name: "财务",
},
},
{
id: 3,
name: "小陈",
age: 22,
email: "cy.mofan@qq.com",
dept: {},
},
],
};
},
methods: {
sorts(a, b) {
console.log(a);
console.log(b);
return b.age - a.age; // 注意交换顺序后的区别
},
showDept(row, column, cellValue, index) {
console.log(row);
console.log(column);
console.log(cellValue);
console.log(index);
if (cellValue) {
return cellValue;
} else {
return "暂无部门";
}
},
},
};
</script>

表格的列属性

6.3 表格的属性

表格的完整属性参看:Table Attributes

参数 说明 类型 可选值 默认值
data 显示的数据 array
height Table 的高度,默认为自动高度。如果 height 为 number 类型,单位 px;如果 height 为 string 类型,则这个高度会设置为 Table 的 style.height 的值,Table 的高度会受控于外部样式。 string/number
max-height Table 的最大高度。合法的值为数字或者单位为 px 的高度。 string/number
stripe 是否为斑马纹 table boolean false
size Table 的尺寸 string medium / small / mini
border 是否带有纵向边框 boolean false
fit 列的宽度是否自撑开 boolean true
show-header 是否显示表头 boolean true
highlight-current-row 是否要高亮当前行 boolean false
row-class-name 行的 className 的回调方法,也可以使用字符串为所有行设置一个固定的 className。 Function({row, rowIndex})/String
empty-text 空数据时显示的文本内容,也可以通过 slot="empty" 设置 String 暂无数据

使用 row-class-name 可以指定每一行的回调方法,也可以直接指定固定的 className。比如,可以给每一行指定不同的样式(设置不同的底色),但是在设置不同的底色时 最好移除 属性 stripe,使用这个属性很有可能会让我们设置的样式无法显示。

在使用 empty-text 属性时,空数据时显示的文本内容,指的是 整个表没有数据 时显示的文本内容。

本次的案例建立在 6.2 表格的列属性 demo 的基础上:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<el-table
:data="tableData"
border
:fit="false"
:height="400"
size="small"
:highlight-current-row="true"
:row-class-name="showCss"
:show-header="false">
</el-table>

<script>
export default {
name: "Tables",
data() {
return {
// 省略已写代码
};
},
methods: {
// 省略以写代码
showCss({row, rowIndex}) {
if(rowIndex % 2 == 0) {
return "warning-row";
} else {
return "success-row";
}
},
},
};
</script>

<style>
.el-table .warning-row {
background: oldlace;
}

.el-table .success-row {
background: #f0f9eb;
}
</style>
表格的属性

6.4 事件与方法

表格的完整事件参看:Table Events

表格的事件:

事件名 说明 参数
select 当用户手动勾选数据行的 Checkbox 时触发的事件 selection, row

表格的事件有很多,学会使用思路就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<el-table @select="selectRow"></el-table>
<!-- 省略已写代码 -->
<script>
export default {
name: "Tables",
data() {
return {
// 省略已写代码
};
},
methods: {
// 省略已写代码
selectRow(selection, row) {
console.log(selection); // 被选中的所有行
console.log(row); // 本次选中的行
}
},
};
</script>

表格的方法:

表格的完整事件参看:Table Methods

方法名 说明 参数
clearSelection 用于多选表格,清空用户的选择

表格的方法有很多,学会使用思路就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<el-table ref="mytable">
<!-- 省略已写代码 -->
</el-table>

<el-button type="primary" @click="clearSelect">清空表格</el-button>
<script>
export default {
name: "Tables",
data() {
return {
// 省略已写代码
};
},
methods: {
// 省略已写代码
clearSelect() {
this.$refs.mytable.clearSelection();
}
},
};
</script>

6.5 自定义操作列

一般来说,一个表格中还有一列操作列,在这一列中可以编辑、删除数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<el-table>
<!-- 省略已写代码 -->
<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>

<script>
export default {
name: "Tables",
data() {
return {
// 省略已写代码
};
},
methods: {
// 省略已写代码
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
}
},
};
</script>

自定义操作列

6.6 自定义表头

有时候我们还想自定义表头,比如在表头上添加一个搜索栏。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<el-table :data="tableData.filter(data => !search || data.name.toLowerCase().includes(search.toLowerCase()))">
<el-table-column type="selection"></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)">
编辑
</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">
删除
</el-button>
</template>
</el-table-column>
</el-table>

<script>
export default {
name: "Tables",
data() {
return {
// 省略已写代码
};
},
methods: {
// 省略已写代码
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
}
},
};
</script>

自定义表头

Element UI 中 Table 表格的内容有很多,在此只介绍思想,详情参考官方文档:Table 表格

7. 小案例讲解

7.1 项目搭建

执行以下命令,初始化项目:

1
vue init webpack element_users

等待初始化完毕后,下载 Element UI 的依赖:

1
npm i element-ui -S

等待下载完毕后,在 main.js 文件中引入并使用 Element UI:

1
2
3
4
5
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

// 在 Vue 脚手架中使用 Element UI
Vue.use(ElementUI);

然后在 assets 目录下创建名为 indexImgs 的文件夹,向里面塞六张图片,作为首页轮播图。

还会使用到 Axios,因此需要进行安装:

在项目的根目录中,执行以下命令,安装 Axios:

1
npm install axios --save

等待安装完毕后,前往 main.js 文件,添加以下代码:

1
2
3
4
5
// 引入 Axios
import axios from 'axios'

// 修改内部的 $http 为 axios
Vue.prototype.$http = axios

7.2 页面导航菜单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<template>
<div id="app">
<el-container>
<el-header>
<!-- 导航菜单 -->
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="horizontal" @select="handleSelect">
<el-menu-item index="/index">主页</el-menu-item>
<el-menu-item index="/users" >用户管理</el-menu-item>
<el-menu-item index="/msgs">消息中心</el-menu-item>
<el-menu-item index="/orders">订单管理</el-menu-item>
</el-menu>
</el-header>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</div>
</template>

<script>
export default {
name: 'App',
data() {
return {
activeIndex: '/index',
};
},
methods: {
handleSelect(key, keyPath) {
this.$router.push(key);
}
}
}
</script>

7.3 首页轮播图

创建一个名为 Index.vue 的组件,该组件主要用于主页显示。在 index.js 中注册组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import Vue from 'vue'
import Router from 'vue-router'
import Index from '../components/Index.vue'
import List from '../components/user/List.vue'

Vue.use(Router)

export default new Router({
routes: [{
path: '/',
redirect: '/index',
},
{
path: '/index',
component: Index
},
{
path: '/users',
component: List
}
]
})

// 解决 ElementUI 导航栏中的 vue-router 在 3.0 版本以上重复点菜单报错问题
const originalPush = Router.prototype.push
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err)
}

就这一次哦,以后就省略组件的注册了。😊

然后在 Index.vue 中编写主页轮播图的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
<div>
<el-carousel indicator-position="outside" height="500px">
<el-carousel-item v-for="item in imgs" :key="item">
<el-image :src="item" fit="contain" style="height: 600px"></el-image>
</el-carousel-item>
</el-carousel>
</div>
</template>

<script>
import homeImg1 from '../assets/indexImgs/1.jpg'
import homeImg2 from '../assets/indexImgs/2.jpg'
import homeImg3 from '../assets/indexImgs/3.jpg'
import homeImg4 from '../assets/indexImgs/4.jpg'
import homeImg5 from '../assets/indexImgs/5.jpg'
import homeImg6 from '../assets/indexImgs/6.jpg'
export default {
name: "Index",
data() {
return {
imgs: [
homeImg1, homeImg2, homeImg3, homeImg4, homeImg5, homeImg6
],
};
},
};
</script>

7.4 用户管理界面

创建 List.vue 作为用户管理界面的组件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<template>
<div>
<el-table :data="tableData.filter(data => !search || data.name.toLowerCase().includes(search.toLowerCase()))" style="width: 100%">
<el-table-column label="编号" width="180">
<template slot-scope="scope">
<span style="margin-left: 10px"> {{ scope.row.id }} </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="生日" prop="birth"></el-table-column>
<el-table-column label="性别" prop="gender"></el-table-column>
<el-table-column label="地址" prop="address"></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)">编辑</el-button>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-button type="success" style="margin-top: 10px" size="mini">添加</el-button>
</div>
</template>

<script>
export default {
name: "List",
data() {
return {
tableData: [
{
id: 1,
name: "王小虎",
birth: '2016-05-02',
address: "上海市",
gender: '男',
},
{
id: 2,
name: "默烦",
birth: '2000-01-01',
address: "成都市",
gender: '男',
},
],
search: '',
};
},
methods: {
handleEdit(index, row) {
console.log(index, row);
},
handleDelete(index, row) {
console.log(index, row);
},
},
};
</script>

用户管理界面

7.5 用户管理后端编写

使用 IDEA 创建一个 SpringBoot 项目或 Module,并引入一下依赖:

Spring Boot DevTools
Lombok
Spring Web
MyBatis Framework
MySQL Driver

新建数据库,在库内新建一张表:

1
2
3
4
5
6
7
8
CREATE TABLE `t_user` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`name` varchar(80) DEFAULT NULL,
`birth` timestamp NULL DEFAULT NULL,
`gender` varchar(4) DEFAULT NULL,
`address` varchar(120) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

注意: 这里 birth 的类型设置成了 timestamp,如果设置成 date 类型,可能会导致后续存储的数据和界面显示的数据不一致。

项目配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server:
port: 9090
servlet:
context-path: /

spring:
datasource:
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
username: root
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/elementusers?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=GMT%2B8

mybatis:
mapper-locations: classpath:indi/mofan/mapper/*.xml
type-aliases-package: indi.mofan.entity

主要实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* @author mofan 2021/1/16
*/
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Accessors(chain = true)
public class User {
private String id;
private String name;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birth;
private String gender;
private String address;
}

数据访问层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
/**
* @author mofan 2021/1/16
*/
@Mapper
@Repository
public interface UserDao {

/**
* 查询所有用户信息
* @return
*/
List<User> findAll();

/**
* 添加用户
* @param user
*/
void save(User user);

/**
* 更新用户信息
* @param user
*/
void update(User user);

/**
* 删除某一用户信息
* @param id
*/
void delete(String id);

/**
* 分页查询
* @param start
* @param rows
* @return
*/
List<User> findByPage(@Param("start") Integer start,
@Param("rows") Integer rows);

/**
* 查询总条数
* @return
*/
Long findTotals();
}

对应的 MyBatis 映射文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="indi.mofan.dao.UserDao">
<select id="findAll" resultType="indi.mofan.entity.User">
select id, name, birth, gender, address
from t_user
</select>

<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into t_user values(#{id}, #{name}, #{birth}, #{gender}, #{address})
</insert>

<update id="update">
update t_user
set name = #{name}, birth=#{birth}, gender=#{gender}, address=#{address}
where id = #{id}
</update>

<delete id="delete">
delete from t_user where id = #{id}
</delete>

<!-- 分页查询 -->
<select id="findByPage" resultType="indi.mofan.entity.User">
select id, name, birth, gender, address
from t_user limit #{start}, #{rows}
</select>

<select id="findTotals" resultType="long">
select count(*) from t_user
</select>
</mapper>

业务层实现类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* @author mofan 2021/1/16
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl implements UserService {

@Autowired
private UserDao userDao;

@Override
@Transactional(readOnly = true)
public List<User> findAll() {
return userDao.findAll();
}

@Override
public void save(User user) {
userDao.save(user);
}

@Override
public void update(User user) {
userDao.update(user);
}

@Override
public void delete(String id) {
userDao.delete(id);
}

@Override
public List<User> findByPage(Integer pageNow, Integer rows) {
int start = (pageNow - 1) * rows;
return userDao.findByPage(start, rows);
}

@Override
public Long findTotals() {
return userDao.findTotals();
}
}

控制层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import com.alibaba.druid.util.StringUtils;

/**
* @author mofan 2021/1/16
*/
@RestController
@RequestMapping("user")
@CrossOrigin
public class UserController {

@Autowired
private UserService userService;

@GetMapping("findAll")
public List<User> findAll() {
return userService.findAll();
}

@PostMapping("saveOrUpdate")
public Map<String, Object> saveOrUpdate(@RequestBody User user) {
Map<String, Object> map = new HashMap<>(8);
try {
if (StringUtils.isEmpty(user.getId())){
userService.save(user);
map.put("success", true);
map.put("msg", "添加用户信息成功");
} else {
userService.update(user);
map.put("success", true);
map.put("msg", "修改用户信息成功");
}
} catch (Exception e) {
map.put("success", false);
map.put("msg", "用户信息提交失败" + e.getMessage());
}
return map;
}

@GetMapping("delete")
public Map<String, Object> delete(String id) {
Map<String, Object> map = new HashMap<>(8);
try {
userService.delete(id);
map.put("success", true);
map.put("msg", "删除用户信息成功");
} catch (Exception e) {
map.put("success", false);
map.put("msg", "删除用户信息失败" + e.getMessage());
}
return map;
}

@GetMapping("findByPage")
public Map<String, Object> findByPage(Integer pageNow, Integer pageSize) {
Map<String, Object> map = new HashMap<>(16);
pageNow = pageNow == null ? 1 : pageNow;
pageSize = pageSize == null ? 4 : pageSize;
List<User> users = userService.findByPage(pageNow, pageSize);
Long totals = userService.findTotals();
map.put("users", users);
map.put("total", totals);
return map;
}
}

后端搞定! 😎

7.6 前端页面完善

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
<template>
<div>
<el-table
:data="
tableData.filter(
(data) =>
!search || data.name.toLowerCase().includes(search.toLowerCase())
)
"
style="width: 100%"
>
<el-table-column label="编号" width="180">
<template slot-scope="scope">
<span style="margin-left: 10px"> {{ scope.row.id }} </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="生日" prop="birth"></el-table-column>
<el-table-column label="性别" prop="gender"></el-table-column>
<el-table-column label="地址" prop="address"></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)"
>编辑</el-button
>
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
<el-row>
<el-col :span="12" :offset="12">
<!-- 分页组件 -->
<el-pagination
style="margin: 15px 0px"
prev-text="上一页"
next-text="下一页"
background
layout="prev, pager, next, jumper, total, sizes"
:page-size="size"
:current-page="pageNow"
:page-sizes="[2, 4, 6, 8, 10]"
@current-change="findPage"
@size-change="findSize"
:total="total"
>
</el-pagination
></el-col>
</el-row>

<el-button
type="success"
style="margin-top: 10px"
size="mini"
@click="dialogFormVisible = true"
>添加</el-button
>

<!-- 添加用户表单 -->
<el-dialog
title="用户信息"
:visible.sync="dialogFormVisible"
width="40%"
:close-on-click-modal="false"
@close="addDialogClose"
>
<el-form
:model="user"
ref="formRef"
:hide-required-asterisk="false"
:rules="rules"
>
<el-form-item label="姓名" :label-width="formLabelWidth" prop="name">
<el-input v-model="user.name" style="width: 220px"></el-input>
</el-form-item>
<el-form-item label="性别" :label-width="formLabelWidth" prop="gender">
<el-radio v-model="user.gender" label="男">男</el-radio>
<el-radio v-model="user.gender" label="女">女</el-radio>
</el-form-item>
<el-form-item label="生日" :label-width="formLabelWidth" prop="birth">
<el-date-picker
v-model="user.birth"
type="date"
placeholder="请选择你的生日"
value-format="yyyy-MM-dd"
>
</el-date-picker>
</el-form-item>
<el-form-item label="地址" :label-width="formLabelWidth" prop="address">
<el-input v-model="user.address" style="width: 220px"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">取 消</el-button>
<el-button type="primary" @click="submitUserInfo('formRef')"
>提 交</el-button
>
</div>
</el-dialog>
</div>
</template>

<script>
export default {
name: "List",
data() {
return {
tableData: [],
search: "",
dialogFormVisible: false,
user: {
name: "",
gender: "男",
birth: "",
address: "",
},
formLabelWidth: "120px",
total: 0,
size: 4,
pageNow: 1,
rules: {
name: [
{ required: true, message: "请输入用户的名称", trigger: "blur" },
],
birth: [
{ required: true, message: "请输入用户的出生日期", trigger: "blur" },
],
address: [
{ required: true, message: "请输入用户的地址", trigger: "blur" },
],
},
};
},
methods: {
handleEdit(index, row) {
this.user = row;
this.dialogFormVisible = true;
},
handleDelete(index, row) {
this.delRow(row.id);
},
// 更新用户信息或添加用户信息
submitUserInfo(formRef) {
this.$refs[formRef].validate((valid) => {
if (valid) {
this.saveOrUpdateUserInfo();
} else {
this.$message.error("请输入正确的数据");
return false;
}
});
},
// 关闭表单的回调
addDialogClose() {
this.$refs.formRef.resetFields(); // 清空表单
this.user = {};
},
getUserList(page, size) {
page = page ? page : this.pageNow;
size = size ? size : this.size;
this.$http
.get(
"http://localhost:9090/user/findByPage?pageNow=" +
page +
"&pageSize=" +
size
)
.then((res) => {
this.tableData = res.data.users;
this.total = res.data.total;
});
},
saveOrUpdateUserInfo() {
this.$http
.post("http://localhost:9090/user/saveOrUpdate", this.user)
.then((res) => {
if (res.data.success) {
// 关闭对话框
this.dialogFormVisible = false;
this.$refs.formRef.resetFields(); // 清空表单
this.user = {};
this.showMsg(res.data.msg);
this.getUserList(this.pageNow, this.size);
}
});
},
delRow(id) {
this.$confirm("此操作将删除选中用户, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
this.$http
.get("http://localhost:9090/user/delete?id=" + id)
.then((res) => {
if (res.data.success == true) {
this.getUserList(); // 查询所有用户
this.showMsg(res.data.msg);
}
});
})
.catch(() => {
this.$message({
type: "info",
message: "已取消删除",
});
});
},
showMsg(msg) {
this.$message({
message: msg,
type: "success",
});
},
// 用来处理分页的相关方法
findPage(page) {
this.pageNow = page;
this.getUserList(page, this.size);
},
// 用来处理每页显示的记录
findSize(size) {
this.size = size;
this.getUserList(this.pageNow, size);
},
},
created() {
this.getUserList();
},
};
</script>

<style>
</style>

注意: 时间选择器组件 <el-date-picker> 使用了属性 value-format="yyyy-MM-dd",请务必使用该属性,否则会造成后续存储的时间和界面显示的时间不一致。

这样,关于用户的增删改查就完成了,并且还用到了前面没有讲解的一些组件,比如 Dialog 对话框、Pagination 分页等。

可以在浏览器地址栏输入 http://localhost:8080/#/users 以访问界面。👊

Element-UI案例显示结果

8. Pagination 分页

当数据量过多时,使用分页分解数据。

Pagination 分页组件是作为 Data 数据组件的一项,数据组件中还有很多其他的组件,比如前面讲解的 Table 表格就是其中之一。

我们已经在 7. 小案例讲解 中使用了分页组件,在此列举一些分页组件常用的属性与方法。

具体使用请参考文档:Pagination

Pagination 的完整属性

参数 说明 类型 可选值 默认值
small 是否使用小型分页样式 boolean false
background 是否为分页按钮添加背景色 boolean false
page-size 每页显示条目个数,支持 .sync 修饰符 number 10
total 总条目数 number
page-count 总页数,total 和 page-count 设置任意一个就可以达到显示页码的功能;如果要支持 page-sizes 的更改,则需要使用 total 属性 Number
pager-count 页码按钮的数量,当总页数超过该值时会折叠 number 大于等于 5 且小于等于 21 的奇数 7
current-page 当前页数,支持 .sync 修饰符 number 1
layout 组件布局,子组件名用逗号分隔 String sizes, prev, pager, next, jumper, ->, total, slot ‘prev, pager, next, jumper, ->, total’
page-sizes 每页显示个数选择器的选项设置 number[] [10, 20, 30, 40, 50, 100]
popper-class 每页显示个数选择器的下拉框类名 string
prev-text 替代图标显示的上一页文字 string
next-text 替代图标显示的下一页文字 string
disabled 是否禁用 boolean false
hide-on-single-page 只有一页时是否隐藏 boolean -

Pagination 的完整事件

事件名称 说明 回调参数
size-change pageSize 改变时会触发 每页条数
current-change currentPage 改变时会触发 当前页
prev-click 用户点击上一页按钮改变当前页后触发 当前页
next-click 用户点击下一页按钮改变当前页后触发 当前页

好了,这基本就是 Element UI 的全部内容了,当然了本文只做思路讲解,还有许多的内容没有讲解到,具体的使用还是参看官方文档更舒服。😉


Element UI 使用思路完