1. 用户管理

1.1. user页面下的diolog表单

  本节课完成user页面下的diolog表单,表单里的元素都是动态渲染,以一个CommonForm组件的形式放入user页面。
Vue Web开发(九)-LMLPHP

  运用Element ui Form表单。
Vue Web开发(九)-LMLPHP

1.1.1. CommonForm组件

  在src/components下新建CommonForm.vue组件,添加props,用于接受3个参数,formLabel为一个数组,form的相关配置,form的表单数据,类型为Object,表单布局inline,为一个布尔值。el-form添加属性,首先是ref标识,可以通过refs拿到ref实例,label-width为初始高度,但是会根据内容变化而变化,并不固定。model用来数据的双向绑定(重要),我们传入的数据是form。inline属性表示dialog样式,inline表示上下排列。对传入的form进行遍历,label表示表单域名称。表单组件有input(姓名、年龄、地址)、select(性别选择)、switch、datepicker(日期)、option(下拉)。
  首先判断组件的type,input组件设置placeholder属性,表示input框内的文字,使用字符串拼接。v-model进行数据绑定,拿到form下面的[item.model],form前面已经model过了,这里就可以使用。switch、select()、switch、datepicker、option的方法也类似。
  最后对组件进行扩展,slot后面会讲个slot的作用。

//src/components/CommonForm.vue
<template>
    <el-form ref="form" label-width="100px" :model="form" :inline="inline">
        <el-form-item v-for="item in formLabel" :key="item.label" :label="item.label">
            <el-input
                    v-if="item.type === 'input'"
                    :placeholder="'请输入'+item.label"
                    v-model="form[item.model]">
            </el-input>
            <el-switch
                    v-if="item.type === 'switch'"
                    v-model="form[item.model]">
            </el-switch>
            <el-date-picker
                    v-if="item.type === 'date'"
                    type="date"
                    value-format="yyyy-MM-dd"
                    placeholder="选择日期"
                    v-model="form[item.model]">
            </el-date-picker>
            <el-select
                    v-if="item.type === 'select'"
                    placeholder="请选择"
                    v-model="form[item.model]">
                <el-option
                        v-for="item in item.opts"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value">
                </el-option>
            </el-select>
        </el-form-item>
        <!-- 扩展如果当前组件否不满足-->
        <el-form-item>
            <slot></slot>
        </el-form-item>
    </el-form>
</template>
<script>
    export default {
        name: 'CommonForm',
        // 由外部组件传入数据。
        props: {
            formLabel: Array,
            form: {},
            inline: Boolean,
        },
        data() {
            return{}
        }
    }
</script>

1.1.2. User引入CommonForm

  (1)在//src/views/user/ondex.vue引入CommonForm。

//src/views/user/index.vue
 <common-form
    :formLabel="operateFormLabel"
     :form="operateForm"
      :inline="true"
       ref="form">
</common-form>

  (2)添加样式,弹性布局,左右两边靠边,上下对齐。

<style lang="less" scoped>
.manage-header{
    display: flex;
    justify-content: space-between;
    align-items: center;
}
</style>

  (3)添加请求方法。

 methods: {
            confirm() {
                if (this.operateType === 'edit') {
                    this.$http.post('/user/edit', this.operateForm).then(res => {
                        console.log(res)
                        this.isShow = false
                        this.getList()
                    })
                } else {
                    this.$http.post('/user/add', this.operateForm).then(res => {
                        console.log(res)
                        this.isShow = false
                        this.getList()
                    })
                }
            },
            addUser() {
                this.isShow = true,
                    this.operateType = 'add',
                    this.operateForm = {
                        name: '',
                        addr: '',
                        age: '',
                        birth: '',
                        sex: ''
                    }
            },
            getList() {

            }
        }
//src/api/mock.js
import Mock from 'mockjs'
import homeApi from './mockServeData/home.js'
import userApi from './mockServeData/user.js'
Mock.mock('/home/getData',homeApi.getStatisticalData)
Mock.mock(/user\/add/,'post',userApi.createUser)
Mock.mock(/user\/edit/,'post',userApi.updateUser)```
//src/api/mockServeData/user.js
// mock数据模拟
import Mock from 'mockjs'
// get请求从config.url获取参数,post从config.body中获取参数
function param2Obj(url) {
    const search = url.split('?')[1]
    if (!search) {
        return {}
    }
    return JSON.parse(
        '{"' +
        decodeURIComponent(search)
            .replace(/"/g, '\\"')
            .replace(/&/g, '","')
            .replace(/=/g, '":"') +
        '"}'
    )
}
let List = []
const count = 200
//模拟200条用户数据
for (let i = 0; i < count; i++) {
    List.push(
        Mock.mock({
            id: Mock.Random.guid(),
            name: Mock.Random.cname(),
            addr: Mock.mock('@county(true)'),
            'age|18-60': 1,
            birth: Mock.Random.date(),
            sex: Mock.Random.integer(0, 1)
        })
    )
}
export default {
    /**
     * 获取列表
     * 要带参数 name, page, limt; name可以不填, page,limit有默认值。
     * @param name, page, limit
     * @return {{code: number, count: number, data: *[]}}
     */
    getUserList: config => {
        //limit默认是10,因为分页器默认也是一页10个
        const {name, page = 1, limit = 10} = param2Obj(config.url)

        const mockList = List.filter(user => {
            //如果name存在会,根据name筛选数据
            if (name && user.name.indexOf(name) === -1) return false
            return true
        })
        //分页
        const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
        return {
            code: 200,
            data: {
                list: pageList,
                count: mockList.length, //数据总条数需要返回
            }
        }
    },
    /**
     * 增加用户
     * @param name, addr, age, birth, sex
     * @return {{code: number, data: {message: string}}}
     */
    createUser: config => {
        const {name, addr, age, birth, sex} = JSON.parse(config.body)
        List.unshift({
            id: Mock.Random.guid(),
            name: name,
            addr: addr,
            age: age,
            birth: birth,
            sex: sex
        })
        return {
            code: 200,
            data: {
                message: '添加成功'
            }
        }
    },
    /**
     * 删除用户
     * @param id
     * @return {*}
     */
    deleteUser: config => {
        const {id} = param2Obj(config.url)
        if (!id) {
            return {
                code: -999,
                message: '参数不正确'
            }
        } else {
            List = List.filter(u => u.id !== id)
            return {
                code: 200,
                message: '删除成功'
            }
        }
    },
    /**
     * 批量删除
     * @param id
     * @return {*}
     */
    batchremove: config => {
        let {ids} = param2Obj(config.url)
        ids = ids.split(',')
        List = List.filter(u => !ids.includes(u.id))
        return {
            code: 20000,
            data: {
                message: '批量删除成功'
            }
        }
    },

    /**
     * 修改用户
     * @param id, name, addr, age, birth, sex
     * @return {{code: number, data: {message: string}}}
     */
    updateUser: config => {
        const { id, name, addr, age, birth, sex } = JSON.parse(config.body)
        const sex_num = parseInt(sex)
        List.some(u => {
            if (u.id === id) {
                u.name = name
                u.addr = addr
                u.age = age
                u.birth = birth
                u.sex = sex_num
                return true
            }
        })
        return {
            code: 200,
            data: {
                message: '编辑成功'
            }
        }
    }
}

  operateFormLabel赋值给formLabel,operateForm赋值给form,inline默认为true,即样式为inline布局,ref拿到组件实例。加上弹窗底部footer,利用刚刚的slot标签。添加两个button。分别是“取消”“确定”。第一个button设定点击事件,将isShow设为false,第二个button添加点击事件comfirm函数,这里预留空值,type设置为primary(高亮显示)。
  在dialog外还有两个button,分别是新增和搜索。新增按钮添加addUser事件。搜索按钮添加getList事件,这里再一次引入CommonForm,因为我们需要一个input输入框,但是我们考科一通过更换数据而不是更换组件达到目标效果。注意对比两次引入CommonForm组件的不同之处。formLabel数组,包含一个对象,因为只有一个搜索框,对象里包含三个属性,model、label、type,model为自定义名称、label为输入框前的标签、type为输入类型。SearchForm存放keyworld内容。

//src/views/user/index.vue
<template>
    <div class="manage">
        <!-- dialog为弹窗内容 -->
        <el-dialog
                :title="operateType === 'add' ? '新增用户' : '更新用户'"
                :visible.sync="isShow">
            <!-- 这里冒号是将数据传送给CommonForm组件。 -->
            <common-form
                    :formLabel="operateFormLabel"
                    :form="operateForm"
                    :inline="true"
                    ref="form">
            </common-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="isShow = false">取消</el-button>
                <el-button type="primary" @click="confirm">确认</el-button>
            </div>
        </el-dialog>
        <div class="manage-header">
            <el-button type="primary" @click="addUser">+新增</el-button>
            <common-form ref="form"
                         :formLabel="formLabel"
                         :form="searchFrom"
                         :inline="true">
                <el-button type="primary" @click='getList'>+搜索</el-button>
            </common-form>
        </div>
    </div>
</template>
<script>
    import CommonForm from '../../components/CommonForm.vue'
    export default {
        name: 'User',
        components: {
            CommonForm
        },
        data() {
            return {
                operateType: 'add',
                isShow: false,
                operateFormLabel: [
                    {
                        model: 'name',
                        label: '姓名',
                        type: 'input'
                    },
                    {
                        model: 'age',
                        label: '年龄',
                        type: 'input'
                    },
                    {
                        model: 'sex',
                        label: '性别',
                        type: 'select',
                        opts: [
                            {
                                label: '男',
                                value: 1
                            },
                            {
                                label: '女',
                                value: 0
                            }
                        ]
                    },
                    {
                        model: 'birth',
                        label: '出生日期',
                        type: 'date'
                    },
                    {
                        model: 'addr',
                        label: '地址',
                        type: 'input'
                    }
                ],
                operateForm: {
                    name: '',
                    addr: '',
                    age: '',
                    birth: '',
                    sex: ''
                },
                formLabel: [
                    {
                        model: "keyword",
                        label: '',
                        type: 'input'
                    },
                ],
                searchFrom: {
                    keyword: '',
                }
            }
        },
        methods: {
            confirm() {
                if (this.operateType === 'edit') {
                    this.$http.post('/user/edit', this.operateForm).then(res => {
                        console.log(res)
                        this.isShow = false
                        this.getList()
                    })
                } else {
                    this.$http.post('/user/add', this.operateForm).then(res => {
                        console.log(res)
                        this.isShow = false
                        this.getList()
                    })
                }
            },
            addUser() {
                this.isShow = true,
                    this.operateType = 'add',
                    this.operateForm = {
                        name: '',
                        addr: '',
                        age: '',
                        birth: '',
                        sex: ''
                    }
            },
            getList() {

            }
        }
    }
</script>
<style lang="less" scoped>
    .manage-header {
        display: flex;
        flex-direction: row;
        justify-content: space-between;
        align-items: center;
    }

</style>

Vue Web开发(九)-LMLPHP
  用户表单新增diolog表单示例下载

12-18 17:56
查看更多