封面来源:本文封面来源于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:
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
|
等待项目创建完毕后,前往项目根目录执行以下命令,来启动一下创建的项目:
如果可以启动成功,证明我们的创建没有问题。
然后在项目的根目录中执行以下命令,安装 Element UI:
等待安装完毕后,指定当前项目中使用 Element UI。前往项目的 src
目录下,找到 main.js
文件,在这个文件中添加以下代码:
1 2 3 4 5
| import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css';
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-组件名称
进行使用!
创建按钮
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>
|
3.2 Link 文字链接
创建文字链接
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>
|
注意:
1、在一个布局组件中,是由 row
和 col
组合而成的。
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>
|
基本上常用的也就 gutter
和 tag
两个属性,其他属性可参考: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>
|
注意 span
和 offset
属性的区别!
其他属性可参考: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-header 或 el-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 组件,只需要设置 v-model
绑定变量,选中意味着变量的值为相应 Radio label
属性的值,label
可以是 String
、Number
或 Boolean
。
注意: 在使用 Radio 单选按钮的时候,至少要加入 v-model
和 label
两个属性。
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>
|
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>
|
总结:
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>
|
与 Radio 单选按钮一样,Checkbox 也有自己的属性,两者都差不多,具体可以参考:Checkbox Attributes
同样的,Checkbox 也有属于自己的事件,其事件也是当绑定值变化时触发的事件,事件名称为 change
,其回调参数是更新后的值。
多选框组的使用
上述案例中,Checkbox 似乎与单选按钮一样,根本无法实现多选,那是因为要使用多选框组才能实现多选。
多选框组适用于多个勾选框绑定到同一个数组的情景,通过是否勾选来表示这一组选项中选中的项。
checkbox-group
元素能把多个 Checkbox 管理为一组,只需要在 Group 中使用 v-model
绑定 Array
类型的变量即可。 el-checkbox
的 label
属性是该 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
注意:
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 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>
|
总结:
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>
|
注意: 在下拉列表中,<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 的所有属性
参数 |
说明 |
类型 |
可选值 |
默认值 |
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>
|
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 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
,否则可能会造成添加的时间日期与真正存储的时间日期不一致。
readonly
和 disabled
最大的区别在于设置前者时,数据 会随着表单的提交而提交;而设置后者时,数据并 不会随着表单的提交而提交。
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>
|
Picker Options 和 Shortcuts
Picker Options:用来对日期控件做自定义配置
参数 |
说明 |
类型 |
可选值 |
默认值 |
shortcuts |
设置快捷选项,需要传入 { text, onClick } 对象用法参考 demo 或下表 |
Object[] |
— |
— |
disabledDate |
设置禁用状态,参数为当前日期,要求返回 Boolean |
Function |
— |
— |
cellClassName |
设置日期的 className |
Function(Date) |
— |
— |
firstDayOfWeek |
周起始日 |
Number |
1 到 7 |
7 |
onPick |
选中日期后会执行的回调,只有当 daterange 或 datetimerange 才生效 |
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>
|
注意: 在使用 <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 的所有属性
参数 |
说明 |
类型 |
可选值 |
默认值 |
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>
|
由输入框、选择器、单选框、多选框等控件组成,用以收集、校验、提交数据。
对应官方文档: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-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>
|
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>
|
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>
|
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 的依赖:
等待下载完毕后,在 main.js
文件中引入并使用 Element UI:
1 2 3 4 5
| import ElementUI from 'element-ui'; import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
|
然后在 assets
目录下创建名为 indexImgs
的文件夹,向里面塞六张图片,作为首页轮播图。
还会使用到 Axios,因此需要进行安装:
在项目的根目录中,执行以下命令,安装 Axios:
1
| npm install axios --save
|
等待安装完毕后,前往 main.js
文件,添加以下代码:
1 2 3 4 5
| import axios from '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 } ] })
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
|
@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
|
@Mapper @Repository public interface UserDao {
List<User> findAll();
void save(User user);
void update(User user);
void delete(String id);
List<User> findByPage(@Param("start") Integer start, @Param("rows") Integer rows);
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
|
@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;
@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
以访问界面。👊
当数据量过多时,使用分页分解数据。
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 使用思路完