美文网首页Vue前端框架前端开发
Vue 后台管理项目12-用户列表页实现

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

作者: 夜半暖人心 | 来源:发表于2019-03-22 23:11 被阅读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/

    相关文章

      网友评论

        本文标题:Vue 后台管理项目12-用户列表页实现

        本文链接:https://www.haomeiwen.com/subject/eyndvqtx.html