1. 用户管理
1.1. user页面下的diolog表单
本节课完成user页面下的diolog表单,表单里的元素都是动态渲染,以一个CommonForm组件的形式放入user页面。
运用Element ui Form表单。
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>