一.介绍ElementUI
ElementUI中文网 :Element - The world's most popular Vue UI framework
Element-Ul是饿了么前端团队推出的一款基于Vue.js 2.0 的桌面端UI框架,手机端有对应框架是Mint UI 。
(使用,学习都去官网即可。)
二.ElementUI的使用
2.1组件
2.1.1.Base
样式相关组件
①.引入
<!-- 引入样式 -->
<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>
先网站试试能不能用,比如浏览器输入https://unpkg.com/element-ui/lib/index.js,看看有没有东西。
若地址访问不通,就去bootcdn复制。
②.Layout布局
借鉴了bootstrap的布局方式,这里改成了24个分栏,做页面分隔可以更加细致。
<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>
<style>
.el-row {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.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>
bootstrap里是div自己加class。这里直接自定义了一些标签出来。
行el-row 列el-col (这些往下拉就能看到。该UI库,每个样式都会自成一个页面,详细的说明都在页面的下面)
实际上,这些标签最终会翻译成div标签。
③.布局容器Container
上下左右等等布局。
④.color色彩
Success绿色 Warning黄色 Danger红色 Info灰色
主色 Brand Color蓝色
⑤.Typography字体
黑体为主
⑥.Border边框
⑦.lcon图标
<i class="el-icon-edit"></i>
<i class="el-icon-share"></i>
<i class="el-icon-delete"></i>
<el-button type="primary" icon="el-icon-search">搜索</el-button>
使用的i标签,class属性值就是图标对应样式。按钮上也可加图标,用icon样式。
⑧.Button按钮
⑨.Link文字链接
2.1.2Form
表单相关组件
①.Radio单选框
<template>
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</template>
<script>
export default {
data () {
return {
radio: '1'
};
}
}
</script>
翻译后还是div画出的。
可点击在线运行:
html里有引入elementUI的方式。
css里有css文件里引入css的方式,若html里引入css文件,要用href标签。
示例:
新建项目,选择vue项目(普通模式),起名day20_elementUI
在index.html文件中,删除没用的,留下如下内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
</head>
<body>
<div id="app">
</div>
</body>
<script>
</script>
</html>
开始测试:
将打开的在线运行中html里引入elementUI的路径复制一份过来。
同时还需要一份css文件。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="app">
</div>
</body>
<script>
</script>
</html>
引完之后,运行一下,看看地址有没有问题。
接下来拿过元素:
从在线运行中html里复制一份页面元素。
从在线运行中html里复制一份js代码。
<body>
<div id="app">
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</div>
</body>
<script>
var Main = {
data () {
return {
radio: '1'
};
}
}
var Ctor = Vue.extend(Main)
new Ctor().$mount('#app')
</script>
好像js代码不太一样,其实一样:
创建vue对象,以前直接new vue,这里Vue.extend(Main)
<body>
<div id="app">
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</div>
</body>
<script>
var option = {
data () {
return {
radio: '1'
};
}
}
var myVue = Vue.extend(option)
new myVue().$mount('#app')
</script>
运行后,就出来想要的效果。
也可自己new vue:
<body>
<div id="app">
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
radio: '1'
};
}
})
</script>
data的配置上,以前是json对象的形式。这里是函数对象的形式,通过return把要返回的json对象返回出来。
data:function(){
return {
radio: '1'
};
}
和上面一样,是elementUI官方推荐的写法。且后面脚手架环境使用这种函数返回json对象的方式可以处理组件之间数据传递的bug问题。
故,之后就用这种方式配置data数据。
②.Checkbox多选框
③.Input输入框
④.InputNumber计数器
⑤.Select选择器
也是拿div画的。
<template>
<el-select v-model="value" placeholder="请选择">
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</template>
<script>
export default {
data() {
return {
options: [{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}],
value: ''
}
}
}
</script>
示例:
遍历的时候label和value添进去,对于:key是用v-for时vue官方推荐加的东西,key后写元素遍历时的唯一标记。
<body>
<div id="app">
<el-radio v-model="radio" label="1">备选项</el-radio>
<el-radio v-model="radio" label="2">备选项</el-radio>
<hr />
<el-select v-model="selvalue" placeholder="请选择">
<el-option
v-for="item in seloptions"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
radio: '1',
selvalue:'',
seloptions:[{
value: '选项1',
label: '黄金糕'
}, {
value: '选项2',
label: '双皮奶'
}, {
value: '选项3',
label: '蚵仔煎'
}, {
value: '选项4',
label: '龙须面'
}, {
value: '选项5',
label: '北京烤鸭'
}]
};
}
})
</script>
不用打开在线运行,就在示例复制。
⑥.Cascader级联选择器
有children就有级联。一般有children的都是一个套一个,不过一般不超过三级,否则用户体验效果不好。
⑦.Switch开关
⑧.Slider滑块
一般手机端用的多,比如调音量和亮度。
⑨.TimePicker时间选择器
⑩.DatePicker日期选择器
⑪.DateTimePicker日期时间选择器
⑫.Upload上传
⑬.Rate评分
⑭.ColorPicker颜色选择器
⑮.Transfer穿梭框
之前做过一个自己模拟出来的。
<template>
<el-transfer v-model="value" :data="data"></el-transfer>
</template>
<script>
export default {
data() {
const generateData = _ => {
const data = [];
for (let i = 1; i <= 15; i++) {
data.push({
key: i,
label: `备选项 ${ i }`,
disabled: i % 4 === 0
});
}
return data;
};
return {
data: generateData(),
value: [1, 4]
};
}
};
</script>
示例:
<body>
<div id="app">
<el-transfer v-model="value" :data="data"></el-transfer>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
const generateData = _ => {
const data = [];
for (let i = 1; i <= 15; i++) {
data.push({
key: i,
label: `备选项 ${ i }`,
disabled: i % 4 === 0
});
}
return data;
};
return {
data: generateData(),
value: [1, 4]
};
}
})
</script>
generateData其实是通过遍历,往data里写key,label和是否禁用disabled。
按照这个格式,自己准备generateData。
<body>
<div id="app">
<el-transfer v-model="value" :data="data"></el-transfer>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
data: [{key:1,label:'选项1',disabled:true},{key:2,label:'选项2',disabled:false}],
value: ''
};
}
})
</script>
左边叫可选项,右边叫选中项。左边列表在data里配置即可。
右边列表实际是对应选项的值。比如value: [2],选项2就跑到了右边的框,即右边的框配个value就行。
故一般提交右边的选项,只要提交value即可。
⑯.Form表单
2.1.3Data
①.Table表格
<template>
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
}
}
}
</script>
使用el-table,里面用:data绑定数据。在data里准备好要遍历的json数据。
遍历时,table没有用v-for,因为在自己代码里v-for了,不用在元素上v-for了。
并且要说清楚哪一列遍历到哪个格子上。
示例:
<body>
<div id="app">
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
prop="date"
label="日期"
width="180">
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎',
address: '上海市普陀区金沙江路 1516 弄'
}]
};
}
})
</script>
使用table时也可加按钮,会使用到一个数据插头的功能:
<body>
<div id="app">
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
label="测试"
width="180">
我的数据
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</div>
</body>
这样每一列都是定值,可以使用数据插头:
官方的例子是使用slot-scope="scope"
这里用最新的写法:
<body>
<div id="app">
<el-table
:data="tableData"
style="width: 100%">
<el-table-column
label="测试"
width="180">
<template v-slot="mytest"> <!--使用template标签,加v-slot插头,名字随便起,这里叫mytest -->
亲爱的!!! {{mytest.row.name}} <!--拿到当前行的数据,然后还是想用name,前面加了个前缀。 -->
</template>
</el-table-column>
<el-table-column
prop="name"
label="姓名"
width="180">
</el-table-column>
<el-table-column
prop="address"
label="地址">
</el-table-column>
</el-table>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
tableData: [{
date: '2016-05-02',
name: '王小虎1',
address: '上海市普陀区金沙江路 1518 弄'
}, {
date: '2016-05-04',
name: '王小虎2',
address: '上海市普陀区金沙江路 1517 弄'
}, {
date: '2016-05-01',
name: '王小虎3',
address: '上海市普陀区金沙江路 1519 弄'
}, {
date: '2016-05-03',
name: '王小虎4',
address: '上海市普陀区金沙江路 1516 弄'
}]
};
}
})
</script>
②.Tag标签
③.Progress进度条
④.Tree树形控件
<el-tree
:data="data"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]"
:props="defaultProps">
</el-tree>
<script>
export default {
data() {
return {
data: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
}
};
</script>
示例:
<body>
<div id="app">
<el-tree
:data="data"
show-checkbox
node-key="id"
:default-expanded-keys="[2, 3]"
:default-checked-keys="[5]"
:props="defaultProps">
</el-tree>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
data: [{
id: 1,
label: '一级 1',
children: [{
id: 4,
label: '二级 1-1',
children: [{
id: 9,
label: '三级 1-1-1'
}, {
id: 10,
label: '三级 1-1-2'
}]
}]
}, {
id: 2,
label: '一级 2',
children: [{
id: 5,
label: '二级 2-1'
}, {
id: 6,
label: '二级 2-2'
}]
}, {
id: 3,
label: '一级 3',
children: [{
id: 7,
label: '二级 3-1'
}, {
id: 8,
label: '二级 3-2'
}]
}],
defaultProps: {
children: 'children',
label: 'label'
}
};
}
})
</script>
修改数据:
<body>
<div id="app">
<el-tree
:data="data"
show-checkbox
node-key="myid"
:default-expanded-keys="[2, 3]"
:default-checked-keys="checkData"
:props="defaultProps">
</el-tree>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
data: [{
myid: 1,
maname: '一级 1',
subdata: [{
myid: 4,
maname: '二级 1-1',
subdata: [{
myid: 9,
maname: '三级 1-1-1'
}, {
myid: 10,
maname: '三级 1-1-2'
}]
}]
}, {
myid: 2,
maname: '一级 2',
subdata: [{
myid: 5,
maname: '二级 2-1'
}, {
myid: 6,
maname: '二级 2-2'
}]
}, {
myid: 3,
maname: '一级 3',
subdata : [{
myid: 7,
maname: '二级 3-1'
}, {
myid: 8,
maname: '二级 3-2'
}]
}],
defaultProps: {
children: 'subdata',
label: 'maname'
},
checkData:[9,10]
};
}
})
</script>
⑤.Pagination分页
在前端计算按钮的生成,需要传的是总记录数和每页显示的记录数
<template>
<div class="block">
<span class="demonstration">显示总数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage1"
:page-size="100"
layout="total, prev, pager, next"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">调整每页显示条数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage2"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="sizes, prev, pager, next"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">直接前往</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage3"
:page-size="100"
layout="prev, pager, next, jumper"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">完整功能</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</template>
<script>
export default {
methods: {
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
}
},
data() {
return {
currentPage1: 5,
currentPage2: 5,
currentPage3: 5,
currentPage4: 4
};
}
}
</script>
示例:
<body>
<div id="app">
<div class="block">
<span class="demonstration">显示总数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage1"
:page-size="100"
layout="total, prev, pager, next"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">调整每页显示条数</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage2"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="sizes, prev, pager, next"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">直接前往</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage3"
:page-size="100"
layout="prev, pager, next, jumper"
:total="1000">
</el-pagination>
</div>
<div class="block">
<span class="demonstration">完整功能</span>
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
currentPage1: 5,
currentPage2: 5,
currentPage3: 5,
currentPage4: 4
};
},
methods: {
handleSizeChange(val) {
console.log(`每页 ${val} 条`);
},
handleCurrentChange(val) {
console.log(`当前页: ${val}`);
}
}
})
</script>
size-change(pageSize 改变时会触发)和current-change(currentPage 改变时会触发)是它定义的两个事件。
⑥.Badge标记
评论,回复带一个角标
⑦.Avatar头像
等等...
2.1.4Notice
①.警告框
②.Loding加载
③.Message消息提示
2.1.5Navigation
①.NavMenu导航菜单
三.使用elementUI做页面
3.1登录页面
①.新建loginPage.html
~~~html
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
};
},
methods: {
}
})
</script>
</html> ~
使用卡片组件做登录框,将代码复制进来:
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
</style>
</head>
<body>
<div id="app">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>卡片名称</span>
<el-button style="float: right; padding: 3px 0" type="text">操作按钮</el-button>
</div>
<div v-for="o in 4" :key="o" class="text item">
{{'列表内容 ' + o }}
</div>
</el-card>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
};
},
methods: {
}
})
</script>
</html>
测试后发现,现在卡片在左上角,需要调整样式:
给
<el-card class="box-card">
加一个样式:
<el-card class="box-card mycard">
同时在style标签加:
.mycard{
margin:240px auto;
}
现在修改标题为登录,同时删除操作按钮:
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div v-for="o in 4" :key="o" class="text item">
{{'列表内容 ' + o }}
</div>
</el-card>
</div>
</body>
下面是主体内容,将表单组件相关代码复制进来:
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<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="mySubmit()">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</body>
引入的el-form标签上有数据双向绑定(:model="form"),需要将绑定的form也拉过来:
return {
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
}
};
最下面还绑定了点击事件(@click="mySubmit()"),对应的将函数补全:
methods: {
mySubmit(){
console.log("提交数据");
}
}
运行没报错。现在去掉表单里没用的框,并将内容修改为用户名,同时修改form里绑定的数据为username:
对应的删掉下面form里没用的数据。
然后加一个密码框(复制登录框,并修改参数):
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="用户名">
<el-input v-model="form.username"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.userpwd"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</body>
<script>
new Vue({
el:"#app",
data () {
return {
form: {
username: '',
userpwd:''
}
};
},
methods: {
mySubmit(){
console.log("提交数据");
}
}
})
</script>
密码要用密码框,找到输入框里的密码框,使用show-password
属性即可得到一个可切换显示隐藏的密码框:
(加该属性即可)
<el-form-item label="密码">
<el-input v-model="form.userpwd" show-password></el-input>
</el-form-item>
元素上用model绑定的是form对象(:model="form"),用v-model绑定的是form对象的子对象(v-model="form.username"和v-model="form.userpwd"),点击按钮,我们提交的就应该是用户名和密码。
在点击事件中增加:
console.log(this.form);
会在控制台看到:
是键值对结构。json对象最终要传的是url拼接,故引入qs。
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.js"></script>
然后用qs里的方法将数据转化一下:
console.log(window.Qs.stringify(this.form));
此时控制台输出:
username=123&userpwd=456
以上,登录的基本功能就做完了。
②.将登录的功能做的复杂一点:
在用户名对应的框右边加小人图标,密码对应的框右边加锁的图标。
也是输入框,里面有带 icon 的输入框,可加前后缀。
(可以通过 prefix-icon
和 suffix-icon
属性在 input 组件首部和尾部增加显示图标,也可以通过 slot 来放置图标。)
这里加后缀:(加suffix-icon属性即可):
<el-form-item label="用户名">
<el-input v-model="form.username" suffix-icon="el-icon-date"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-date"></el-input>
</el-form-item>
图标还不是要求的图标,在图标里找需要的图标,修改后:
<el-form-item label="用户名">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
做登录框还会有数据效验,还是在表单组件里,有表单验证:
(Form 组件提供了表单验证的功能,只需要通过 rules
属性传入约定的验证规则,并将 Form-Item 的 prop
属性设置为需校验的字段名即可。)
在
<el-form ref="form" :model="form" label-width="80px">
加rules属性:
<el-form ref="form" rules="rules" :model="form" label-width="80px">
rules是绑定的数据,故需要在data里定义出来。和form同级,也是json格式。需要配置的东西从例子复制(只复制效验密码的部分):
data () {
return {
form: {
username: '',
userpwd:''
},
rules:{
userpwd: [
{ required: true, message: '请输入活动名称', trigger: 'blur' },
{ min: 3, max: 5, message: '长度在 3 到 5 个字符', trigger: 'blur' }
]
}
}
第一个规则里:required是必填项。trigger是触发器的意思,blur是失去焦点时触发。
修改内容:
rules:{
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
最后在密码框对应的 Form-Item里加prop属性:
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
代码最终如下:
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="form" :rules="rules" :model="form" label-width="80px">
<el-form-item label="用户名">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
mySubmit(){
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
}
},
data () {
return {
form: {
username: '',
userpwd:''
},
rules: {
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
};
}
})
</script>
以上的数据效验只是一个样式,本身却没啥效果。此时还需提交时调用校验效果,将点击提交部分的代码复制进来:
methods: {
mySubmit(){
this.$refs[formName].validate((valid) => {
if (valid) {
alert('submit!');
} else {
console.log('error submit!!');
return false;
}
});
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
}
}
$refs是注册给vue的组件,可通过组件名将vue里注册的组件拿出来。如何给vue注册组件,只需在标签里加ref属性。上面已经用ref=form注册过组件,组件名form现在改成myform。
validate方法是来触发验证规则的,其参数就是验证的结果。
改成自己的:
methods: {
mySubmit(){
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
} else {
console.log('数据有误 不能提交');
return false;
}
});
}
}
以上就将校验效果完整的做完了。此时密码框前面有一个*,现在不希望出现它。还是Form表单,拉到最下面。在Form Attributes部分有
参数 | 说明 | 类型 | 可选值 | 默认值 |
hide-required-asterisk | 是否隐藏必填字段的标签旁边的红色星号 | boolean | — | false |
因为是Form Attributes,故属性要加在form上。
<el-form ref="myform" :rules="rules" :model="form" label-width="80px" hide-required-asterisk>
将两个按钮内容改一下,分别是登录和重置。
<el-form-item>
<el-button type="primary" @click="mySubmit()">登录</el-button>
<el-button>重置</el-button>
</el-form-item>
重置清空的效果:点击该按钮,账号和密码框能全部清掉。
还是Form表单,表单验证部分有重置,复制相关代码,改成自己的:
(要求form-item上有prop属性)
<el-button @click="resetForm()">重置</el-button>
对应的:
resetForm(formName) {
this.$refs['myform'].resetFields(); //通过this.$refs['myform']找到组件,调用resetFields方法清空数据
}
此时只有密码框重置,因为用户框没加prop属性,此时加上该属性:
<el-form-item label="用户名" prop="username">
最终的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.js"></script>
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
.mycard{
margin:240px auto;
}
</style>
</head>
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="myform" :rules="rules" :model="form" label-width="80px" hide-required-asterisk>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">登录</el-button>
<el-button @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
mySubmit(){
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
} else {
console.log('数据有误 不能提交');
return false;
}
});
},
resetForm(formName) {
this.$refs['myform'].resetFields(); //通过this.$refs['myform']找到组件,调用resetFields方法清空数据
}
},
data () {
return {
form: {
username: '',
userpwd:''
},
rules: {
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
};
}
})
</script>
</html>
3.2主菜单页面
新建mainPage.html,登录成功后跳转到主菜单页面。
先在登录页面添加跳转:
mySubmit(){
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
//后台服务接口返回登录成功
location.href = "mainPage.html";
} else {
console.log('数据有误 不能提交');
return false;
}
});
}
接下来做主菜单页面:
①.框架里添加布局
框架如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.js"></script>
<style>
</style>
</head>
<body>
<div id="app">
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
},
data () {
return {
};
}
})
</script>
</html>
在组件的Basic里找Container布局容器:
找上左右布局,复制body部分代码,同时将样式也复制进去:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.js"></script>
<style>
.text {
font-size: 14px;
}
.item {
margin-bottom: 18px;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both
}
.box-card {
width: 480px;
}
.mycard{
margin:240px auto;
}
</style>
</head>
<body>
<div id="app">
<el-card class="box-card mycard">
<div slot="header" class="clearfix">
<span>登录</span>
</div>
<div class="text item">
<el-form ref="myform" :rules="rules" :model="form" label-width="80px" hide-required-asterisk>
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" suffix-icon="el-icon-user"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userpwd">
<el-input v-model="form.userpwd" show-password suffix-icon="el-icon-lock"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="mySubmit()">登录</el-button>
<el-button @click="resetForm()">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-card>
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
mySubmit(){
this.$refs['myform'].validate((valid) => {
if (valid) {
console.log("提交数据");
console.log(window.Qs.stringify(this.form));
//后台服务接口返回登录成功
location.href = "mainPage.html";
} else {
console.log('数据有误 不能提交');
return false;
}
});
},
resetForm(formName) {
this.$refs['myform'].resetFields(); //通过this.$refs['myform']找到组件,调用resetFields方法清空数据
}
},
data () {
return {
form: {
username: '',
userpwd:''
},
rules: {
userpwd: [
{ required: true, message: '请输入密码', trigger: 'blur' },
{ min: 6, max: 8, message: '长度在 6 到 8 个字符', trigger: 'blur' }
]
}
};
}
})
</script>
</html>
布局未占满整个页面,需调整:
需要让html占满,body占满,div占满,元素占满。在style样式里:
<style>
html,body{
height:100%;
width:100%;
margin:0px ;
padding:0px;
}
#app{
height:100%;
}
.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;
/* height:100%; 这里也加个样式,后来发现不生效,说明被覆盖 */
}
body .el-container { /*其实是选择器的问题,从外面整一个 */
height:100%;
}
.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>
此时布局占满整个页面
②.布局里添加导航菜单
左边是导航,找导航菜单,复制代码:
(有两组导航条,选择一个复制。同时将栅格拉满,占满24)
<body>
<div id="app">
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<el-col :span="24">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<el-submenu index="1">
<template slot="title">
<i class="el-icon-location"></i>
<span>导航一</span>
</template>
<el-menu-item-group>
<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">选项1</el-menu-item>
</el-submenu>
</el-submenu>
<el-menu-item index="2">
<i class="el-icon-menu"></i>
<span slot="title">导航二</span>
</el-menu-item>
<el-menu-item index="3" disabled>
<i class="el-icon-document"></i>
<span slot="title">导航三</span>
</el-menu-item>
<el-menu-item index="4">
<i class="el-icon-setting"></i>
<span slot="title">导航四</span>
</el-menu-item>
</el-menu>
</el-col>
</el-row>
</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
},
data () {
return {
};
}
})
</script>
一共四组。el-submenu里包含子菜单(导航条一),el-menu-item里不包含子菜单(二,三,四)。带禁用效果的(三)。
含子菜单的可用el-submenu展示主菜单结构,用el-menu-item-group分按钮组,用el-menu-item做按钮选项。
知道这些,就可自己做导航菜单了:
<el-submenu index="5">
<template slot="title">
<i class="el-icon-document"></i>
<span>系统参数</span>
</template>
<el-menu-item index="51">参数配置</el-menu-item>
<el-menu-item index="52">全局参数</el-menu-item>
</el-submenu>
不同用户的权限不同,导航条也就不同,应动态生成。
如下,准备一组假数据:
data () {
return {
menuList:[{"menuid":"11","menuname":"系统管理"},{"menuid":"12","menuname":"用户管理"}]
};
}
然后el-submenu里套el-menu-item,故加v-for。index属性是菜单的编号,做数据绑定,要:index。菜单编号是menu.menuid
<el-submenu v-for="menu in menuList" :index="menu.menuid">
<template slot="title">
<i class="el-icon-document"></i>
<span>{{menu.menuname}}</span>
</template>
<el-menu-item index="51">参数配置</el-menu-item>
<el-menu-item index="52">全局参数</el-menu-item>
</el-submenu>
主菜单里还可以有子菜单,将假数据填入:
data () {
return {
menuList:[{"menuid":"11","menuname":"系统管理","icon":"el-icon-s-tools","submenu":
[{"menuid":"11001","menuname":"系统参数"},
{"menuid":"11002","menuname":"系统参数"},
{"menuid":"11003","menuname":"系统参数"}]},
{"menuid":"12","menuname":"用户管理","icon":"el-icon-s-phone","submenu":
[{"menuid":"12001","menuname":"用户入职"},
{"menuid":"12002","menuname":"用户离职"}]}]
};
}
(拼json格式,最好在 在线json去效验)
然后添子数据:
(v-for的另一个用户,v-for里套v-for,循环可嵌套)
<!--给不同用户展示不同的菜单,主要功能点还是在后台,后台根据用户的权限给前台准备好查询菜单的服务接口-->
<el-submenu v-for="menu in menuList" :index="menu.menuid">
<template slot="title">
<i class="el-icon-document"></i>
<span>{{menu.menuname}}</span>
</template>
<el-menu-item v-for="subm in menu.submenu" :index="subm.menuid">{{subm.menuname}}</el-menu-item>
</el-submenu>
最终的代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/v2.6.10/vue.js" type="text/javascript" charset="UTF-8"></script>
<script src="//unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<link href="//unpkg.com/element-ui@2.15.7/lib/theme-chalk/index.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.js"></script>
<style>
html,body{
height:100%;
width:100%;
margin:0px ;
padding:0px;
}
#app{
height:100%;
}
.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;
/* height:100%; 这里也加个样式,后来发现不生效,说明被覆盖 */
}
body .el-container {
height:100%;
}
.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>
</head>
<body>
<div id="app">
<el-container>
<el-header>Header</el-header>
<el-container>
<el-aside width="200px">
<el-col :span="24">
<el-menu
default-active="2"
class="el-menu-vertical-demo"
@open="handleOpen"
@close="handleClose"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b">
<!--给不同用户展示不同的菜单,主要功能点还是在后台,后台根据用户的权限给前台准备好查询菜单的服务接口-->
<el-submenu v-for="menu in menuList" :index="menu.menuid">
<template slot="title">
<i class="el-icon-document"></i>
<span>{{menu.menuname}}</span>
</template>
<el-menu-item v-for="subm in menu.submenu" :index="subm.menuid">{{subm.menuname}}</el-menu-item>
</el-submenu>
</el-menu>
</el-col>
</el-row>
</el-aside>
<el-main>Main</el-main>
</el-container>
</el-container>
</div>
</body>
<script>
new Vue({
el:"#app",
methods: {
handleOpen(key, keyPath) {
console.log(key, keyPath);
},
handleClose(key, keyPath) {
console.log(key, keyPath);
}
},
data () {
return {
menuList:[{"menuid":"11","menuname":"系统管理","icon":"el-icon-s-tools","submenu":
[{"menuid":"11001","menuname":"系统参数"},
{"menuid":"11002","menuname":"系统参数"},
{"menuid":"11003","menuname":"系统参数"}]},
{"menuid":"12","menuname":"用户管理","icon":"el-icon-s-phone","submenu":
[{"menuid":"12001","menuname":"用户入职"},
{"menuid":"12002","menuname":"用户离职"}
]}]
};
}
})
</script>
</html>