一、頁面
1.佈局
假設,我們要開發一個會員列表的頁面。
首先,新增vue頁面檔案“src\pages\Member.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="width: 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>
2.修改路由
src\router\index.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
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"> $width: 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>
點選左側的“會員資訊管理”的選單,執行效果如下:
二、動態查詢資料
1.mock.js
新增檔案:src\mock\member.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 }
新增src\mock\index.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/>' })
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="width: 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>
完整的專案結構如下圖所示:
執行效果如下:
其中,使用了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
如果你覺得我的部落格對你有幫助,可以給我點兒打賞,左側微信,右側支付寶。
有可能就是你的一點打賞會讓我的部落格寫的更好:)