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

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

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

  • 相关阅读:
    Linux下安装MySQL数据库(压缩包方式安装)
    使用Gitblit 在windows 上部署你的Git Server
    windows下使用docker的常用命令
    CentOS7安装Docker与使用篇
    linux安装redis
    Linux系统目录
    shiro之授权
    shiro之身份认证
    redis
    迅为4412uboot烧坏了报错问题
  • 原文地址:https://www.cnblogs.com/GoodHelper/p/8431835.html
Copyright © 2011-2022 走看看