Vue前端框架前端开发

Vue 后台管理项目12-用户列表页实现

2019-03-22  本文已影响544人  夜半暖人心

用户列表页实现

1.完成user组件静态布局

页面结构:组件盒子内分五部分,顶级面包屑(全局组件)+ 操作框 + 用户数据列表 + 底部的分页 + 用户增删改弹框(后面写动态交互再添加),都用el-row(饿了吗Layout 布局)包裹

image

Ⅰ.顶级面包屑的实现:参照前两章

Ⅱ.操纵框:
饿了吗组件 复合型输入框传送们http://element-cn.eleme.io/#/zh-CN/component/input
   button按钮 传送门http://element-cn.eleme.io/#/zh-CN/component/button

Ⅲ.用户数据列表:
饿了吗组件 Table表格(固定列表格) 传送门http://element-cn.eleme.io/#/zh-CN/component/table
   Switch 开关传送门http://element-cn.eleme.io/#/zh-CN/component/switch

Ⅳ.底部的分页:
饿了吗组件 Pagination 分页(完整功能)传送门http://element-cn.eleme.io/#/zh-CN/component/pagination

效果图:

image

示例代码

<template>
  <div id="user">
    <!-- 顶级面包屑 -->
    <el-row>
      <el-col :span="24">
        <breadcrumb :level2="level2" :level3="level3"></breadcrumb>
      </el-col>
    </el-row>
    <!-- 操纵框 -->
    <el-row class="operate">
      <el-col :span="4">
        <!-- 输入的内容最终是放在搜索里面 -->
        <el-input placeholder="请输入内容" v-model="pageData.query">
          <template slot="append">
            <i class="el-icon-search"></i>
          </template>
        </el-input>
      </el-col>
      <el-col :span="20">
        <el-button type="success" plain>添加用户</el-button>
      </el-col>
    </el-row>
    <!-- 用户数据 -->
    <el-row>
      <el-col :sapn="24">
        <el-table :data="userList" style="width: 100%" border>
          <!-- 返回的数据没有对应的属性名,把prop删掉 -->
          <!-- 增加type="index",会设置排序 -->
          <el-table-column label="#" width="30" type="index"></el-table-column>
          <el-table-column prop="username" label="姓名" width="180"></el-table-column>
          <el-table-column prop="email" label="邮箱" width="300"></el-table-column>
          <el-table-column prop="mobile" label="电话" width="300"></el-table-column>
          <el-table-column prop="mg_state" label="用户状态" width="80">
            <!-- slot-scope 废弃,已经被v-slot代替,为插槽传入 prop 的时候使用 -->
            <template slot-scope="scope">
              <el-switch
                v-model="scope.row.mg_state"
                active-color="#13ce66"
                inactive-color="#ff4949"
              ></el-switch>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button type="primary" plain size="mini" icon="el-icon-edit"></el-button>
              <el-button type="danger" plain size="mini" icon="el-icon-check"></el-button>
              <el-button type="warning" plain size="mini" icon="el-icon-delete"></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>
    <!-- 底部的分页 -->
    <el-row>
      <el-col :span="24">
        <!-- 删掉el-pagination如下的默认事件 -->
        <!-- @size-change="handleSizeChange"
        @current-change="handleCurrentChange" -->
        <el-pagination
          :current-page="pageData.pagenum"
          :page-sizes="[2, 4, 6, 8, 10]"
          :page-size="pageData.pagesize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
        ></el-pagination>
      </el-col>
    </el-row>
  </div>
</template>
<script>
export default {
  data() {
    return {
      level2: "用户管理",
      level3: "用户列表",
      //页码
      pageData: {
        pagenum: 1,
        pagesize: 10,
        query: ""
      },
      //总页数,默认为0
      total: 0,
      //用户的数据
      userList: []
    };
  },
  created() {
    //get请求需要通过params属性来传对象
    this.$axios.get("users", { params: this.pageData }).then(res => {
      console.log(res);
      this.userList = res.data.data.users;
      this.total = res.data.data.total;
    });
  }
};
</script>
<style lang="scss">
#user {
  .operate {
    background-color: #e8edf3;
  }
}
</style>

2.完成user组件动态交互

Ⅰ.用户查询

NO. 题外话:组件中写name的好处
1 vue开发者界面语义更明确
2 可以使用搜索快速定位到组件

image

用户查询步骤:点搜索→发请求→调接口→拿数据

NO. 用户查询步骤
1 根据input输入的查询字段可以进行模糊搜索,如果input输入为空默认搜索到全部用户
2 搜索方法和页面刷新created调用的方法一样,可以封装复用

Ⅱ.用户添加
饿了吗:Dialog 对话框(自定义内容) 传送门http://element-cn.eleme.io/#/zh-CN/component/dialog

NO. Dialog对话框
1 和面包屑同级,新增html用户添加的对话框代码
1 在form上添加:rules="rules"属性,增加表单数据验证
2 在form上添加:ref="userForm"属性,并将userForm传给提交按钮,增加表单提交验证
3 表单验证是前端验证可以被绕过,主要防止普通用户的误操作
4 技术用户可以绕过前端验证,比如用postman直接发送请求,添加用户,就不需要受到前端的限制
5 所以后端服务器一定会再验证一次
//template
 <!-- 添加用户的对话框 -->
    <el-dialog title="添加用户" :visible.sync="visible">
      <!-- label-position控制label名的显示位置,注意要设置label-width才能生效 -->
      <!-- 表单数据验证要加form上添加:rules="rules"属性 -->
      <!-- 表单提交验证要加ref="userForm"属性,并将userForm传给提交按钮 -->
      <el-form :model="form" :rules="rules" ref="userForm" label-position="left" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="form.username" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <!-- 添加type="password"属性,让密码不明文显示 -->
          <el-input v-model="form.password" type="password" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="邮箱">
          <el-input v-model="form.email" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="手机号">
          <el-input v-model="form.mobile" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="visible = false">取 消</el-button>
        <!-- 记住这边的userForm要加单引号 -->
        <el-button type="primary" @click="submitForm('userForm')">确 定</el-button>
      </div>
    </el-dialog>

//css
<style lang="scss">
#user {
  .operate {
    background-color: #e8edf3;
  }
  .el-dialog {
    width:30%;
  }
}
</style>

//js
<script>
export default {
  //写了name方便在Vue Devtools谷歌插件应用内找到对应的组件
  name: "user",
  data() {
    return {
      level2: "用户管理",
      level3: "用户列表",
      //页码
      pageData: {
        pagenum: 1,
        pagesize: 10,
        //query是查询的字段
        query: ""
      },
      //总页数,默认为0
      total: 0,
      //用户的数据
      userList: [],
      //是否 显示对话框
      visible: false,
      form: {
        username: "",
        password: "",
        email: "",
        mobile: ""
      },
      //表单验证规则
       rules: {
          username: [
            { required: true, message: '请输入用户名', trigger: 'blur' },
            { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
          ],
          password: [
            { required: true, message: '请输入密码', trigger: 'blur' },
            { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
          ]
      }
    }
  },
  methods: {
    //查询用户方法
    async getUsers() {
      //get请求需要通过params属性来传对象
      //用async/await 同步执行异步代码
      let res = await this.$axios.get("users", {
        params: this.pageData
      });
      //赋值
      this.userList = res.data.data.users;
      this.total = res.data.data.total;
    },
    //提交增加用户方法
    //这边submitForm和validate都要加上async,内部的await才能生效
    async submitForm(formName) {
       this.$refs[formName].validate(async valid => {
         if (valid) {
           //验证成功
           //调用接口
           let res = await this.$axios.post("users",this.form);
           console.log(res);
           if(res.data.meta.status===201){
           //201表示成功请求并创建了新的资源,可以继续执行下一步
           //关闭弹框
           this.visible=false;
           //重新获取数据
           this.getUsers();
           }
         } else {
           //验证失败
           this.$message.error('请您输入正确的信息')
           return false;
         }
       });
     },
  },
  //生命周期函数,回调函数
  async created() {
    //get请求需要通过params属性来传对象
    // let res = await this.$axios.get("users", { params: this.pageData });
    // this.userList = res.data.data.users;
    // this.total = res.data.data.total;

    //直接调用封装后的代码
    this.getUsers();
  }
};
</script>

Ⅲ.用户状态(启用跟禁用该用户)

饿了吗组件 Switch 开关有change方法

image
//template中
 <!-- slot-scope 废弃,已经被v-slot代替,为插槽传入table中的userList -->
 <template slot-scope="scope">
    <el-switch
       v-model="scope.row.mg_state"
       active-color="#13ce66"
       inactive-color="#ff4949"
       @change="statusChange(scope.row)">
    </el-switch>
 </template>

//js的methods中增加如下方法
<script>
 async statusChange(data){
       console.log(data);
       let res = await this.$axios.put(`users/${data.id}/state/${data.mg.state}`);
     }
</script>

Ⅳ.用户删除:传入id即可

//在删除按钮增加delOne方法,写在methods内
<script>
     delOne(data){
       console.log(data);
       let id = data.id;
       //提示用户
       this.$confirm('此操作将永久删除用户,是否继续?',"提示",{
         confirmButtonText:"确定",
         cancelButtonText:"取消",
         type:"danger"
       })
       .then(async()=>{
         //确定
         let res = await this.$axios.delete(`users/${id}`);
         //console.log(res);
         //重新获取用户数据即可
         this.getUsers();
       })
       .catch(()=>{
         //取消
       })
     }
</script>

V.用户编辑:

NO. 用户编辑
1 进入编辑状态
2 保存编辑结果

进入编辑状态

//template

<!-- 修改用户的对话框 -->
    <el-dialog title="修改用户" :visible.sync="editVisible">
      <!-- label-position控制label名的显示位置,注意要设置label-width才能生效 -->
      <!-- 表单提交验证要加ref="userForm"属性,并将userForm传给提交按钮 -->
      <el-form :model="editForm" ref="editForm" label-position="left" label-width="70px">
        <el-form-item label="用户名" prop="username">
          <!-- 用户名不可改,可以再input内加disabled属性,就能实现禁止修改 -->
          <!-- 对于利用vue浏览器插件进行修改的用户,只能说牛逼,暂时没有想到解决方法 -->
          <el-input v-model="editForm.username" disabled autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="邮箱">
          <el-input v-model="editForm.email" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="手机号">
          <el-input v-model="editForm.mobile" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="editVisible = false">取 消</el-button>
        <!-- 记住这边的userForm要加单引号 -->
        <el-button type="primary" @click="submitEdit('editForm')">确 定</el-button>
      </div>
    </el-dialog>


//js:
<script>
//1.data数据里增加
      //编辑框是否可见
      editVisible:false,
      //编辑框的表单数据
      editForm:{
        username:'',
        email:'',
        mobile:''
        //增加用户的id,方便后续编辑使用
        id:''
      }

//2.methods里增加方法
     //显示编辑框
     showEditDialog(data){
       //打印data
       console.log(data);
       //显示编辑框
       this.editVisible = true;
       //js的for in方法,遍历editForm的key,将data对应的key赋值给editForm的key
       for (const key in this.editForm) {
          this.editForm[key] = data[key];
         }
       //这种方法可能会在vue插件界面被篡改数据,保险点是用id再请求一个接口获取数据
       //如果id也被修改了呢?一般不会这么无聊
     }
</script>

保存编辑结果

//1.template:增加确定保存按钮
<div slot="footer" class="dialog-footer">
     <el-button @click="editVisible = false">取 消</el-button>
     <!-- 记住这边的userForm要加单引号 -->
     <el-button type="primary" @click="submitEdit()">确 定</el-button>
</div>

//2.js:methods里增加方法
<script>
async submitEdit(){
       let res = await this.$axios.put(
         `users/${this.editForm.id}`,
         this.editForm
       );
       console.log(res);
       if(res.data.meta.status===200){
         //关闭编辑框
         this.editVisible = false;
         //重新获取数据即可
         this.getUsers();
       }
     }
</script>

VI.分配角色

NO. 分配角色
1 弹出角色框,分配角色
2 保存分配结果

饿了吗组件 Select 选择器
传送门http://element-cn.eleme.io/#/zh-CN/component/select

//template
<!-- 分配角色的对话框 -->
    <el-dialog title="分配角色" :visible.sync="roleVisible">
      <!-- 就一个下拉框,不需要绑定表单数据:model="editForm",绑定角色数据就行 -->
      <el-form  label-position="left" label-width="100px">
        <el-form-item label="当前用户">
          {{selectUser.username}}
        </el-form-item>
        <el-form-item label="请选择角色">
           <el-select v-model="selectUser.role_name" placeholder="请选择">
              <el-option
                v-for="item in roles"
                :key="item.id"
                :label="item.roleName"
                :value="item.id">
              </el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="roleVisible = false">取 消</el-button>
        <!-- 记住这边的userForm要加单引号 -->
        <el-button type="primary" @click="submitRole">确 定</el-button>
      </div>
    </el-dialog>

//js
<script>
// data里增加下面数据
    //分配角色框是否显示
    roleVisible:false,
    //当前选中的用户数据
    selectUser:'',
    //所有的角色数据
    roles:''


//methods里增加下面的方法
    //显示角色对话框
    async showRoleDialog(data){
       this.roleVisible = true;
       //通过data获取用户的名字,用户的角色
       //console.log(data);
       //为了方便编码,直接保存当前选择的用户数据
       this.selectUser = data;
       //获取所有的角色,去数据库获取(角色列表接口)
        let res = await this.$axios.get('roles');
        console.log(res);
        this.roles = res.data.data;
        console.log(this.roles);
    },
    //保存分配结果
    async submitRole(){
      // 获取用户id,获取角色id
      // 调用接口
      let res = this.$axios.put(`users/${this.selectUser.id}/role`,{
         rid:this.selectUser.role_name
       });
       console.log(res);
       //关闭对话框
       this.roleVisible = false;
       //提示用户,之前已经有axios拦截器了
    }
</script>

V.分页功能实现
饿了吗组件 Pagination 分页的一些属性和方法

属性/方法 作用
1.@size-change="handleSizeChange" pageSize (每页条数) 改变时会触发,回调参数是新的pageSize
2.@current-change="handleCurrentChange" currentPage(当前页)改变时会触发,回调参数是新的currentPage
3.:page-sizes="[2, 4, 6, 8, 10]" 这是下拉框可以选择的,每选择一行,要展示多少内容
4.:page-size="pageSize" 显示当前行的条数
5.:total="userList.length" 总共有多少数据
6.:data="userList.slice((currentPage-1)pagesize,currentPagepagesize) userList取第几页的数据,最为重要的一句话

//html
<!-- 用户数据 -->
    <el-row>
      <el-col :sapn="24">
        <!-- 如下对数据请求的处理,最为重要的一句话,表示,userList取第几页的数据 -->
        <!-- :data="userList.slice((currentPage-1)*pagesize,currentPage*pagesize)"   -->
        <!-- arrayObject.slice(start,end)方法,参数是指数组对应的下标元素,start参数必选,end参数可选 -->
        <el-table style="width: 100%" border
         :data="userList.slice((pageData.pagenum-1)*pageData.pagesize,pageData.pagenum*pageData.pagesize)" >
          <!-- 返回的数据没有对应的属性名,把prop删掉 -->
          <!-- 增加type="index",会设置排序 -->
          <el-table-column label="#" width="30" type="index"></el-table-column>
          <el-table-column prop="username" label="姓名" width="180"></el-table-column>
          <el-table-column prop="email" label="邮箱" width="300"></el-table-column>
          <el-table-column prop="mobile" label="电话" width="300"></el-table-column>
          <el-table-column prop="mg_state" label="用户状态" width="80">
            <!-- slot-scope 废弃,已经被v-slot代替,为插槽传入table中的userList -->
            <template slot-scope="scope">
              <el-switch
                v-model="scope.row.mg_state"
                active-color="#13ce66"
                inactive-color="#ff4949"
                @change="statusChange(scope.row)"
              ></el-switch>
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="scope">
              <el-button type="primary" plain size="mini" @click="showEditDialog(scope.row)" icon="el-icon-edit"></el-button>
              <el-button type="danger" plain size="mini" @click="delOne(scope.row)" icon="el-icon-delete"></el-button>
              <el-button type="warning" plain size="mini"  @click="showRoleDialog(scope.row)" icon="el-icon-check"></el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-col>
    </el-row>
<!-- 底部的分页 -->
    <el-row>
      <!-- size-change pageSize(每页条数)改变时会触发的事件 -->
      <!-- current-change currentPage(当前页)改变时会触发 -->
      <!-- :page-sizes="[2, 4, 6, 8, 10]" 这是下拉框可以选择的,每选择一行,要展示多少内容 -->
      <!-- :page-size="pageData.pagesize"显示当前行的条数 -->
      <!-- :total="userList.length" 这是总共有多少数据 -->
      <el-col :span="24">
        <!-- 删掉el-pagination如下的默认事件 -->
        <!-- @size-change="handleSizeChange"
        @current-change="handleCurrentChange"-->
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pageData.pagenum"
          :page-sizes="[2, 4, 6, 8, 10]"
          :page-size="pageData.pagesize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="userList.length"
        ></el-pagination>
      </el-col>
    </el-row>


//js 在methods中加如下方法
<script>
handleSizeChange(size){
      this.pageData.pagesize = size;//每页下拉显示数据
      // console.log(this.pageData.pagesize);
    },
handleCurrentChange(currentPage){
      this.pageData.pagenum = currentPage;//点击第几页
      // console.log(this.pageData.pagenum);
    }
</script>

本文同步发表在我的个人博客:https://www.lubaojun.com/

上一篇下一篇

猜你喜欢

热点阅读