基于Vue+ELement搭建動(dòng)態(tài)樹(shù)與數(shù)據(jù)表格實(shí)現(xiàn)分頁(yè)模糊查詢實(shí)戰(zhàn)全過(guò)程
一、前言
在上一篇博文我們搭建了首頁(yè)導(dǎo)航和左側(cè)菜單,但是我們的左側(cè)菜單是死數(shù)據(jù)今天我們就來(lái)把死的變成活的,并且完成右側(cè)內(nèi)容的書(shū)籍?dāng)?shù)據(jù)表格的展示與分頁(yè)效果,話不多說(shuō)上代碼??!
二、左側(cè)動(dòng)態(tài)樹(shù)實(shí)現(xiàn)
2.1.后臺(tái)數(shù)據(jù)接口定義
首先我們將后端的代碼寫(xiě)好Controller層代碼
package com.zking.ssm.controller;
import com.zking.ssm.model.Module;
import com.zking.ssm.model.RoleModule;
import com.zking.ssm.model.TreeNode;
import com.zking.ssm.service.IModuleService;
import com.zking.ssm.util.JsonResponseBody;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("/module")
public class ModuleController {
@Autowired
private IModuleService moduleService;
@RequestMapping("/queryRootNode")
@ResponseBody
public JsonResponseBody<List<Module>> queryRootNode(){
try {
List<Module> modules = moduleService.queryRootNode(-1);
return new JsonResponseBody<>("OK",true,0,modules);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("初始化首頁(yè)菜單錯(cuò)誤",false,0,null);
}
}
@RequestMapping("/queryElementTree")
@ResponseBody
public JsonResponseBody<List<TreeNode>> queryElementTree(){
try {
List<TreeNode> modules = moduleService.queryTreeNode(-1);
return new JsonResponseBody<>("OK",true,0,modules);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("初始化ElementUI的Tree組件錯(cuò)誤",false,0,null);
}
}
@RequestMapping("/addRoleModule")
@ResponseBody
public JsonResponseBody<?> addRoleModule(RoleModule roleModule){
try {
moduleService.addRoleModule(roleModule);
return new JsonResponseBody<>("新增角色權(quán)限成功",true,0,null);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("新增角色權(quán)限失敗",false,0,null);
}
}
@RequestMapping("/queryModuleByRoleId")
@ResponseBody
public JsonResponseBody<List<String>> queryModuleByRoleId(RoleModule roleModule){
try {
List<String> modules = moduleService.queryModuleByRoleId(roleModule);
return new JsonResponseBody<>("OK",true,0,modules);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("獲取角色權(quán)限失敗",false,0,null);
}
}
}由此我們可知后端查詢的樹(shù)形菜單的接口為:http://localhost:8080/ssm/module/queryRootNode
2.2.前端導(dǎo)航菜單綁定
數(shù)據(jù)有了我們只用考慮怎么通過(guò)Vue拿到數(shù)據(jù)以及展示數(shù)據(jù)就可以了。
找到src下面的api目錄下的action.js文件添加下列接口
'SYSTEM_USER_MODULE': '/module/queryRootNode', //左側(cè)菜單
在LeftNav.vue中的鉤子函數(shù)內(nèi)編寫(xiě)方法去到后端拿取數(shù)據(jù)賦予變量
created() {
this.$root.Bus.$on('aaa', r => {
this.collapsed = r;
});
//加載頁(yè)面先去后端拿數(shù)據(jù)
let url = this.axios.urls.SYSTEM_USER_MODULE;
this.axios.get(url, {}).then(r => {
this.menus=r.data.rows
}).catch(e => {
})
}并在data中定義變量 menus:[]
menus:[]
2.3.根據(jù)數(shù)據(jù)渲染頁(yè)面
去到我們ELement查找相應(yīng)的代碼進(jìn)行cv,下面是我找好的你們直接用,我們現(xiàn)在只需要將后端獲取到的數(shù)據(jù)在上面的代碼中進(jìn)行遍歷即可。
<!-- 左側(cè)菜單內(nèi)容-->
<el-submenu v-for="m in menus" :index="'ind_'+m.id" :key="'key_'+m.id">
<template slot="title">
<i :class="m.icon"></i>
<span>{{m.text}}</span>
</template>
<el-menu-item v-for="ms in m.modules" :index="ms.url" :key="'key_'+ms.id">
<i :class="ms.icon"></i>
<span>{{ms.text}}</span>
</el-menu-item>
</el-submenu>效果展示:

2.4.動(dòng)態(tài)路由實(shí)現(xiàn)
我們點(diǎn)擊下方的子菜單肯定會(huì)顯示右側(cè)白框里面的內(nèi)容,所以我們需要實(shí)現(xiàn)動(dòng)態(tài)路由
①實(shí)現(xiàn)路由跳轉(zhuǎn)及當(dāng)前項(xiàng)的設(shè)置
<el-menu router :default-active="$route.path"> <el-menu-item index="/company/userManager">用戶管理</el-menu-item> </el-menu>
注意事項(xiàng):
①要實(shí)現(xiàn)路由跳轉(zhuǎn),先要在
el-menu標(biāo)簽上添加router屬性,然后只要在每個(gè)el-menu-item標(biāo)簽內(nèi)的index屬性設(shè)置一下url即可實(shí)現(xiàn)點(diǎn)擊el-menu-item實(shí)現(xiàn)路由跳轉(zhuǎn)。②導(dǎo)航當(dāng)前項(xiàng),在
el-menu標(biāo)簽中綁定 :default-active="$route.path",注意是綁定屬性,不要忘了加“:”,當(dāng)$route.path等于el-menu-item標(biāo)簽中的index屬性值時(shí)則該item為當(dāng)前項(xiàng)。③el-submenu標(biāo)簽中的url屬性不能為空,且不能相同,否則會(huì)導(dǎo)致多個(gè)節(jié)點(diǎn)收縮/折疊效果相同的問(wèn)題。
②生成相對(duì)應(yīng)的Vue文件
根據(jù)我們點(diǎn)擊子菜單所顯示的層級(jí)關(guān)系進(jìn)行Vue組件的編寫(xiě),下面以書(shū)本管理下面的新增書(shū)本為例

AddBook.Vue
<template> <h1>新增書(shū)本</h1> </template> <script> </script> <style> </style>
③配置路由與路由路徑的關(guān)系
index.js
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import AppMain from '@/components/AppMain'
import LeftNav from '@/components/LeftNav'
import TopNav from '@/components/TopNav'
import Login from '@/views/Login'
import Registered from '@/views/Registered'
import AddBook from '@/views/book/AddBook'
import BookList from '@/views/book/BookList'
Vue.use(Router)
export default new Router({
routes: [{
path: '/',
name: 'Login',
component: Login
}, {
path: '/Registered',
name: 'Registered',
component: Registered
}, {
path: '/AppMain',
name: 'AppMain',
component: AppMain,
children: [{
path: '/LeftNav',
name: 'LeftNav',
component: LeftNav
}, {
path: '/TopNav',
name: 'TopNav',
component: TopNav
}, {
path: '/book/AddBook',
name: 'AddBook',
component: AddBook
}, {
path: '/book/BookList',
name: 'BookList',
component: BookList
}]
}]
})④將組件渲染到頁(yè)面上
在AppMain.js中顯示組件就需要加上<router-view></router-view>
<template>
<el-container class="main-container">
<el-aside v-bind:class="asideClass">
<LeftNav></LeftNav>
</el-aside>
<el-container>
<el-header class="main-header">
<TopNav></TopNav>
</el-header>
<el-main class="main-center">
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</template>
<script>
// 導(dǎo)入組件
import TopNav from '@/components/TopNav.vue'
import LeftNav from '@/components/LeftNav.vue'
// 導(dǎo)出模塊
export default {
components: {
TopNav,LeftNav
},data() {
return {
asideClass: "main-aside"
}
},
created(){
this.$root.Bus.$on('aaa',r=>{
this.asideClass=r ? 'main-aside-collapsed':'main-aside';
});
}
};
</script>
<style scoped>
.main-container {
height: 100%;
width: 100%;
box-sizing: border-box;
}
.main-aside-collapsed {
/* 在CSS中,通過(guò)對(duì)某一樣式聲明! important ,可以更改默認(rèn)的CSS樣式優(yōu)先級(jí)規(guī)則,使該條樣式屬性聲明具有最高優(yōu)先級(jí) */
width: 64px !important;
height: 100%;
background-color: #334157;
margin: 0px;
}
.main-aside {
width: 240px !important;
height: 100%;
background-color: #334157;
margin: 0px;
}
.main-header,
.main-center {
padding: 0px;
border-left: 2px solid #333;
}
</style>效果演示:

三、右側(cè)內(nèi)容數(shù)據(jù)表格
3.1.根據(jù)文檔搭建頁(yè)面
首先我們分析一下,我們右側(cè)有那些內(nèi)容?然后去到我們ELementUI官網(wǎng)查找相對(duì)應(yīng)的案例代碼,我們首先需要一個(gè)form表單提供我們輸入書(shū)籍名稱進(jìn)行模糊查詢,還需要數(shù)據(jù)表格展示數(shù)據(jù),其次就是底部的分頁(yè)條來(lái)完成分頁(yè)效果,知道了需求我們直接去找案例代碼即可。
AddBook.js
<template>
<div>
<!--搜索欄-->
<el-form :inline="true" class="form-search" style="padding: 30px;">
<el-form-item label="書(shū)本名稱">
<el-input v-model="bookname" placeholder="請(qǐng)輸入書(shū)本名稱"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="query(1)">查詢</el-button>
</el-form-item>
</el-form>
<!-- 數(shù)據(jù)表格-->
<el-table :data="tableData" style="width: 100%" :row-class-name="tableRowClassName">
<el-table-column prop="id" label="編號(hào)" width="180">
</el-table-column>
<el-table-column prop="bookname" label="書(shū)籍名稱" width="180">
</el-table-column>
<el-table-column prop="price" label="書(shū)籍價(jià)格" width="180">
</el-table-column>
<el-table-column prop="booktype" label="書(shū)籍類別" width="180">
</el-table-column>
</el-table>
<!-- 分頁(yè)欄-->
<div class="block">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage4"
:page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper"
:total="400">
</el-pagination>
</div>
</div>
</template>
<script>
export default {
data() {
return {
bookname: "",
tableData: []
}
},
methods: {
}
}
</script>
<style>
.el-table .warning-row {
background: oldlace;
}
.el-table .success-row {
background: #f0f9eb;
}
</style>
這樣我們的基本內(nèi)容就搭建完成了
3.2.實(shí)現(xiàn)模糊查詢
和前面一樣我們先去后端將接口定義好
package com.zking.ssm.controller;
import com.zking.ssm.model.Book;
import com.zking.ssm.service.IBookService;
import com.zking.ssm.util.JsonResponseBody;
import com.zking.ssm.util.PageBean;
import com.zking.ssm.vo.BookFileVo;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/book")
public class BookController {
@Autowired
private IBookService bookService;
@RequestMapping("/addBook")
@ResponseBody
public JsonResponseBody<?> addBook(Book book){
try {
bookService.insert(book);
return new JsonResponseBody<>("新增書(shū)本成功",true,0,null);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("新增書(shū)本失敗",false,0,null);
}
}
@RequestMapping("/editBook")
@ResponseBody
public JsonResponseBody<?> editBook(Book book){
try {
bookService.updateByPrimaryKey(book);
return new JsonResponseBody<>("編輯書(shū)本成功",true,0,null);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("編輯書(shū)本失敗",false,0,null);
}
}
@RequestMapping("/delBook")
@ResponseBody
public JsonResponseBody<?> delBook(Book book){
try {
bookService.deleteByPrimaryKey(book.getId());
return new JsonResponseBody<>("刪除書(shū)本成功",true,0,null);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("刪除書(shū)本失敗",false,0,null);
}
}
@RequestMapping("/queryBookPager")
@ResponseBody
public JsonResponseBody<List<Book>> queryBookPager(Book book, HttpServletRequest req){
try {
PageBean pageBean=new PageBean();
pageBean.setRequest(req);
List<Book> books = bookService.queryBookPager(book, pageBean);
return new JsonResponseBody<>("OK",true,pageBean.getTotal(),books);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("分頁(yè)查詢書(shū)本失敗",false,0,null);
}
}
@RequestMapping("/queryBookCharts")
@ResponseBody
public JsonResponseBody<?> queryBookCharts(){
try{
Map<String, Object> charts = bookService.queryBookCharts();
return new JsonResponseBody<>("OK",true,0,charts);
}catch (Exception e){
e.printStackTrace();
return new JsonResponseBody<>("查詢統(tǒng)計(jì)分析數(shù)據(jù)失敗",false,0,null);
}
}
@RequestMapping("/upload")
@ResponseBody
public JsonResponseBody<?> upload(BookFileVo bookFileVo){
try {
MultipartFile bookFile = bookFileVo.getBookFile();
System.out.println(bookFileVo);
System.out.println(bookFile.getContentType());
System.out.println(bookFile.getOriginalFilename());
return new JsonResponseBody<>("上傳成功",true,0,null);
} catch (Exception e) {
e.printStackTrace();
return new JsonResponseBody<>("上傳失敗",false,0,null);
}
}
@RequestMapping("/download")
public void download(HttpServletRequest request, HttpServletResponse response){
try {
String relativePath = "uploads/1.jpg";
String absolutePath = request.getRealPath(relativePath);
InputStream is = new FileInputStream(new File(absolutePath));
OutputStream out = response.getOutputStream();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
byte[] by = new byte[1024];
int len = -1;
while (-1 != (len = is.read(by))) {
out.write(by);
}
is.close();
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
@RequestMapping("/downloadUrl")
public void downloadUrl(HttpServletRequest request, HttpServletResponse response){
String relativePath = "uploads/1.jpg";
String absolutePath = request.getRealPath(relativePath);
InputStream is = null;
OutputStream out = null;
try {
is = new FileInputStream(new File(absolutePath));
// 設(shè)置Content-Disposition
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
out = response.getOutputStream();
IOUtils.copy(is, out);
response.flushBuffer();
System.out.println("完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(is);
IOUtils.closeQuietly(out);
}
}
}
由此我們可知后端查詢書(shū)籍的接口為:http://localhost:8080/ssm/book/queryBookPager
action.js文件添加下列接口
'BOOK_LIST': '/book/queryBookPager', //書(shū)籍查詢
在AddBook.vue中的鉤子函數(shù)內(nèi)編寫(xiě)方法去到后端拿取數(shù)據(jù)賦予變量
created() {
//加載頁(yè)面先去后端拿數(shù)據(jù)
let params={
bookname:this.bookname
}
let url = this.axios.urls.BOOK_LIST;
this.axios.get(url, {params:params}).then(r => {
console.log(r)
this.tableData = r.data.rows
}).catch(e => {
})
}由于不止我們初始頁(yè)面需要用到這個(gè)方法模糊查詢也要所以我們將該代碼進(jìn)行封裝讓它有復(fù)用性
methods: {
//封裝查詢方法
list(params) {
let url = this.axios.urls.BOOK_LIST;
this.axios.get(url, {
params: params
}).then(r => {
console.log(r)
this.tableData = r.data.rows
}).catch(e => {
})
},
//模糊查詢方法
query() {
let params = {
bookname: this.bookname
}
this.list(params)
}
},
created() {
//加載頁(yè)面先去后端拿數(shù)據(jù)
let params = {
bookname: this.bookname
}
this.list()
}效果展示:

四、分頁(yè)實(shí)現(xiàn)
更改我們的分頁(yè)欄代碼并定義變量,編寫(xiě)分頁(yè)欄中自帶的兩個(gè)方法,一個(gè)是頁(yè)碼發(fā)生變化會(huì)觸發(fā)一個(gè)是頁(yè)數(shù)發(fā)生改變會(huì)觸發(fā)。
<!-- 分頁(yè)欄-->
<div class="block">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page"
:page-sizes="[10, 20, 30, 40]" :page-size="rows" layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div><script>
export default {
data() {
return {
bookname: "",
tableData: [],
rows: 10,
page: 1,
total: 0,
}
},
methods: {
//封裝查詢方法
list(params) {
let url = this.axios.urls.BOOK_LIST;
this.axios.get(url, {
params: params
}).then(r => {
console.log(r)
this.tableData = r.data.rows
this.total = r.data.total
}).catch(e => {
})
},
//模糊查詢方法
query() {
let params = {
bookname: this.bookname
}
this.list(params)
},
//當(dāng)頁(yè)發(fā)生變化會(huì)觸發(fā)
handleSizeChange(r) {
let params = {
bookname: this.bookname,
rows: this.rows,
rows: r
}
this.list(params)
},
//當(dāng)前頁(yè)數(shù)發(fā)生變化會(huì)觸發(fā)
handleCurrentChange(p) {
let params = {
bookname: this.bookname,
rows: this.rows,
page: p
}
this.list(params)
}
},
created() {
//加載頁(yè)面先去后端拿數(shù)據(jù)
let params = {
bookname: this.bookname
}
this.list()
}
}
</script>效果展示:

總結(jié)
到此這篇關(guān)于基于Vue+ELement搭建動(dòng)態(tài)樹(shù)與數(shù)據(jù)表格實(shí)現(xiàn)分頁(yè)模糊查詢的文章就介紹到這了,更多相關(guān)Vue+ELement分頁(yè)模糊查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解swiper在vue中的應(yīng)用(以3.0為例)
這篇文章主要介紹了詳解swiper在vue中的應(yīng)用(以3.0為例),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
vue3中使用router路由實(shí)現(xiàn)跳轉(zhuǎn)傳參的方法
這篇文章主要介紹了vue3中使用router路由實(shí)現(xiàn)跳轉(zhuǎn)傳參的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03
解決vue ui報(bào)錯(cuò)Couldn‘t parse bundle asset“C:
這篇文章主要介紹了解決vue ui報(bào)錯(cuò)Couldn‘t parse bundle asset“C:\Users\Administrator\vue_project1\dist\js\about.js“. Analyzer問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
Vue封裝localStorage設(shè)置過(guò)期時(shí)間的示例詳解
這篇文章主要介紹了Vue封裝localStorage設(shè)置過(guò)期時(shí)間的相關(guān)資料,在這個(gè)示例中,我們?cè)贛yComponent.vue組件的setup函數(shù)中導(dǎo)入了setItemWithExpiry和getItemWithExpiry函數(shù),并在函數(shù)內(nèi)部使用它們來(lái)設(shè)置和獲取帶有過(guò)期時(shí)間的localStorage數(shù)據(jù),需要的朋友可以參考下2024-06-06
vue實(shí)現(xiàn)自定義H5視頻播放器的方法步驟
這篇文章主要介紹了vue實(shí)現(xiàn)自定義H5視頻播放器的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
vue使用echarts時(shí)created里拿到的數(shù)據(jù)無(wú)法渲染的解決
這篇文章主要介紹了vue使用echarts時(shí)created里拿到的數(shù)據(jù)無(wú)法渲染的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03

