【Vue2+Element ui通用后台】用户列表

  • Post author:
  • Post category:vue




新增用户

首先增加一个 ‘新增’ 按钮,点击弹出对话框来新增用户。弹出框可以使用 Element UI 的

Dialog对话框

,其中

visible

表示是否显示 Dialog,支持 .sync 修饰符。我们点击新增按钮把这个标识置为 true,Dialog 即可显示

在这里插入图片描述

其中 Dialog 是一个表单,可以使用 Element UI 的

Form表单

,其中

:model = 'form'

是表单数据对象,所以我们在下面的 data 中需要定义这个数据

export default {
  name: "Home",
  data(){
    return{
      dialogVisible: false,
      form:{
        name:'',
        age:'',
        sex:'',
        birth:'',
        addr:'',
      }
    }
  }
}

然后 form 中的内容,每条都需要使用

<el-form-item>

。当垂直方向空间受限且表单较简单时,可以在一行内放置表单,可以使用

:inline="true"

需要输入的用

el-input

,性别用

el-select

选择框,form 表单中有示例代码可以直接拿过来。日期可以使用

日期选择器

当点击确定的时候需要进行验证,我们可以参考

表单验证

。Form 组件提供了表单验证的功能,只需要通过 rules 属性传入约定的验证规则,并将 Form-Item 的 prop 属性设置为需校验的字段名即可



用户列表


Element UI table

首先 api 下的 mockServeData 新增 user.js

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

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 => {
        const { name, page = 1, limit = 20 } = param2Obj(config.url)
        // console.log('name:' + name, 'page:' + page, '分页大小limit:' + limit)
        const mockList = List.filter(user => {
            if (name && user.name.indexOf(name) === -1 && user.addr.indexOf(name) === -1) return false
            return true
        })
        const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
        return {
            code: 20000,
            count: mockList.length,
            list: pageList
        }
    },
    /**
     * 增加用户
     * @param name, addr, age, birth, sex
     * @return {{code: number, data: {message: string}}}
     */
    createUser: config => {
        const { name, addr, age, birth, sex } = JSON.parse(config.body)
        console.log(JSON.parse(config.body))
        List.unshift({
            id: Mock.Random.guid(),
            name: name,
            addr: addr,
            age: age,
            birth: birth,
            sex: sex
        })
        return {
            code: 20000,
            data: {
                message: '添加成功'
            }
        }
    },
    /**
     * 删除用户
     * @param id
     * @return {*}
     */
    deleteUser: config => {
        const { id } = JSON.parse(config.body)
        if (!id) {
            return {
                code: -999,
                message: '参数不正确'
            }
        } else {
            List = List.filter(u => u.id !== id)
            return {
                code: 20000,
                message: '删除成功'
            }
        }
    },
    /**
     * 批量删除
     * @param config
     * @return {{code: number, data: {message: string}}}
     */
    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: 20000,
            data: {
                message: '编辑成功'
            }
        }
    }
}

然后修改 mock.js

......
import user from './mockServeData/user'

// 定义mock请求拦截
......

// 用户列表的数据
Mock.mock('/api/user/add','post',user.createUser);
Mock.mock('/api/user/edit','post',user.updateUser);
Mock.mock('/api/user/del','post',user.deleteUser);
Mock.mock('/api/user/getUser',user.getUserList);

然后修改 index.js

......


// 请求首页数据
......

export const getUser = (params)=>{
    // 返回用户列表
    return http.get('/user/getUser',params)
}

// post 和 get 不同,参数是data对象,可以参考:
// https://www.axios-http.cn/docs/api_intro
export const addUser = (data)=>{
    return http.post('/user/add',data)
}

export const editUser = (data)=>{
    return http.post('/user/edit',data)
}

export const delUser = (data)=>{
    return http.post('/user/del',data)
}

在这里插入图片描述



用户编辑、删除

列表最后有两个按钮,分别是编辑和删除,这里用到了

自定义列模板

然后 调用接口,展示数据,修改 User.vue。修改和新增公用的一个弹框,所以使用一个变量来进行区分,所以在 data 中新增一个变量:

modalType: 0,// 0表示新增的弹框,1表示编辑的弹框

然后在提交的时候进行判断是新增还是编辑,新增和编辑后都需要重新加载列表来刷新页面,也就是重新调用 getUser 方法,所以可以把这个方法封装下

然后在新建时把 modalType 赋值为 0,同时显示弹框;在编辑时把 modalType 赋值为1,显示弹框的同时,把要修改的数据也显示在弹框中,需要对传过来的 row 进行深拷贝,否则页面的数据也会进行修改了

新增效果如下:

在这里插入图片描述

编辑效果如下:

在这里插入图片描述

进行删除时我们可以使用

MessageBox

来先进行确认,效果如下:

在这里插入图片描述

完整 User.vue 代码:

<template>
  <div class="manage">
    <el-dialog
        title="提示"
        :visible.sync="dialogVisible"
        :before-close="handleClose"
        width="50%">
      <!--表单数据-->
      <el-form ref="form" :inline="true" :rules="rules" :model="form" label-width="80px">
        <el-form-item label="姓名" prop="name">
          <el-input v-model="form.name" placeholder="请输入姓名"></el-input>
        </el-form-item>
        <el-form-item label="年龄" prop="age">
          <el-input v-model="form.age" placeholder="请输入年龄"></el-input>
        </el-form-item>
        <el-form-item label="性别" prop="sex">
          <el-select v-model="form.sex" placeholder="请选择活动性别">
            <el-option label="男" :value="1"></el-option>
            <el-option label="女" :value="0"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="出生日期" prop="birth">
          <el-date-picker
              v-model="form.birth"
              type="date"
              placeholder="请选择日期"
              value-format="yyyy-MM-DD">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="地址" prop="addr">
          <el-input v-model="form.addr" placeholder="请输入地址"></el-input>
        </el-form-item>
      </el-form>

      <span slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="submit">确 定</el-button>
      </span>
    </el-dialog>
    <div class="manage-header">
      <el-button type="primary" @click="handleAdd">+ 新增</el-button>
      <el-table
          :data="tableData"
          style="width: 100%">
        <el-table-column
            prop="name"
            label="姓名"
            width="180">
        </el-table-column>
        <el-table-column
            prop="age"
            label="年龄">
        </el-table-column>
        <el-table-column
            prop="sex"
            label="性别">
          <template slot-scope="scope">
            <span style="margin-left: 10px">{{ scope.row.sex === 1?'男':'女' }}</span>
          </template>
        </el-table-column>
        <el-table-column
            prop="birth"
            label="出生日期">
        </el-table-column>
        <el-table-column
            prop="addr"
            label="地址">
        </el-table-column>
        <el-table-column
            label="操作">
          <template slot-scope="scope">
            <el-button size="mini" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
import {addUser, delUser, editUser, getUser} from '../api'

export default {
  name: "Home",
  data(){
    return{
      dialogVisible: false,
      form:{
        name:'',
        age:'',
        sex:'',
        birth:'',
        addr:'',
      },
      rules: {
        name: [
          {required: true, message: '请输入姓名', trigger: 'blur'},
        ],
        age: [
          {required: true, message: '请输入年龄', trigger: 'blur'},
        ],
        sex: [
          {required: true, message: '请选择性别', trigger: 'blur'},
        ],
        birth: [
          {required: true, message: '请选择出生日期', trigger: 'blur'},
        ],
        addr: [
          {required: true, message: '请输入地址', trigger: 'blur'},
        ],
      },
      tableData: [],
      modalType: 0,// 0表示新增的弹框,1表示编辑的弹框
    }
  },
  methods: {
    // 用户提交表单
    submit(){
      this.$refs.form.validate((valid)=>{
        if(valid){
          // 后续操作
          if(this.modalType === 0){
            addUser(this.form).then(()=>{
              // 重新获取列表接口
              this.getList();
            })
          }else{
            editUser(this.form).then(()=>{
              this.getList();
            });
          }
          console.log(this.form);
          // 关闭弹窗
          this.dialogVisible = false;
          // 表单内容清空
          this.$refs.form.resetFields();
        }
      })
    },
    handleClose(){
      // 弹框关闭前情况数据
      this.$refs.form.resetFields();
      this.dialogVisible = false;
    },
    cancel(){
      this.handleClose();
    },
    handleEdit(row){
      this.modalType = 1;
      this.dialogVisible = true;
      // 注意,需要对数据进行深拷贝
      this.form = JSON.parse(JSON.stringify(row));
    },
    handleDelete(row){
      this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        console.log('TTT row.id',row.id);
        delUser({id:row.id}).then(()=>{
          this.$message({
            type: 'success',
            message: '删除成功!'
          });
          // 重新获取列表
          this.getList();
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        });
      });
    },
    // 获取列表
    getList(){
      getUser().then(({data})=>{
        // console.log('TTT',data);
        this.tableData = data.list;
      })
    },
    handleAdd(){
      this.modalType = 0;
      this.dialogVisible = true;
    }
  },
  mounted() {
    this.getList();
  }
}
</script>

<style scoped>

</style>



样式修改、分页

首先我们把 table 拿到 class = ‘manage’ 的 div 中,然后给 manage 高度设置为 90%。

table 组件的属性中



height

可以调整 table 的高度,我们也设置为 90%,我们还可以通过

stripe

来给 table 添加斑马纹

<el-table
        height="90%"
        stripe
        :data="tableData"
        style="width: 100%">
        ......
</el-table>

然后我们增加

分页

其中 total 是总条目数,在

getList

中获取数据后,给 total 赋值即可,获取的数据如下,count 就是数据总数

在这里插入图片描述


current-change

在当前页面改变时会触发,在 user.js 中获取用户列表的时候可以传分页的参数来控制分页。在

Axios基本用例

中,我们可以看到 get 请求传递参数时需要传递 params 的一个对象

<template>
  <div class="manage">
    ......
    <div class="manage-header">
      <el-button type="primary" @click="handleAdd">+ 新增</el-button>
    </div>
    <div class="common-table">
    	<el-table
        	height="90%"
        	stripe
        	:data="tableData"
       	 	style="width: 100%">
      	......
    	</el-table>
    	<div class="pager">
    		<el-pagination
        		layout="prev, pager, next"
        		:total="total"
        		@current-change="handleCurrentChange">
    		</el-pagination>
    	<div>
    </div>
  </div>
</template>
<script>
......
export default {
  name: "Home",
  data(){
    return{
      ......
      total: 0,//当前数据总条数
      pageData:{
        page: 1,
        limit: 10
      }
    }
  },
  methods: {
    ......
    // 获取列表
    getList(){
      getUser({params:this.pageData}).then(({data})=>{
        // console.log('TTT',data);
        this.tableData = data.list;
        this.total = data.count || 0;
      })
    },
    ......
    handleCurrentChange(val){
     this.pageData.page = val;
     this.getList();
    }
  },
  mounted() {
    this.getList();
  }
}
</script>
<style lang="less" scoped>
.manage{
  height: 90%;
  .common-table{
    position: relative;
    height: calc(100% - 62px);
    .pager{
      position: absolute;
      bottom: 0;
      right: 20px;
    }
  }
}
</style>

然后由于我们的增加了参数

在这里插入图片描述

mock 数据匹配不到了,所以我们还需要修改 mock.js ,改为整则匹配

Mock.mock(/api\/user\/getUser/,user.getUserList);

在这里插入图片描述



搜索

页面新增搜索布局表单 userForm,并增加样式。点击查询时调用

onSubmit

调用搜索接口

查看 user.js 中

getUserList

方法搜索需要传 name 参数,所以在 data 中增加 userForm 并增加 name 字段


getUser

中传递参数时,新增这个 name 参数即可,使用 ES6 语法 使用扩展运算符 来合并 name 和 pageData

<template>
  <div class="manage">
    ......
    <div class="manage-header">
      <el-button type="primary" @click="handleAdd">+ 新增</el-button>
      <el-form :inline="true" :model="userForm">
        <el-form-item>
          <el-input type="input" v-model="userForm.name"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
    ......
  </div>
</template>
<script>
......
export default {
  name: "Home",
  data(){
    return{
      ......
      userForm:{
        name: ''
      }
    }
  },
  methods: {
    ......
    // 获取列表
    getList(){
      getUser({params:{...this.userForm,...this.pageData}}).then(({data})=>{
        // console.log('TTT',data);
        this.tableData = data.list;
        this.total = data.count || 0;
      })
    }......
    // 查询
    onSubmit(){
     this.getList();
    }
  },
  ......
}
</script>

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

在这里插入图片描述



版权声明:本文为u010356768原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。