首页 > 技术文章 > 前端学习十(视图组件、element-ui应用)

whitewall 2021-12-08 21:50 原文

一、视图组件

模板如下,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>
View Code

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>
View Code

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>
View Code

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>
View Code

二、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>
View Code

引用见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)

推荐阅读