基于Vue+ELement搭建動(dòng)態(tài)樹(shù)與數(shù)據(jù)表格實(shí)現(xiàn)分頁(yè)模糊查詢(xún)實(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); } } }
由此我們可知后端查詢(xún)的樹(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">用戶(hù)管理</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ū)籍名稱(chēng)進(jìn)行模糊查詢(xú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ū)本名稱(chēng)"> <el-input v-model="bookname" placeholder="請(qǐng)輸入書(shū)本名稱(chēng)"></el-input> </el-form-item> <el-form-item> <el-button type="primary" icon="el-icon-search" @click="query(1)">查詢(xún)</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ū)籍名稱(chēng)" 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ū)籍類(lèi)別" 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)模糊查詢(xú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è)查詢(xún)書(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<>("查詢(xún)統(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); } } }
由此我們可知后端查詢(xún)書(shū)籍的接口為:http://localhost:8080/ssm/book/queryBookPager
action.js文件添加下列接口
'BOOK_LIST': '/book/queryBookPager', //書(shū)籍查詢(xún)
在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è)方法模糊查詢(xún)也要所以我們將該代碼進(jìn)行封裝讓它有復(fù)用性
methods: { //封裝查詢(xún)方法 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 => { }) }, //模糊查詢(xún)方法 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: { //封裝查詢(xún)方法 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 => { }) }, //模糊查詢(xún)方法 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è)模糊查詢(xún)的文章就介紹到這了,更多相關(guān)Vue+ELement分頁(yè)模糊查詢(xún)內(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-09vue3中使用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-04Vue封裝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-06vue輪詢(xún)請(qǐng)求解決方案的完整實(shí)例
項(xiàng)目開(kāi)發(fā)中需要做一個(gè)輪詢(xún),所以將實(shí)現(xiàn)的過(guò)程記錄了一下,下面這篇文章主要給大家介紹了關(guān)于vue輪詢(xún)解決方案的相關(guān)資料,需要的朋友可以參考下2021-07-07vue實(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-07vue使用echarts時(shí)created里拿到的數(shù)據(jù)無(wú)法渲染的解決
這篇文章主要介紹了vue使用echarts時(shí)created里拿到的數(shù)據(jù)無(wú)法渲染的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03