一.介绍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>