是一个基于 Vue 的前端组件框架,使用它可以快速构建美观的前端页面。
1.快速开始
创建一个简单的 JavaWeb 应用。
添加一个 Html 页面,并在<head>
标签中加入 Element 和 Vue 的相关 js 引用:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue@2.7.14_dist_vue.min.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">
</head>
需要注意的是,Element 使用的是 2.X 版本的 Vue。
在 Vue 的初始化代码中定义相关数据模型和生效的标签:
<script>
new Vue({
el: '#app',
data: function() {
return { visible: false }
}
})
</script>
这里初始化 Vue 的方式是 2.X 版本的方式,与 3.X 的写法有所不同。
在 Html 中添加 Element UI 的相关组件:
<body>
<div id="app">
<el-button @click="visible = true">Button</el-button>
<el-dialog :visible.sync="visible" title="Hello world">
<p>Try Element</p>
</el-dialog>
</div>
</body>
最终的效果是有一个 button 按钮,点击后会出现一个弹出框。
之所以会这样,是因为 Element UI 的按钮标签el-button
上绑定了一个点击事件,该事件由 Vue 的内联事件处理代码visible = true
执行,具体效果是点击后visible
这个数据模型会变成true
。而代表弹框的 Element 标签el-dialog
是否显示由属性visible.sync
决定,该属性绑定了 Vue 的数据模型visible
,所以在visible
变成true
后会显示。相应的,关闭弹窗后visible
会变成false
。
2.布局
Element 的布局分为 Layout 和 Container 两种。
2.1.Layout
示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue@2.7.14_dist_vue.min.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">
<style>
.el-row {
margin-bottom: 20px;
}
.el-col {
border-radius: 4px;
}
.bg-purple-dark {
background: #99a9bf;
}
.bg-purple {
background: #d3dce6;
}
.bg-purple-light {
background: #e5e9f2;
}
.grid-content {
border-radius: 4px;
min-height: 36px;
}
.row-bg {
padding: 10px 0;
background-color: #f9fafc;
}
</style>
</head>
<body>
<div id="app">
<el-row>
<el-col :span="24"><div class="grid-content bg-purple-dark"></div></el-col>
</el-row>
<el-row>
<el-col :span="12"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="12"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
<el-row>
<el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="8"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :span="8"><div class="grid-content bg-purple"></div></el-col>
</el-row>
<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>
<el-row>
<el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
<el-col :span="4"><div class="grid-content bg-purple"></div></el-col>
<el-col :span="4"><div class="grid-content bg-purple-light"></div></el-col>
</el-row>
</div>
</body>
<script>
new Vue({
el: '#app',
data: function() {
return { visible: false }
}
})
</script>
</html>
这种模式下将一行分为24列,每一行可以根据需要让每一列由1到多个列组合而成(span
属性)。
更多关于 Layout 布局的说明可以阅读。
2.2.Container
Container 布局可以将页面划分成不同的区域,通常由头、尾、侧边栏和内容几个部分组成。
示例:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue@2.7.14_dist_vue.min.js"></script>
<script src="js/element-ui/lib/index.js"></script>
<link rel="stylesheet" href="js/element-ui/lib/theme-chalk/index.css">
<style>
.el-header {
background-color: #B3C0D1;
color: #333;
line-height: 60px;
}
.el-aside {
color: #333;
}
</style>
</head>
<body>
<div id="app">
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu :default-openeds="['1', '3']">
<el-submenu index="1">
<template slot="title"><i class="el-icon-message"></i>导航一</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="1-1">选项1</el-menu-item>
<el-menu-item index="1-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="1-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="1-4">
<template slot="title">选项4</template>
<el-menu-item index="1-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="2">
<template slot="title"><i class="el-icon-menu"></i>导航二</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="2-1">选项1</el-menu-item>
<el-menu-item index="2-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="2-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="2-4">
<template slot="title">选项4</template>
<el-menu-item index="2-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu index="3">
<template slot="title"><i class="el-icon-setting"></i>导航三</template>
<el-menu-item-group>
<template slot="title">分组一</template>
<el-menu-item index="3-1">选项1</el-menu-item>
<el-menu-item index="3-2">选项2</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="分组2">
<el-menu-item index="3-3">选项3</el-menu-item>
</el-menu-item-group>
<el-submenu index="3-4">
<template slot="title">选项4</template>
<el-menu-item index="3-4-1">选项4-1</el-menu-item>
</el-submenu>
</el-submenu>
</el-menu>
</el-aside>
<el-container>
<el-header style="text-align: right; font-size: 12px">
<el-dropdown>
<i class="el-icon-setting" style="margin-right: 15px"></i>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item>查看</el-dropdown-item>
<el-dropdown-item>新增</el-dropdown-item>
<el-dropdown-item>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<span>王小虎</span>
</el-header>
<el-main>
<el-table :data="tableData">
<el-table-column prop="date" label="日期" width="140">
</el-table-column>
<el-table-column prop="name" label="姓名" width="120">
</el-table-column>
<el-table-column prop="address" label="地址">
</el-table-column>
</el-table>
</el-main>
</el-container>
</el-container>
</div>
</body>
<script>
new Vue({
el: '#app',
data() {
const item = {
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
};
return {
tableData: Array(20).fill(item)
}
}
})
</script>
</html>
这个示例页面由头部、侧边栏和内容三部分组成。
3.组件
下面的演示将基于之前的示例项目 ,将使用 Element 相关组件改造项目中的 Html 页面。
3.1.表格
品牌列表页的表格替换为 Element 的表格组件 。
<template>
<el-table
:data="brands"
style="width: 100%"
:row-class-name="tableRowClassName"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column
align="center"
type="index"
label="序号">
</el-table-column>
<el-table-column
align="center"
prop="brandName"
label="品牌名称">
</el-table-column>
<el-table-column
align="center"
prop="companyName"
label="企业名称">
</el-table-column>
<el-table-column
align="center"
prop="ordered"
label="排序">
</el-table-column>
<el-table-column
align="center"
prop="description"
label="品牌介绍">
</el-table-column>
<el-table-column
align="center"
prop="statusText"
label="状态">
</el-table-column>
<el-table-column
align="center"
label="操作">
<el-button type="primary">修改</el-button>
<el-button type="danger">删除</el-button>
</el-table-column>
</el-table>
</template>
el-table
标签是 Element 的表格,这里使用到的属性有:
-
data
,绑定 Vue 数据模型(数组)后可以用该模型中的数据遍历填充表格的每一行。 -
selection-change
,对应表格复选框的change
事件,需要绑定 Vue 的事件处理器(方法)。
el-table-column
标签定义了表格的每一列,这里使用的属性有:
-
type
,定义某些特殊的列,比如:-
index
,从1开始自增的序号 -
selection
,带复选框(checkbox)的列
-
-
align
,cell 中内容的对齐方式 -
label
,表头的标题 -
prop
,遍历绑定的数据模型填充每一行时,对应的属性名
Vue 初始化代码:
new Vue({
el: "#app",
methods: {
tableRowClassName({row, rowIndex}) {
if (rowIndex === 1) {
return 'warning-row';
} else if (rowIndex === 3) {
return 'success-row';
}
return '';
},
handleSelectionChange(val) {
this.multipleSelection = val;
console.log(this.multipleSelection);
}
},
data() {
return {
username: "",
brands: [],
multipleSelection: []
}
},
mounted() {
loadBrands(this);
}
})
function loadBrands(_vue){
axios({
method: "POST",
url: "/login-demo/brand/query",
data: {}
})
.then((resp) => {
_vue.brands = resp.data;
_vue.brands.forEach((brand) => {
brand.editUrl = "/login-demo/brand/edit?id=" + brand.id;
brand.deleteUrl = "/login-demo/brand/delete?id=" + brand.id;
brand.statusText = brand.status === 0 ? "启用" : "禁用";
});
});
}
定义了两个自定义方法:
-
tableRowClassName,决定每一行是否使用某种颜色作为背景色
-
handleSelectionChange,绑定到表格复选框的事件处理器,复选框改变后会将选中的数据模型更新到
multipleSelection
这个数据模型。
Vue 的 data 属性定义了所需的数据模型。mounted 事件中通过异步调用获取品牌数据并填充到数据模型 brands。
3.2.表单
通常需要在表格上便加上搜索条件进行搜索,在 Element 中这属于”行内表单“。
<el-form :inline="true" :model="query" class="demo-form-inline">
<el-form-item label="状态">
<el-select v-model="query.status" placeholder="状态">
<el-option label="启用" value="0"></el-option>
<el-option label="禁用" value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="品牌名称">
<el-input v-model="query.brandName" placeholder="品牌名称"></el-input>
</el-form-item>
<el-form-item label="企业名称">
<el-input v-model="query.companyName" placeholder="企业名称"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onSubmit">查询</el-button>
</el-form-item>
</el-form>
el-form
的model
属性绑定作为表单查询条件的数据模型。在表单中的输入控件上,依次使用v-model
属性绑定具体的数据模型属性。
使用一个 el-button
作为表单查询按钮,并绑定click
事件到一个事件处理器onSubmit
。
在 js 中定义数据模型和事件处理器:
new Vue({
el: "#app",
methods: {
// ...
onSubmit() {
console.log('submit!');
loadBrands(this);
}
},
data() {
return {
// ...
query: {
status: null,
brandName: '',
companyName: ''
}
}
},
// ...
})
在具体加载品牌数据的方法中使用表单的查询条件:
function loadBrands(_vue){
axios({
method: "POST",
url: "/login-demo/brand/query",
data: _vue.query
})
.then((resp) => {
// ...
});
}
3.3.对话框
添加两个按钮,分别用于批量删除和新增:
<el-row>
<el-button type="danger" plain>批量删除</el-button>
<el-button type="primary" plain>新增</el-button>
</el-row>
添加一个对话框(Dialog),并用新增按钮可以打开:
<el-row>
<el-button type="danger" plain>批量删除</el-button>
<el-button type="primary" @click="dialogVisible=true" plain>新增</el-button>
</el-row>
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%">
<span>这是一段信息</span>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
</span>
</el-dialog>
需要添加一个用于控制对话框打开关闭的数据模型:
new Vue({
el: "#app",
// ...
data() {
return {
// ...
dialogVisible: false
}
},
// ...
})
在对话框中嵌套一个表单用于填写新增数据:
<el-dialog
title="新增品牌"
:visible.sync="dialogVisible"
width="30%">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="品牌名称">
<el-input v-model="form.brandName"></el-input>
</el-form-item>
<el-form-item label="企业名称">
<el-input v-model="form.companyName"></el-input>
</el-form-item>
<el-form-item label="排序">
<el-input v-model="form.ordered"></el-input>
</el-form-item>
<el-form-item label="品牌介绍">
<el-input type="textarea" v-model="form.description"></el-input>
</el-form-item>
<el-form-item label="状态">
<el-switch v-model="form.status"
active-value="0"
inactive-value="1"></el-switch>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="onFormSubmit">确认</el-button>
<el-button @click="dialogVisible = false">取消</el-button>
</el-form-item>
</el-form>
</el-dialog>
js 的部分这里不再赘述,可以查看完整示例。
3.4.消息提示
通常我们希望成功修改数据后有一个弹出消息提醒用户,并在若干秒后自动消失。对应的 Element 组件是。
实现也很简单:
new Vue({
el: "#app",
methods: {
// ...
onFormSubmit() {
// 新增品牌 dialog 提交
let _vue = this;
axios({
// ...
}).then((resp) => {
// ...
_vue.$message({
message: '添加品牌成功',
type: 'success'
});
});
},
// ...
},
// ...
})
3.5.弹框
批量删除很简单:
<el-button type="danger" @click="batchDeleteBrands" plain>批量删除</el-button>
对应的 js:
batchDeleteBrands(){
let ids = [];
this.multipleSelection.forEach((brand)=>{
ids.push(brand.id);
});
let _vue = this;
axios({
method: "POST",
url: "/login-demo/brand/batchDelete",
data: ids
}).then((resp)=>{
loadBrands(_vue);
_vue.$message({
message: '批量删除成功',
type: 'success'
});
});
}
不过一般为了避免误操作,需要给删除功能增加一个用于确认的:
openBatchDeleteConfirm() {
this.$confirm('此操作将永久删除品牌, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.batchDeleteBrands();
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
让批量删除按钮点击事件绑定到这个方法:
<el-button type="danger" @click="openBatchDeleteConfirm" plain>批量删除</el-button>
3.6.分页
添加分页相关组件:
<div class="block">
<span class="demonstration">分页</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="page.currentPage"
:page-sizes="[5, 10, 15, 20]"
:page-size="page.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="page.total">
</el-pagination>
</div>
size-change
事件会在每页数据条数发生改变时调用。
current-change
事件会在当前页码改变时调用。
current-page
属性表示的是当前页码。
page-size
属性表示的是当前每页展示的条数。
total
属性表示的是总的数据条数。
为分页相关的信息添加数据模型:
data() {
return {
// ...
page: {
currentPage: 1,
pageSize: 5,
total: 5
}
}
},
修改数据加载方法,传入参数中添加分页相关参数:
function loadBrands(_vue) {
axios({
method: "POST",
url: "/login-demo/brand/query",
data: {
query: _vue.query,
page: {
size: _vue.page.pageSize,
currentPage: _vue.page.currentPage
}
}
})
.then((resp) => {
_vue.brands = resp.data.list;
_vue.brands.forEach((brand) => {
brand.editUrl = "/login-demo/brand/edit?id=" + brand.id;
brand.deleteUrl = "/login-demo/brand/delete?id=" + brand.id;
brand.statusText = brand.status === 0 ? "启用" : "禁用";
});
_vue.page.total = resp.data.resultPage.total;
});
}
返回的结果除了填充表格数据,也要设置分页数据中的总数据条数。
The End,谢谢阅读。
本文的完整示例可以从获取。
文章评论