一、视图组件
模板如下,export default例举了常用的对象。style的scoped属性是为了防止组件之间的样式污染,还有lang属性是预编译相关的东西
<template></template> <script> export default { data() { return {} }, methods: {}, components: {}, mounted() {}, } </script> <style scoped> </style>
下面把练习项目时的vue组件列出来,element-ui应用目录下会细讲
Login.vue
<template> <div> <div class="box"> <el-card class="box-card"> <h3 class="title">自动化平台登录</h3> <!-- 然后在template中使用定义的规则 --> <!-- el-form通过rules绑定校验规则 --> <el-form :model="form" :rules="loginRules" ref="loginRef"> <!-- el-form-ite通过prop制定校验字段 --> <el-form-item prop="username"> <el-input placeholder="请输入账号" prefix-icon="el-icon-user-solid" v-model="form.username" ></el-input> </el-form-item> <el-form-item prop="password"> <el-input placeholder="请输入密码" prefix-icon="el-icon-lock" v-model="form.password" :show-password="true" ></el-input> </el-form-item> <!-- <el-form-item label="记住账号"> <el-switch v-model="form.status"></el-switch> </el-form-item> --> <el-form-item class="btn"> <el-button type="primary" @click="login" >点击登录</el-button > </el-form-item> </el-form> </el-card> </div> </div> </template> <script> export default { data() { return { form: { username: 'musen123', password: '123456', status: false, }, // 先定义字段规则 loginRules: { username: [ { required: true, message: '请输入账号', trigger: 'blur' }, ], password: [ { required: true, message: '请输入密码', trigger: 'blur' }, ], }, } }, methods: { login() { // 判断是否需要记住账号 if (this.form.status) { window.localStorage.setItem('username', this.form.username) } else { window.localStorage.removeItem('username') } // 在el-form标签通过ref属性来设置表单引用对象(见上一步) // 在点击登录的处理函数中,通过this.$refs.loginRef获取表单对象,并调用表单对象validate方法进行校验 this.$refs.loginRef.validate(async (res) => { // res为验证的结果,验证通过为true,否则为false if (!res) return const r = await this.$req.loginApi(this.form) if (r.status === 200) { this.$message({ showClose: true, message: '登录成功', type: 'success', duration: 1000, }) const token = r.data.token window.sessionStorage.setItem('token', token) this.$router.push('/home') } else { console.log('=====测试') this.$message({ showClose: true, message: '登录失败', type: 'error', }) } }) }, }, // 数据挂载之后执行的钩子函数 // mounted() { // console.log('钩子函数mounted') // this.form.username = window.localStorage.getItem('username') // }, } </script> <style scoped> .box { width: 100%; height: 100%; position: fixed; background: url(../assets/name.jpg); } .box-card { width: 35%; height: 330px; margin: auto; margin-top: 100px; background-color: rgba(0, 0, 0, 0.2); border: 0px; } .title { color: deepskyblue; text-align: center; } .btn { text-align: center; } </style>
Home.vue
<template> <div> <div class="box1"> <el-container> <el-header> <div class="title">测试开发平台</div> <div class="loginOut"> <el-popconfirm title="是否确认退出登录?" @confirm="loginOut" > <div slot="reference">退出登录</div> </el-popconfirm> </div> </el-header> <el-container> <el-aside width="200px"> <el-menu :default-active="default_active" class="el-menu-vertical-demo" background-color="#545c64" text-color="#fff" active-text-color="#ffd04b" :router="true" unique-opened > <el-submenu index="1"> <template slot="title"> <i class="el-icon-s-home"></i> <span>项目管理</span> </template> <el-menu-item index="/project" >项目列表</el-menu-item > </el-submenu> <el-submenu index="2"> <template slot="title"> <i class="el-icon-star-off"></i> <span>接口管理</span> </template> <el-menu-item index="/interface" >接口列表</el-menu-item > <el-menu-item index="2-2" >添加接口</el-menu-item > <el-submenu index="2-3"> <template slot="title">选项3</template> <el-menu-item index="2-3-1" >选项1</el-menu-item > </el-submenu> </el-submenu> <el-submenu index="3"> <template slot="title"> <i class="el-icon-s-help"></i> <span>用例管理</span> </template> <el-menu-item index="/cases" >用例列表</el-menu-item > <el-menu-item index="/cases/edit" >用例编辑</el-menu-item > </el-submenu> </el-menu> </el-aside> <el-main><router-view></router-view></el-main> </el-container> </el-container> </div> </div> </template> <script> export default { data() { return { default_active: '/project', } }, methods: { loginOut() { window.sessionStorage.removeItem('token') this.$router.push('/login') }, }, mounted() { this.default_active = this.$route.path }, } </script> <style scoped> /* .box1 { overflow: hidden; } .title { float: left; } */ .el-header { background: #545c64; margin-bottom: 5px; } .title { text-align: left; font: normal 25px/60px 'Microsoft YaHei'; width: 90%; float: left; color: white; } .loginOut { float: right; width: 10%; float: right; text-align: center; line-height: 60px; } .loginOut :hover { background: rgb(98, 207, 247); } div ::v-deep .el-menu { height: 100%; } .el-main { padding: 10px; } .el-aside { min-height: 650px; } </style>
Projects.vue
<template> <div> <!-- <el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item> <el-breadcrumb-item>项目管理</el-breadcrumb-item> <el-breadcrumb-item>项目列表</el-breadcrumb-item> </el-breadcrumb> --> <view-titles :t="titles"></view-titles> <el-button type="primary" icon="el-icon-plus" size="small" @click="addP" >添加项目</el-button > <el-card> <el-table :data="tableData" style="width: 100%"> <el-table-column type="index" label="序号"> </el-table-column> <el-table-column prop="name" label="项目名称" width="180"> </el-table-column> <el-table-column prop="create_time" label="创建时间" width="180" > </el-table-column> <el-table-column prop="desc" label="描述"> </el-table-column> <el-table-column prop="leader" label="负责人"> </el-table-column> <el-table-column prop="tester" label="测试"> </el-table-column> <el-table-column fixed="right" label="操作" width="100"> <template slot-scope="scope"> <el-button @click="editP(scope.row)" type="text" size="small" >编辑</el-button > <el-button type="text" size="small" @click="deleteP(scope.row.id)" >删除</el-button > </template> </el-table-column> </el-table> </el-card> <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page" :page-sizes="[10, 20, 50, 100]" :page-size="size" layout="total, sizes, prev, pager, next, jumper" :total="total" > </el-pagination> <el-dialog title="编辑项目" :visible.sync="dlgEditP"> <el-form :model="editData" label-width="80px" size="small "> <el-form-item label="项目名称"> <el-input v-model="editData.name" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="项目描述"> <el-input v-model="editData.desc" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="负责人"> <el-input v-model="editData.leader" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="测试人员"> <el-input v-model="editData.tester" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="研发"> <el-input v-model="editData.programmer" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="发布应用"> <el-input v-model="editData.publish_app" autocomplete="off" ></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dlgEditP = false">取 消</el-button> <el-button type="primary" @click="editPro">确 定</el-button> </div> </el-dialog> <el-dialog title="添加项目" :visible.sync="dlgAddP"> <el-form :model="addData" label-width="80px" size="small "> <el-form-item label="项目名称"> <el-input v-model="addData.name" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="项目描述"> <el-input v-model="addData.desc" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="负责人"> <el-input v-model="addData.leader" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="测试人员"> <el-input v-model="addData.tester" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="研发"> <el-input v-model="addData.programmer" autocomplete="off" ></el-input> </el-form-item> <el-form-item label="发布应用"> <el-input v-model="addData.publish_app" autocomplete="off" ></el-input> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="dlgAddP = false">取 消</el-button> <el-button type="primary" @click="addPro">确 定</el-button> </div> </el-dialog> </div> </template> <script> import BreadCrumb from '@/components/BreadCrumb' export default { data() { return { titles: ['项目管理', '项目列表'], tableData: [], page: 1, total: 0, size: 10, dlgEditP: false, editData: {}, dlgAddP: false, addData: {}, } }, methods: { // 获取项目 async getProjects() { const r = await this.$req.getProjects({ page: this.page, size: this.size, }) if (r.status === 200) { this.tableData = r.data.results this.total = r.data.count } else { alert('获取项目失败') } }, // 每页数据 handleSizeChange(newSize) { this.size = newSize this.page = 1 this.getProjects() }, // 翻页 handleCurrentChange(newPage) { this.page = newPage this.getProjects() }, // 删除项目 async deleteP(id) { const r = await this.$req.deleteProject(id) if (r.status == 204) { this.$message({ showClose: true, message: '删除成功', type: 'success', duration: 1000, }) this.getProjects() } else { this.$message({ showClose: true, message: '删除失败', type: 'error', }) } }, editP(data) { console.log('点击编辑', typeof data) this.dlgEditP = true // 浅拷贝,复制的内存地址,data是一个对象。浅拷贝可以避免取消编辑后,数据不能还原的问题 this.editData = { ...data } }, // 编辑项目 async editPro() { const r = await this.$req.updateProject( this.editData.id, this.editData ) if (r.status == 200) { this.getProjects() this.dlgEditP = false this.$message({ showClose: true, message: '修改成功', type: 'success', duration: 1000, }) } else { this.$message({ showClose: true, message: '修改失败', type: 'error', }) } }, addP() { this.dlgAddP = true }, // 添加项目 async addPro() { const r = await this.$req.addProject(this.addData) if (r.status == 201) { this.getProjects() this.dlgAddP = false this.$message({ showClose: true, message: '添加成功', type: 'success', duration: 1000, }) this.addData = {} } else { this.$message({ showClose: true, message: '添加失败', type: 'error', }) } }, }, // 数据挂载之后执行的钩子函数 mounted() { this.getProjects() }, components: { "view-titles": BreadCrumb, }, } </script> <style scoped> .el-breadcrumb { margin-bottom: 10px; } .el-button { margin-bottom: 5px; } div ::v-deep .el-card__body { padding: 0px; } div ::v-deep .el-form-item { margin-bottom: 10px; } </style>
EditCase.vue
<template> <div class="case_edit"> <view-titles :t="titles"></view-titles> <el-card> <el-divider content-position="left">Api</el-divider> <el-row :gutter="20"> <el-col :span="4"> <el-select v-model="value" placeholder="请选择"> </el-select> </el-col> <el-col :span="8"> <el-input placeholder="请输入内容" v-model="input1"> <template slot="prepend">Host</template> </el-input></el-col > <el-col :span="8"> <el-input placeholder="请输入内容" v-model="input1"> <template slot="prepend">接口地址</template> </el-input></el-col > <el-col :span="4"> <el-button type="primary" icon="el-icon-s-promotion">运行</el-button></el-col > </el-row> </el-card> </div> </template> <script> import BreadCrumb from '@/components/BreadCrumb' export default { data() { return { titles: ['用例管理', '用例编辑'], } }, components: { 'view-titles': BreadCrumb, }, } </script> <style scoped> .el-divider__text { color: rgb(64, 144, 201); font-weight: bold; } </style>
二、element-ui应用
1、Form 表单==输入框校验提示规则 ,也可以自定义规则(Login.vue)
https://element.eleme.io/#/zh-CN/component/form
// 先定义字段规则 loginRules: { username: [ { required: true, message: '请输入账号', trigger: 'blur' }, ] }
<!-- 然后在 el-form通过rules绑定校验规则 --> <el-form :model="form" :rules="loginRules" ref="loginRef"> <!-- 最后在 el-form-ite通过prop制定校验字段 --> <el-form-item prop="username"> <el-input placeholder="请输入账号" prefix-icon="el-icon-user-solid" v-model="form.username"></el-input> </el-form-item> </el-form>
2、按钮提交时表单校验提示(Login.vue)
// 在el-form标签通过ref属性来设置表单引用对象(见上一步) // 在点击登录的处理函数中,通过this.$refs.loginRef获取表单对象,并调用表单对象validate方法进行校验 this.$refs.loginRef.validate(async (res) => { // res为验证的结果,验证通过为true,否则为false if (!res) return }
3、Switch 开关==记住账号(Login.vue)
https://element.eleme.io/#/zh-CN/component/switch
4、钩子函数mounted的使用,示例是进入到项目列表页面时调用的获取项目数据的方法
// vue组件挂载之后执行的钩子函数 mounted() { this.getProjects() },
5、Message 消息提示(Login.vue)
https://element.eleme.io/#/zh-CN/component/message
6、 图标 icon https://element.eleme.io/#/zh-CN/component/icon
带 icon 的输入框 https://element.eleme.io/#/zh-CN/component/input
7、容器布局(Home.vue)
https://element.eleme.io/#/zh-CN/component/container/
8、Popconfirm 气泡确认框==退出登录提示(Home.vue)
https://element.eleme.io/#/zh-CN/component/popconfirm
9、NavMenu 导航菜单==侧边栏导航、顶部栏导航(Home.vue)
https://element.eleme.io/#/zh-CN/component/menu
a、router属性,启用该模式会在激活导航时以 index 作为 path 进行路由跳转
b、default-active属性,默认激活菜单,填index
10、刷新页面时,显示菜单激活问题(Home.vue)
使用钩子函数mounted(),获取当前路径,再赋值给default-active(element-ui侧边导航栏的属性)
mounted() { this.default_active = this.$route.path }
11、页面信息展示部分因为都是相同的位置,且都在父组件Home.vue中,所以需要用到子路由,以及通过重定向默认展示子路由信息(见上一节)
12、发现修改element-ui样式不生效,可以使用 ::v-deep样式穿透 解决(Home.vue)
div ::v-deep .el-menu { height: 100%; }
13、Breadcrumb 面包屑的封装和引用
https://element.eleme.io/#/zh-CN/component/breadcrumb
封装
<template> <el-breadcrumb separator-class="el-icon-arrow-right"> <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item> <el-breadcrumb-item v-for="(value,index) in t" :key='index'>{{value}}</el-breadcrumb-item> </el-breadcrumb> </template> <script> export default { props: ['t'], } </script> <style scoped> </style>
引用见Projects.vue
14、表格
https://element.eleme.io/#/zh-CN/component/table
编辑和删除事件可以传入本行数据信息
editP(data) { console.log('点击编辑', data) this.dlgEditP = true // 浅拷贝,复制的内存地址,data是一个对象。浅拷贝可以避免取消编辑后,数据不能还原的问题 this.editData = { ...data } }
15、分页
https://element.eleme.io/#/zh-CN/component/pagination
// 切换每页数据条数,事件触发page置为1,再获取数据信息 handleSizeChange(newSize) { this.size = newSize this.page = 1 this.getProjects() }, // 翻页 handleCurrentChange(newPage) { this.page = newPage this.getProjects() }
16、对话框
https://element.eleme.io/#/zh-CN/component/dialog
属性 visible.sync 默认为false,即不展示;
点击编辑置为true,编辑页面取消和确认置为false;
添加项目时,点击确认后,表单数据得置为空。不然下次新增会带入
17、分割线
https://element.eleme.io/#/zh-CN/component/divider
18、分栏间隔
https://element.eleme.io/#/zh-CN/component/layout
gutter属性控制两栏之间的间隔,span属性控制该栏宽度(span属性加起来不能超过24)