zoukankan      html  css  js  c++  java
  • spring boot + vue + element-ui全栈开发入门——前端列表页面开发

     一、页面


    1.布局

    假设,我们要开发一个会员列表的页面。

    首先,添加vue页面文件“srcpagesMember.vue”

     参照文档http://element.eleme.io/#/zh-CN/component/table中的例子,实现一个静态的列表页面

    代码如下:

    <template>
    <section>
      <!--工具条-->
      <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
        <el-form :inline="true" :model="filters">
          <el-form-item>
            <el-input v-model="filters.query" placeholder="姓名/手机号等条件" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" v-on:click="getRows" icon="el-icon-search">查询</el-button>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" v-on:click="handleAdd" icon="el-icon-plus">添加</el-button>
          </el-form-item>
        </el-form>
      </el-col>
      <el-table :data="rows" style=" 100%" stripe border>
        <el-table-column label="注册日期" width="180">
          <template slot-scope="scope">
           <i class="el-icon-time"></i>
           <span style="margin-left: 10px">{{ scope.row.date }}</span>
         </template>
        </el-table-column>
        <el-table-column label="姓名" width="180" :show-overflow-tooltip="true">
          <template slot-scope="scope">
           <el-popover trigger="hover" placement="top">
             <p>姓名: {{ scope.row.name }}</p>
             <p>住址: {{ scope.row.address }}</p>
             <div slot="reference" class="name-wrapper">
               <el-tag size="medium">{{ scope.row.name }}</el-tag>
             </div>
           </el-popover>
         </template>
        </el-table-column>
        <el-table-column prop="sex" label="性别" width="100" align="center" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            {{scope.row.sex===1?'男':'女'}}
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scope">
           <el-button
             size="mini"
             type="primary"
             @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
           <el-button
             size="mini"
             type="danger"
             @click="handleDelete(scope.$index, scope.row)">删除</el-button>
         </template>
        </el-table-column>
      </el-table>
    </section>
    </template>
    
    <script>
    let data = () => {
      return {
        filters: {},
        rows: []
      }
    }
    
    let handleAdd = function() {
    
    }
    
    let handleEdit = function(index, row) {
      console.log(index, row);
    }
    
    let handleDelete = function(index, row) {
      console.log(index, row);
    }
    
    let getRows = function() {
      this.rows = []
      this.rows.push({
        date: '2018-05-02',
        name: '王小虎1',
        sex: 1,
        address: '上海市普陀区金沙江路 1518 弄'
      })
      this.rows.push({
        date: '2018-05-04',
        name: '王小虎2',
        sex: 2,
        address: '上海市普陀区金沙江路 1517 弄'
      })
      this.rows.push({
        date: '2018-05-01',
        name: '王小虎3',
        sex: 2,
        address: '上海市普陀区金沙江路 1519 弄'
      })
      this.rows.push({
        date: '2018-05-03',
        name: '王小虎5',
        sex: 1,
        address: '上海市普陀区金沙江路 1516 弄'
      })
    }
    
    export default {
      data: data,
      methods: {
        //添加
        handleAdd,
        //修改
        handleEdit,
        //删除
        handleDelete,
        //获取分页
        getRows
      },
      mounted: function() {
        this.getRows()
      }
    }
    </script>
    
    <style scoped>
    </style>
    Member.vue

    2.修改路由

    src outerindex.js文件中,添加

    routes.push({
      path: '/member',
      name: '会员管理',
      component: Main,
      iconCls: 'fa fa-user-circle-o',
      children: [{
        path: '/member/data',
        component: Member,
        name: '会员信息管理'
      }]
    })
    

      

    完整代码如下:

    import Vue from 'vue'
    import Router from 'vue-router'
    
    Vue.use(Router)
    
    import Main from '@/pages/Main'
    import Dashboard from '@/pages/Dashboard'
    import Member from '@/pages/Member'
    
    let routes = [{
      path: '/',
      component: Main,
      hidden: true,
      children: [{
        path: '/',
        component: Dashboard,
        name: '首页'
      }]
    }]
    
    routes.push({
      path: '/member',
      name: '会员管理',
      component: Main,
      iconCls: 'fa fa-user-circle-o',
      children: [{
        path: '/member/data',
        component: Member,
        name: '会员信息管理'
      }]
    })
    
    const router = new Router({
      routes: routes
    })
    
    export default router
    src outerindex.js

    3.修改首页,使其出现“会员管理”的菜单

    <el-menu :default-active="$route.path" :collapse="collapsed">
                <template v-for="(item,index) in menus">
                  <el-submenu :index="index+''" v-if="!item.leaf">
                    <template slot="title"><i :class="item.iconCls"></i><span v-if="!collapsed">{{item.name}}</span></template>
                <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" @click="$router.push(child.path)">{{child.name}}</el-menu-item>
                </el-submenu>
                <el-menu-item v-if="item.leaf&&item.children.length>0" :index="item.children[0].path"><i :class="item.iconCls"></i>{{item.children[0].name}}</el-menu-item>
                </template>
              </el-menu>

    完整代码如下:

    <template>
    <section>
      <el-container class="container">
        <!--左边-->
        <el-aside :width="collapsed? '65px' : '200px' ">
          <el-container>
            <el-header>
              <span class="menu-button" v-if="collapsed" @click.prevent="collapsed=!collapsed">
                <i class="fa fa-align-justify"></i>
              </span>
              <span v-else class="system-name">{{systemName}}</span>
            </el-header>
            <el-main>
              <el-menu :default-active="$route.path" :collapse="collapsed">
                <template v-for="(item,index) in menus">
                  <el-submenu :index="index+''" v-if="!item.leaf">
                    <template slot="title"><i :class="item.iconCls"></i><span v-if="!collapsed">{{item.name}}</span></template>
                <el-menu-item v-for="child in item.children" :index="child.path" :key="child.path" @click="$router.push(child.path)">{{child.name}}</el-menu-item>
                </el-submenu>
                <el-menu-item v-if="item.leaf&&item.children.length>0" :index="item.children[0].path"><i :class="item.iconCls"></i>{{item.children[0].name}}</el-menu-item>
                </template>
              </el-menu>
            </el-main>
          </el-container>
        </el-aside>
        <!--内容-->
        <el-container>
          <!--页眉-->
          <el-header class="header">
            <el-row>
              <el-col :span="18" class="header-title">
                <span v-if="collapsed" class="system-name">{{systemName}}</span>
                <span v-else class="menu-button" @click.prevent="collapsed=!collapsed">
                  <i class="fa fa-align-justify"></i>
                </span>
              </el-col>
              <el-col :span="6"><span class="el-dropdown-link userinfo-inner">你好:{{userName}}</span></el-col>
            </el-row>
          </el-header>
          <!--中间-->
          <el-main class="main">
            <transition name="fade" mode="out-in">
              <router-view></router-view>
            </transition>
          </el-main>
        </el-container>
      </el-container>
    </section>
    </template>
    
    <script>
    let data = () => {
      return {
        collapsed: false,
        systemName: '后台管理',
        userName: '系统管理员',
        menus: []
      }
    }
    
    let initMenu = function() {
      for (let i in this.$router.options.routes) {
        let root = this.$router.options.routes[i]
        if (root.hidden)
          continue
        let children = []
        for (let j in root.children) {
          let item = root.children[j]
          if (item.hidden)
            continue
          children.push(item)
        }
    
        if (children.length < 1)
          continue
    
        this.menus.push(root)
        root.children = children
      }
    }
    
    export default {
      data: data,
      methods: {
        initMenu
      },
      mounted: function() {
        this.initMenu()
      }
    }
    </script>
    
    <style scoped="scoped"
      lang="scss">
    $ 100%;
    $height: 100%;
    $background-color: #0b0a3e;
    $header-color: #fff;
    $header-height: 60px;
    
    .container {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 100%;
        .el-aside {
            .el-header {
                line-height: $header-height;
                background-color: $background-color;
                color: $header-color;
                text-align: center;
            }
            .el-container {
                height: $height;
                .el-main {
                    padding: 0;
                }
            }
        }
    
        .main {
            width: $width;
            height: $height;
        }
    
        .menu-button {
            width: 14px;
            cursor: pointer;
        }
    
        .userinfo-inner {
            cursor: pointer;
        }
    
        .el-menu {
            height: $height;
        }
    
        .header {
            background-color: $background-color;
            color: $header-color;
            text-align: center;
            line-height: $header-height;
            padding: 0;
    
            .header-title {
                text-align: left;
                span {
                    padding: 0 20px;
                }
            }
        }
    
        .system-name {
            font-size: large;
            font-weight: bold;
        }
    }
    </style>
    srcpagesMain.vue

    点击左侧的“会员信息管理”的菜单,运行效果如下:

    二、动态查询数据


    1.mock.js

    添加文件:srcmockmember.js

    import Mock from 'mockjs'
    
    let adapters = []
    adapters.push(
      (mockAdapter) => mockAdapter.onPost('/api/member/loadPage').reply(req => {
        let promise = new Promise((resolve, reject) => {
          let data = req.data ? JSON.parse(req.data) : {
            size: 20
          }
          let result = {
            rows: [],
            total: 10000
          }
          for (let i = 0; i < data.size; i++) {
            let item = Mock.mock({
              id: Mock.Random.guid(),
              name: Mock.Random.cname(),
              sex: Mock.Random.integer(1, 2),
              'age|18-30': 1,
              date: Mock.Random.date(),
              address: Mock.mock('@county(true)'),
            })
            result.rows.push(item)
          }
          setTimeout(() => {
            resolve([200, result])
          }, 2000)
        })
        return promise
      })
    )
    
    export {
      adapters
    }

    添加srcmockindex.js文件

    import axios from 'axios'
    import MockAdapter from 'axios-mock-adapter'
    
    let mockAdapter = new MockAdapter(axios)
    
    //会员api
    import {
      adapters as member
    } from '@/mock/member.js'
    member.forEach(item => item(mockAdapter))
    
    export default mockAdapter

    2.修改main.js文件

    在main.js中导入mock.js

    //开发模式开启mock.js
    if (process.env.NODE_ENV === 'development') {
      require('./mock')
    }

    导入axios

    import axios from 'axios'
    Vue.prototype.$axios = axios

    完整main.js代码:

    // The Vue build version to load with the `import` command
    // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
    import Vue from 'vue'
    import App from './App'
    import router from './router'
    
    Vue.config.productionTip = false
    
    import 'font-awesome/css/font-awesome.min.css'
    
    import ElementUI from 'element-ui'
    import './assets/theme/element-#0b0a3e/index.css'
    Vue.use(ElementUI)
    
    //开发模式开启mock.js
    if (process.env.NODE_ENV === 'development') {
      require('./mock')
    }
    
    import axios from 'axios'
    Vue.prototype.$axios = axios
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      components: {
        App
      },
      template: '<App/>'
    })
    srcmain.js

    3.修改Member.vue文件

    修改查询分页的方法:

    let getRows = function() {
      if (this.pageLoading)
        return
      this.pageLoading = true
    
      let params = {
        page: this.page,
        size: this.size,
        query: this.filters.query
      }
      //调用post请求
      this.$axios.post('/api/member/loadPage', params).then(res => {
        this.pageLoading = false
        if (!res.data || !res.data.rows)
          return
        //总数赋值
        this.total = res.data.total
        this.page++;
        //页面元素赋值
        this.rows = res.data.rows
      }).catch(e => this.pageLoading = false)
    }
    

      

    完整的Member.vue代码如下:

    <template>
    <section>
      <!--工具条-->
      <el-col :span="24" class="toolbar" style="padding-bottom: 0px;">
        <el-form :inline="true" :model="filters">
          <el-form-item>
            <el-input v-model="filters.query" placeholder="姓名/手机号等条件" />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" v-on:click="handleQuery" icon="el-icon-search">查询</el-button>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" v-on:click="handleAdd" icon="el-icon-plus">添加</el-button>
          </el-form-item>
        </el-form>
      </el-col>
      <el-table :data="rows" style=" 100%;overflow: auto;" :height="clientHeight" stripe border highlight-current-row v-loading="pageLoading">
        <el-table-column label="注册日期" width="180">
          <template slot-scope="scope">
           <i class="el-icon-time"></i>
           <span style="margin-left: 10px">{{ scope.row.date }}</span>
         </template>
        </el-table-column>
        <el-table-column label="姓名" width="180" :show-overflow-tooltip="true">
          <template slot-scope="scope">
           <el-popover trigger="hover" placement="top">
             <p>姓名: {{ scope.row.name }}</p>
             <p>住址: {{ scope.row.address }}</p>
             <div slot="reference" class="name-wrapper">
               <el-tag size="medium">{{ scope.row.name }}</el-tag>
             </div>
           </el-popover>
         </template>
        </el-table-column>
        <el-table-column prop="sex" label="性别" width="100" align="center" :show-overflow-tooltip="true">
          <template slot-scope="scope">
            {{scope.row.sex===1?'男':'女'}}
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scope">
           <el-button
             size="mini"
             type="primary"
             @click="handleEdit(scope.$index, scope.row)"><i class="el-icon-edit"></i>编辑</el-button>
           <el-button
             size="mini"
             type="danger"
             @click="handleDelete(scope.$index, scope.row)"><i class="el-icon-delete"></i>删除</el-button>
         </template>
        </el-table-column>
      </el-table>
      <!--底部-->
      <el-col :span="24" class="toolbar">
        <el-pagination layout="prev, pager, next" @current-change="handleCurrentChange" :page-size="20" :total="total" style="float:right;">
        </el-pagination>
      </el-col>
    
    </section>
    </template>
    
    <script>
    
    let data = () => {
      return {
        //页码
        page: 1,
        //每页数量
        size: 20,
        //总数
        total: 0,
        //查询条件
        filters: {},
        //页面数据
        rows: [],
        //页面载入状态
        pageLoading: false,
        //列表高度
        clientHeight: '100%',
    
      }
    }
    
    let handleAdd = function() {
    
    }
    
    let handleEdit = function(index, row) {
    
    }
    
    let handleDelete = function(index, row) {
     
    }
    
    let getRows = function() {
      if (this.pageLoading)
        return
      this.pageLoading = true
    
      let params = {
        page: this.page,
        size: this.size,
        query: this.filters.query
      }
      //调用post请求
      this.$axios.post('/api/member/loadPage', params).then(res => {
        this.pageLoading = false
        if (!res.data || !res.data.rows)
          return
        //总数赋值
        this.total = res.data.total
        this.page++;
        //页面元素赋值
        this.rows = res.data.rows
      }).catch(e => this.pageLoading = false)
    }
    
    let handleQuery = function() {
      this.page = 1
      this.getRows()
    }
    
    let handleCurrentChange = function(val) {
      this.page = val
      this.getRows()
    }
    
    let initHeight = function() {
      this.clientHeight = (document.documentElement.clientHeight - 258) + 'px'
    }
    
    export default {
      data: data,
      methods: {
        //查询
        handleQuery,
        //添加
        handleAdd,
        //修改
        handleEdit,
        //删除
        handleDelete,
        //页数改变
        handleCurrentChange,
        //获取分页
        getRows,
        //初始化高度
        initHeight
      },
      mounted: function() {
        window.addEventListener('resize', this.initHeight)
        this.initHeight()
        this.getRows()
      }
    }
    </script>
    
    <style scoped>
    </style>
    srcpagesMember.vue

    完整的项目结构如下图所示:

     

    运行效果如下:

    其中,使用了axios来调用http post协议,url是'/api/member/loadPage',并post了body参数。

    但我并没有写任何后端代码。奇怪的是,获取的数据从哪里来?答案是:mock.js,因为使用了mock.js+axios-mock-adapter来拦截并模拟http协议。

    返回目录

    git代码地址:https://github.com/carter659/spring-boot-vue-element.git

    如果你觉得我的博客对你有帮助,可以给我点儿打赏,左侧微信,右侧支付宝。

    有可能就是你的一点打赏会让我的博客写的更好:)

  • 相关阅读:
    泛微云桥e-Bridge 目录遍历,任意文件读取
    (CVE-2020-8209)XenMobile-控制台存在任意文件读取漏洞
    selenium 使用初
    将HTML文件转换为MD文件
    Python对word文档进行操作
    使用java安装jar包出错,提示不是有效的JDK java主目录
    Windows server 2012安装VM tools异常解决办法
    ifconfig 命令,改变主机名,改DNS hosts、关闭selinux firewalld netfilter 、防火墙iptables规则
    iostat iotop 查看硬盘的读写、 free 查看内存的命令 、netstat 命令查看网络、tcpdump 命令
    使用w uptime vmstat top sar nload 等命令查看系统负载
  • 原文地址:https://www.cnblogs.com/GoodHelper/p/8431835.html
Copyright © 2011-2022 走看看