zoukankan      html  css  js  c++  java
  • Vue + ElementUI的电商管理系统实例03 用户列表

    1、通过路由展示用户列表页

    新建user文件夹,里面新建Users.vue文件:

    <template>
    <div>
      <h3>用户列表组件</h3>
    </div>
    </template>
    
    <script>
    export default {
    }
    </script>
    
    <style lang="less" scoped>
    
    </style>

    修改路由文件,添加Users路由:

    import Users from '../components/user/Users.vue'
    
    const routes = [
      { path: '/', redirect: '/login' }, // 重定向
      { path: '/login', component: Login },
      {
        path: '/home',
        component: Home,
        redirect: '/welcome', // 重定向
        children: [ // 子路由
          { path: '/welcome', component: Welcome },
          { path: '/users', component: Users } // 用户列表
        ]
      }
    ]

    这时点击左侧菜单的用户列表,就可以看到跳转到了用户列表页:

    2、小bug:刷新后左侧菜单的高亮没有了

    Menu Attribute里有个default-active属性: 表示当前激活菜单的 index,就是说如果想让菜单中的某一项高亮被激活,就把这项对应的index的值,赋值为整个menu菜单的default-active属性。

    每次点击左侧二级菜单时,把对应的index的值,赋值给default-active属性。

    <el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true"
               :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="activePath">
    
    <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState">
    
    <script>
    export default {
      data() {
        return {
          activePath: '' // 激活状态值
        }
      },
      methods: {  
        // 保存菜单链接的激活状态
        saveNavState(item) {
          console.log(item.index)
          this.activePath = item.index
        }
      }
    }
    </script>

    这样写完后发现可以实现效果,但是一刷新,激活状态又没有了,,准备存到sessioStorage中实现保存:

    <el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true"
               :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="activePath">
    
    <el-menu-item :index="'/' + subItem.path" v-for="subItem in item.children" :key="subItem.id" @click="saveNavState">
    
    <script>
    export default {
      data() {
        return {
          activePath: '' // 被激活的链接地址
        }
      },
      // 生命周期函数
      created() {
        this.getMenuList()
        this.activePath = window.sessionStorage.getItem('activePath')
      },
      methods: {
        // 保存菜单链接的激活状态
        saveNavState(item) {
          console.log(item.index)
          this.activePath = item.index
          // 将点击之后的index地址保存到客户端的sessionStorage中
          window.sessionStorage.setItem('activePath', item.index)
        }
      }
    }
    </script>

    可以实现效果了,刷新后还是高亮的。

    后来发现新版Element支持更简单的写法了:

    <el-menu background-color="#333744" text-color="#fff" active-text-color="#409eff" :unique-opened="true"
               :collapse="isCollapse" :collapse-transition="false" :router="true" :default-active="$route.path">
    
    <!--直接给default-active绑定$route.path的值就可以了-->

    3、用户列表基础布局

    首先要把使用的面包屑和卡片组件添加到element.js里:

    import Vue from 'vue'
    import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main,
      Menu, Submenu, MenuItemGroup, MenuItem, Breadcrumb, BreadcrumbItem, Card } from 'element-ui'
    
    Vue.use(Button)
    Vue.use(Form)
    Vue.use(FormItem)
    Vue.use(Input)
    Vue.use(Container)
    Vue.use(Header)
    Vue.use(Aside)
    Vue.use(Main)
    Vue.use(Menu)
    Vue.use(Submenu)
    Vue.use(MenuItemGroup)
    Vue.use(MenuItem)
    Vue.use(Breadcrumb)
    Vue.use(BreadcrumbItem)
    Vue.use(Card)
    // 挂载到Vue全局
    Vue.prototype.$message = Message

    在Users.vue里添加面包屑和卡片代码:

    <template>
      <div>
        <!--面包屑导航区域-->
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item>用户管理</el-breadcrumb-item>
          <el-breadcrumb-item>用户列表</el-breadcrumb-item>
        </el-breadcrumb>
        <!--卡片视图区域-->
        <el-card>
          111
        </el-card>
      </div>
    </template>

    然后在全局样式global里添加重置样式:

    /* 全局样式表 */
    html, body, #app {height: 100%; margin: 0; padding: 0;}
    .el-breadcrumb{margin-bottom: 15px;font-size: 12px;}
    .el-card{box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;}

    然后进行卡片里的布局,上部是一个搜索框和一个添加按钮,这个可以用栅格布局,记得把Row, Col添加导入到element.js,这里就不写了

    实现代码:

    <template>
      <div>
        <!--面包屑导航区域-->
        <el-breadcrumb separator-class="el-icon-arrow-right">
          <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
          <el-breadcrumb-item>用户管理</el-breadcrumb-item>
          <el-breadcrumb-item>用户列表</el-breadcrumb-item>
        </el-breadcrumb>
        <!--卡片视图区域-->
        <el-card>
          <el-row :gutter="20">
            <el-col :span="10">
              <!--搜索区域-->
              <el-input placeholder="请输入内容">
                <el-button slot="append" icon="el-icon-search"></el-button>
              </el-input>
            </el-col>
            <el-col :span="4">
              <el-button type="primary">添加用户</el-button>
            </el-col>
          </el-row>
        </el-card>
      </div>
    </template>

    实现效果:

    4、请求接口获取用户列表数据

    查看接口文档,1.3.1用户数据列表:请求路径是users,请求方式是get,请求参数是:query 查询参数 可以为空、pagenum 当前页码 不能为空、pagesize 每页显示条数 不能为空

    代码如下:

    <script>
    export default {
      data() {
        return {
          userList: [], // 用户列表
          total: 0, // 用户总数
          // 获取用户列表的参数对象
          queryInfo: {
            query: '', // 查询参数
            pagenum: 1, // 当前页码
            pagesize: 2 // 每页显示条数
          }
        }
      },
      created() { // 生命周期函数
        this.getUserList()
      },
      methods: {
        async getUserList() {
          const { data: res } = await this.$http.get('users', { params: this.queryInfo })
          console.log(res)
          if (res.meta.status !== 200) return this.$message.error(res.meta.msg)
          this.userList = res.data.users
          this.total = res.data.total
        }
      }
    }
    </script>

    5、使用表格组件渲染用户列表

    首先还是在element.js里添加Table和TableColumn导入:

    import Vue from 'vue'
    import { Button, Form, FormItem, Input, Message, Container, Header, Aside, Main,
      Menu, Submenu, MenuItemGroup, MenuItem, Breadcrumb, BreadcrumbItem, Card, Row, Col,
      Table, TableColumn } from 'element-ui'
    
    Vue.use(Button)
    Vue.use(Form)
    Vue.use(FormItem)
    Vue.use(Input)
    Vue.use(Container)
    Vue.use(Header)
    Vue.use(Aside)
    Vue.use(Main)
    Vue.use(Menu)
    Vue.use(Submenu)
    Vue.use(MenuItemGroup)
    Vue.use(MenuItem)
    Vue.use(Breadcrumb)
    Vue.use(BreadcrumbItem)
    Vue.use(Card)
    Vue.use(Row)
    Vue.use(Col)
    Vue.use(Table)
    Vue.use(TableColumn)
    // 挂载到Vue全局
    Vue.prototype.$message = Message

    然后添加代码:

    <!--用户列表区域-->
         <el-table :data="userList" style=" 100%" border stripe>
            <el-table-column prop="username" label="姓名"></el-table-column>
            <el-table-column prop="email" label="邮箱"></el-table-column>
            <el-table-column prop="mobile" label="电话"></el-table-column>
            <el-table-column prop="role_name" label="角色"></el-table-column>
            <el-table-column prop="mg_state" label="状态"></el-table-column>
            <el-table-column label="操作"></el-table-column>
         </el-table>

    边框:默认情况下,Table 组件是不具有竖直方向的边框的,如果需要,可以使用border属性,它接受一个Boolean,设置为true即可启用。

    隔行变色:stripe属性可以创建带斑马纹的表格。它接受一个Boolean,默认为false,设置为true即为启用。

    6、表格前面添加索引列

    type="index"

    <!--用户列表区域-->
        <el-table :data="userList" style=" 100%" border stripe>
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="username" label="姓名"></el-table-column>
            <el-table-column prop="email" label="邮箱"></el-table-column>
            <el-table-column prop="mobile" label="电话"></el-table-column>
            <el-table-column prop="role_name" label="角色"></el-table-column>
            <el-table-column prop="mg_state" label="状态"></el-table-column>
            <el-table-column label="操作"></el-table-column>
        </el-table>

    效果图:

    7、自定义状态列的显示效果

    用到Switch 开关组件,添加导入到element.js,这里就不写了。

    然后要用到作用域插槽:

    <!-- 作用域插槽 -->
    <template slot-scope="scope">
         {{scope.row}} 
    </template>

    这里定义了一个作用域插槽,通过slot-scope="scope"接收了当前作用域的数据,然后通过scope.row拿到对应这一行的数据,再绑定具体的属性值就行了。

    <el-table-column prop="mg_state" label="状态">
         <!-- 作用域插槽 -->
         <template slot-scope="scope">
              <!-- {{scope.row}} -->
              <el-switch v-model="scope.row.mg_state"></el-switch>
         </template>
    </el-table-column>

    如果同时指定了prop和作用域插槽,那么作用域插槽会覆盖prop,所以prop就不生效了,可以删掉。

    8、通过作用域插槽自定义操作列

    要用过id来操作对应数据,还是定义作用域插槽来实现:

    <el-table-column label="操作">
          <!-- 作用域插槽 -->
          <template slot-scope="scope">
                {{scope.row.id}}
          </template>
    </el-table-column>

    然后要添加三个按钮组件: size表示尺寸

    <!--修改-->
    <el-button type="primary" size="mini" icon="el-icon-edit"></el-button>
    <!--删除-->
    <el-button type="danger" size="mini" icon="el-icon-delete"></el-button>
    <!--分配角色-->
    <el-button type="warning" size="mini" icon="el-icon-setting"></el-button>

    需要给分配角色按钮添加一个鼠标移上去有提示信息,使用Tooltip 文字提示组件,添加导入这里就不写了:

    <!--分配角色-->
    <el-tooltip class="item" effect="dark" content="分配角色" placement="top" :enterable="false">
         <el-button type="warning" size="mini" icon="el-icon-setting"></el-button>
    </el-tooltip>

    enterable属性:表示鼠标是否可进入到 tooltip 中,默认是true开的,需要把它绑定为false,鼠标移到上面提示就消失了。

    效果图:

    9、实现分页效果

    Pagination 分页组件,添加导入这里就不写了

    属性参数         说明                                                       类型          可选值                                                                默认值
    current-page   当前页数,支持 .sync 修饰符                number     —                                                                       1
    page-sizes      每页显示个数选择器的选项设置            number[]   —                                                                       [10, 20, 30, 40, 50, 100]
    page-size       每页显示条目个数,支持 .sync 修饰符   number    —                                                                       10
    total                总条目数                                                 number    —                                                                        —
    layout             组件布局,子组件名用逗号分隔             String      sizes, prev, pager, next, jumper, ->, total, slot     'prev, pager, next, jumper, ->, total'

    事件名称           说明                                                    回调参数
    size-change      pageSize改变时会触发                     每页条数
    current-change   currentPage改变时会触发              当前页
    prev-click  用户点击上一页按钮改变当前页后触发    当前页
    next-click  用户点击下一页按钮改变当前页后触发    当前页

    <!--分页区域-->
    <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="queryInfo.pagenum"
          :page-sizes="[1, 2, 5, 10]"
          :page-size="queryInfo.pagesize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total">
    </el-pagination>
    
    <script>
    export default {
      methods: {
         // 监听 pageSize 改变的事件
        handleSizeChange(newSize) {
           console.log(newSize)
        },
        // 监听 当前页码值 改变的事件
        handleCurrentChange(newPage) {
           console.log(newPage)
        }  
      }
    }
    </script>

    然后把点击改变后的newSize和newPage,再赋值给回pagesize和pagenum,然后重新获取用户列表数据:

    // 监听 pageSize 改变的事件
       handleSizeChange(newSize) {
          // console.log(newSize)
          this.queryInfo.pagesize = newSize
          // 重新发起请求用户列表
          this.getUserList()
       },
       // 监听 当前页码值 改变的事件
       handleCurrentChange(newPage) {
          // console.log(newPage)
          this.queryInfo.pagenum = newPage
          // 重新发起请求用户列表
          this.getUserList()
       }

    在添加一个全局的分页样式:

    /* 全局样式表 */
    html, body, #app {height: 100%; margin: 0; padding: 0;}
    .el-breadcrumb{margin-bottom: 15px;font-size: 12px;}
    .el-card{box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1) !important;}
    .el-table{margin-top: 15px;font-size: 12px;}
    .el-pagination{margin-top: 15px;}

    现在点击分页,用户列表数据就可以随之变化了。 

    效果图:

    10、修改用户状态

    查看Switch事件:

    事件名称             说明                                         回调参数
    change switch    状态发生变化时的回调函数     新状态的值

    修改代码,添加事件:

    <el-table-column label="状态">
       <!-- 作用域插槽 -->
       <template slot-scope="scope">
            <el-switch v-model="scope.row.mg_state" @change="userStateChanged(scope.row)"></el-switch>
       </template>
    </el-table-column>
    
    <script>
    export default {
      methods: {
        // 监听 当前状态值 改变事件
        userStateChanged(userinfo) {
           console.log(userinfo)
        }
      }
    }
    </script>

    现在就要把修改后的用户信息保存到服务器。

    查看接口文档,1.3.3. 修改用户状态,请求路径:users/:uId/state/:type,请求方法:put,
    请求参数:uId:用户ID:不能为空`携带在url中、type:用户状态:不能为空`携带在url中`:值为 true 或者 false

    修改添加代码:

    // 监听 当前状态值 改变事件
       async userStateChanged(userinfo) {
          console.log(userinfo)
          const { data: res } = await this.$http.put(
            `users/${userinfo.id}/state/${userinfo.mg_state}`
          )
          if (res.meta.status !== 200) {
            userinfo.ms_state = !userinfo.ms_state
            return this.$message.error('更新用户状态失败')
          }
          this.$message.success('更新用户状态成功!')
       }
    // 注意put这里为了拼接动态参数用的是反引号``

    现在点击修改用户状态,再重新刷新后,显示的还是刚才修改后的状态,成功。

    11、实现搜索功能

    给搜索框实现双向绑定,并添加点击事件:绑定queryInfo.query,点击重新获取用户列表

    <!--搜索区域-->
    <el-input v-model="queryInfo.query" placeholder="请输入内容">
          <el-button slot="append" icon="el-icon-search" @click="getUserList"></el-button>
    </el-input>

    添加清空按钮,清空输入框同时刷新用户列表:

    使用clearable属性即可得到一个可清空的输入框

    clear事件 在点击由 clearable 属性生成的清空按钮时触发

    <el-input v-model="queryInfo.query" placeholder="请输入内容" clearable @clear="getUserList">

    效果图:

  • 相关阅读:
    博客访问人数统计
    2018年总结&2019年计划
    区块链产品介绍
    work table a year
    No Ads for Blogs
    滴滴云来袭
    部分博客图片失效问题
    加一个小学期的作品视频
    【原创】我的KM算法详解
    【转载】C++中替代sprintf的std::ostringstream输出流详解
  • 原文地址:https://www.cnblogs.com/joe235/p/12068661.html
Copyright © 2011-2022 走看看