• 基于Vue+ELement搭建动态树与数据表格实现分页


    🎉🎉欢迎来到我的CSDN主页!🎉🎉

    🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚

    🌟推荐给大家我的专栏《ELement》。🎯🎯

    👉点击这里,就可以查看我的主页啦!👇👇

    Java方文山的个人主页

    🎁如果感觉还不错的话请给我点赞吧!🎁🎁

    💖期待你的加入,一起学习,一起进步!💖💖

    请添加图片描述

    目录

    一、前言

    二、左侧动态树实现

    2.1.后台数据接口定义

    2.2.前端导航菜单绑定

    2.3.根据数据渲染页面

    2.4.动态路由实现

    三、右侧内容数据表格

    3.1.根据文档搭建页面

    3.2.实现模糊查询

    四、分页实现


    一、前言

    在上一篇博文我们搭建了首页导航和左侧菜单,但是我们的左侧菜单是死数据今天我们就来把死的变成活的,并且完成右侧内容的书籍数据表格的展示与分页效果,话不多说上代码!!

    二、左侧动态树实现

    2.1.后台数据接口定义

    首先我们将后端的代码写好Controller层代码

    1. package com.zking.ssm.controller;
    2. import com.zking.ssm.model.Module;
    3. import com.zking.ssm.model.RoleModule;
    4. import com.zking.ssm.model.TreeNode;
    5. import com.zking.ssm.service.IModuleService;
    6. import com.zking.ssm.util.JsonResponseBody;
    7. import org.springframework.beans.factory.annotation.Autowired;
    8. import org.springframework.stereotype.Controller;
    9. import org.springframework.web.bind.annotation.RequestMapping;
    10. import org.springframework.web.bind.annotation.ResponseBody;
    11. import java.util.List;
    12. @Controller
    13. @RequestMapping("/module")
    14. public class ModuleController {
    15. @Autowired
    16. private IModuleService moduleService;
    17. @RequestMapping("/queryRootNode")
    18. @ResponseBody
    19. public JsonResponseBody> queryRootNode(){
    20. try {
    21. List modules = moduleService.queryRootNode(-1);
    22. return new JsonResponseBody<>("OK",true,0,modules);
    23. } catch (Exception e) {
    24. e.printStackTrace();
    25. return new JsonResponseBody<>("初始化首页菜单错误",false,0,null);
    26. }
    27. }
    28. @RequestMapping("/queryElementTree")
    29. @ResponseBody
    30. public JsonResponseBody> queryElementTree(){
    31. try {
    32. List modules = moduleService.queryTreeNode(-1);
    33. return new JsonResponseBody<>("OK",true,0,modules);
    34. } catch (Exception e) {
    35. e.printStackTrace();
    36. return new JsonResponseBody<>("初始化ElementUI的Tree组件错误",false,0,null);
    37. }
    38. }
    39. @RequestMapping("/addRoleModule")
    40. @ResponseBody
    41. public JsonResponseBody addRoleModule(RoleModule roleModule){
    42. try {
    43. moduleService.addRoleModule(roleModule);
    44. return new JsonResponseBody<>("新增角色权限成功",true,0,null);
    45. } catch (Exception e) {
    46. e.printStackTrace();
    47. return new JsonResponseBody<>("新增角色权限失败",false,0,null);
    48. }
    49. }
    50. @RequestMapping("/queryModuleByRoleId")
    51. @ResponseBody
    52. public JsonResponseBody> queryModuleByRoleId(RoleModule roleModule){
    53. try {
    54. List modules = moduleService.queryModuleByRoleId(roleModule);
    55. return new JsonResponseBody<>("OK",true,0,modules);
    56. } catch (Exception e) {
    57. e.printStackTrace();
    58. return new JsonResponseBody<>("获取角色权限失败",false,0,null);
    59. }
    60. }
    61. }

    由此我们可知后端查询的树形菜单的接口为:http://localhost:8080/ssm/module/queryRootNode

    2.2.前端导航菜单绑定

    数据有了我们只用考虑怎么通过Vue拿到数据以及展示数据就可以了。

    找到src下面的api目录下的action.js文件添加下列接口

      'SYSTEM_USER_MODULE': '/module/queryRootNode', //左侧菜单

     在LeftNav.vue中的钩子函数内编写方法去到后端拿取数据赋予变量

    1. created() {
    2. this.$root.Bus.$on('aaa', r => {
    3. this.collapsed = r;
    4. });
    5. //加载页面先去后端拿数据
    6. let url = this.axios.urls.SYSTEM_USER_MODULE;
    7. this.axios.get(url, {}).then(r => {
    8. this.menus=r.data.rows
    9. }).catch(e => {
    10. })
    11. }

    并在data中定义变量 menus:[]

     menus:[]

    2.3.根据数据渲染页面

    去到我们ELement查找相应的代码进行cv,下面是我找好的你们直接用,我们现在只需要将后端获取到的数据在上面的代码中进行遍历即可。

    1. <el-submenu v-for="m in menus" :index="'ind_'+m.id" :key="'key_'+m.id">
    2. <template slot="title">
    3. <i :class="m.icon">i>
    4. <span>{{m.text}}span>
    5. template>
    6. <el-menu-item v-for="ms in m.modules" :index="ms.url" :key="'key_'+ms.id">
    7. <i :class="ms.icon">i>
    8. <span>{{ms.text}}span>
    9. el-menu-item>
    10. el-submenu>

    效果展示:

    2.4.动态路由实现

    我们点击下方的子菜单肯定会显示右侧白框里面的内容,所以我们需要实现动态路由

    ①实现路由跳转及当前项的设置

    1. default-active="$route.path">
    2. <el-menu-item index="/company/userManager">用户管理el-menu-item>

    注意事项:

    ①要实现路由跳转,先要在el-menu标签上添加router属性,然后只要在每个el-menu-item标签内的index属性设置一下url即可实现点击el-menu-item实现路由跳转。

    ②导航当前项,在el-menu标签中绑定 :default-active="$route.path",注意是绑定属性,不要忘了加“:”,当$route.path等于el-menu-item标签中的index属性值时则该item为当前项。

    ③el-submenu标签中的url属性不能为空,且不能相同,否则会导致多个节点收缩/折叠效果相同的问题。

    ②生成相对应的Vue文件

    根据我们点击子菜单所显示的层级关系进行Vue组件的编写,下面以书本管理下面的新增书本为例

    AddBook.Vue

    1. <script>
    2. script>
    3. <style>
    4. style>

    ③配置路由与路由路径的关系 

    index.js

    1. import Vue from 'vue'
    2. import Router from 'vue-router'
    3. import HelloWorld from '@/components/HelloWorld'
    4. import AppMain from '@/components/AppMain'
    5. import LeftNav from '@/components/LeftNav'
    6. import TopNav from '@/components/TopNav'
    7. import Login from '@/views/Login'
    8. import Registered from '@/views/Registered'
    9. import AddBook from '@/views/book/AddBook'
    10. import BookList from '@/views/book/BookList'
    11. Vue.use(Router)
    12. export default new Router({
    13. routes: [{
    14. path: '/',
    15. name: 'Login',
    16. component: Login
    17. }, {
    18. path: '/Registered',
    19. name: 'Registered',
    20. component: Registered
    21. }, {
    22. path: '/AppMain',
    23. name: 'AppMain',
    24. component: AppMain,
    25. children: [{
    26. path: '/LeftNav',
    27. name: 'LeftNav',
    28. component: LeftNav
    29. }, {
    30. path: '/TopNav',
    31. name: 'TopNav',
    32. component: TopNav
    33. }, {
    34. path: '/book/AddBook',
    35. name: 'AddBook',
    36. component: AddBook
    37. }, {
    38. path: '/book/BookList',
    39. name: 'BookList',
    40. component: BookList
    41. }]
    42. }]
    43. })

    ④将组件渲染到页面上

    在AppMain.js中显示组件就需要加上

    1. <script>
    2. // 导入组件
    3. import TopNav from '@/components/TopNav.vue'
    4. import LeftNav from '@/components/LeftNav.vue'
    5. // 导出模块
    6. export default {
    7. components: {
    8. TopNav,LeftNav
    9. },data() {
    10. return {
    11. asideClass: "main-aside"
    12. }
    13. },
    14. created(){
    15. this.$root.Bus.$on('aaa',r=>{
    16. this.asideClass=r ? 'main-aside-collapsed':'main-aside';
    17. });
    18. }
    19. };
    20. script>
    21. <style scoped>
    22. .main-container {
    23. height: 100%;
    24. width: 100%;
    25. box-sizing: border-box;
    26. }
    27. .main-aside-collapsed {
    28. /* 在CSS中,通过对某一样式声明! important ,可以更改默认的CSS样式优先级规则,使该条样式属性声明具有最高优先级 */
    29. width: 64px !important;
    30. height: 100%;
    31. background-color: #334157;
    32. margin: 0px;
    33. }
    34. .main-aside {
    35. width: 240px !important;
    36. height: 100%;
    37. background-color: #334157;
    38. margin: 0px;
    39. }
    40. .main-header,
    41. .main-center {
    42. padding: 0px;
    43. border-left: 2px solid #333;
    44. }
    45. style>

    效果演示:

    三、右侧内容数据表格

    3.1.根据文档搭建页面

    首先我们分析一下,我们右侧有那些内容?然后去到我们ELementUI官网查找相对应的案例代码,我们首先需要一个form表单提供我们输入书籍名称进行模糊查询,还需要数据表格展示数据,其次就是底部的分页条来完成分页效果,知道了需求我们直接去找案例代码即可。

    AddBook.js

    1. <script>
    2. export default {
    3. data() {
    4. return {
    5. bookname: "",
    6. tableData: []
    7. }
    8. },
    9. methods: {
    10. }
    11. }
    12. script>
    13. <style>
    14. .el-table .warning-row {
    15. background: oldlace;
    16. }
    17. .el-table .success-row {
    18. background: #f0f9eb;
    19. }
    20. style>

    这样我们的基本内容就搭建完成了 

    3.2.实现模糊查询

    和前面一样我们先去后端将接口定义好

    1. package com.zking.ssm.controller;
    2. import com.zking.ssm.model.Book;
    3. import com.zking.ssm.service.IBookService;
    4. import com.zking.ssm.util.JsonResponseBody;
    5. import com.zking.ssm.util.PageBean;
    6. import com.zking.ssm.vo.BookFileVo;
    7. import org.apache.commons.io.IOUtils;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.stereotype.Controller;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.ResponseBody;
    12. import org.springframework.web.multipart.MultipartFile;
    13. import javax.servlet.http.HttpServletRequest;
    14. import javax.servlet.http.HttpServletResponse;
    15. import java.io.File;
    16. import java.io.FileInputStream;
    17. import java.io.InputStream;
    18. import java.io.OutputStream;
    19. import java.net.URLEncoder;
    20. import java.util.List;
    21. import java.util.Map;
    22. @Controller
    23. @RequestMapping("/book")
    24. public class BookController {
    25. @Autowired
    26. private IBookService bookService;
    27. @RequestMapping("/addBook")
    28. @ResponseBody
    29. public JsonResponseBody addBook(Book book){
    30. try {
    31. bookService.insert(book);
    32. return new JsonResponseBody<>("新增书本成功",true,0,null);
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. return new JsonResponseBody<>("新增书本失败",false,0,null);
    36. }
    37. }
    38. @RequestMapping("/editBook")
    39. @ResponseBody
    40. public JsonResponseBody editBook(Book book){
    41. try {
    42. bookService.updateByPrimaryKey(book);
    43. return new JsonResponseBody<>("编辑书本成功",true,0,null);
    44. } catch (Exception e) {
    45. e.printStackTrace();
    46. return new JsonResponseBody<>("编辑书本失败",false,0,null);
    47. }
    48. }
    49. @RequestMapping("/delBook")
    50. @ResponseBody
    51. public JsonResponseBody delBook(Book book){
    52. try {
    53. bookService.deleteByPrimaryKey(book.getId());
    54. return new JsonResponseBody<>("删除书本成功",true,0,null);
    55. } catch (Exception e) {
    56. e.printStackTrace();
    57. return new JsonResponseBody<>("删除书本失败",false,0,null);
    58. }
    59. }
    60. @RequestMapping("/queryBookPager")
    61. @ResponseBody
    62. public JsonResponseBody> queryBookPager(Book book, HttpServletRequest req){
    63. try {
    64. PageBean pageBean=new PageBean();
    65. pageBean.setRequest(req);
    66. List books = bookService.queryBookPager(book, pageBean);
    67. return new JsonResponseBody<>("OK",true,pageBean.getTotal(),books);
    68. } catch (Exception e) {
    69. e.printStackTrace();
    70. return new JsonResponseBody<>("分页查询书本失败",false,0,null);
    71. }
    72. }
    73. @RequestMapping("/queryBookCharts")
    74. @ResponseBody
    75. public JsonResponseBody queryBookCharts(){
    76. try{
    77. Map charts = bookService.queryBookCharts();
    78. return new JsonResponseBody<>("OK",true,0,charts);
    79. }catch (Exception e){
    80. e.printStackTrace();
    81. return new JsonResponseBody<>("查询统计分析数据失败",false,0,null);
    82. }
    83. }
    84. @RequestMapping("/upload")
    85. @ResponseBody
    86. public JsonResponseBody upload(BookFileVo bookFileVo){
    87. try {
    88. MultipartFile bookFile = bookFileVo.getBookFile();
    89. System.out.println(bookFileVo);
    90. System.out.println(bookFile.getContentType());
    91. System.out.println(bookFile.getOriginalFilename());
    92. return new JsonResponseBody<>("上传成功",true,0,null);
    93. } catch (Exception e) {
    94. e.printStackTrace();
    95. return new JsonResponseBody<>("上传失败",false,0,null);
    96. }
    97. }
    98. @RequestMapping("/download")
    99. public void download(HttpServletRequest request, HttpServletResponse response){
    100. try {
    101. String relativePath = "uploads/1.jpg";
    102. String absolutePath = request.getRealPath(relativePath);
    103. InputStream is = new FileInputStream(new File(absolutePath));
    104. OutputStream out = response.getOutputStream();
    105. response.setContentType("application/octet-stream");
    106. response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
    107. byte[] by = new byte[1024];
    108. int len = -1;
    109. while (-1 != (len = is.read(by))) {
    110. out.write(by);
    111. }
    112. is.close();
    113. out.close();
    114. } catch (Exception e) {
    115. e.printStackTrace();
    116. }
    117. }
    118. @RequestMapping("/downloadUrl")
    119. public void downloadUrl(HttpServletRequest request, HttpServletResponse response){
    120. String relativePath = "uploads/1.jpg";
    121. String absolutePath = request.getRealPath(relativePath);
    122. InputStream is = null;
    123. OutputStream out = null;
    124. try {
    125. is = new FileInputStream(new File(absolutePath));
    126. // 设置Content-Disposition
    127. response.setHeader("Content-Disposition",
    128. "attachment;filename=" + URLEncoder.encode("1.jpg", "UTF-8"));
    129. out = response.getOutputStream();
    130. IOUtils.copy(is, out);
    131. response.flushBuffer();
    132. System.out.println("完成");
    133. } catch (Exception e) {
    134. e.printStackTrace();
    135. } finally {
    136. IOUtils.closeQuietly(is);
    137. IOUtils.closeQuietly(out);
    138. }
    139. }
    140. }

     由此我们可知后端查询书籍的接口为:http://localhost:8080/ssm/book/queryBookPager

     action.js文件添加下列接口

    'BOOK_LIST': '/book/queryBookPager', //书籍查询

     在AddBook.vue中的钩子函数内编写方法去到后端拿取数据赋予变量

    1. created() {
    2. //加载页面先去后端拿数据
    3. let params={
    4. bookname:this.bookname
    5. }
    6. let url = this.axios.urls.BOOK_LIST;
    7. this.axios.get(url, {params:params}).then(r => {
    8. console.log(r)
    9. this.tableData = r.data.rows
    10. }).catch(e => {
    11. })
    12. }

    由于不止我们初始页面需要用到这个方法模糊查询也要所以我们将该代码进行封装让它有复用性

    1. methods: {
    2. //封装查询方法
    3. list(params) {
    4. let url = this.axios.urls.BOOK_LIST;
    5. this.axios.get(url, {
    6. params: params
    7. }).then(r => {
    8. console.log(r)
    9. this.tableData = r.data.rows
    10. }).catch(e => {
    11. })
    12. },
    13. //模糊查询方法
    14. query() {
    15. let params = {
    16. bookname: this.bookname
    17. }
    18. this.list(params)
    19. }
    20. },
    21. created() {
    22. //加载页面先去后端拿数据
    23. let params = {
    24. bookname: this.bookname
    25. }
    26. this.list()
    27. }

    效果展示:

    四、分页实现

    更改我们的分页栏代码并定义变量,编写分页栏中自带的两个方法,一个是页码发生变化会触发一个是页数发生改变会触发。

    1. <div class="block">
    2. <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page"
    3. :page-sizes="[10, 20, 30, 40]" :page-size="rows" layout="total, sizes, prev, pager, next, jumper"
    4. :total="total">
    5. el-pagination>
    6. div>

    效果展示:

    请添加图片描述

    到这里我的分享就结束了,欢迎到评论区探讨交流!!

    💖如果觉得有用的话还请点个赞吧 💖

  • 相关阅读:
    与商超便利店巨头内卷“即时零售”
    CEC2018:动态多目标测试函数DF10~DF14的PS及PF
    7-5 最大子矩阵和问题
    通过字符设备驱动的分步实现编写LED驱动,另外实现特备文件和设备的绑定
    策略模式在springboot中的使用
    SpringBoot 01: JavaConfig + @ImportResource + @PropertyResource
    idea项目找不到符号
    登场即王炸!木牛4D成像雷达迭代升级,挑战高阶智驾感知最高性能
    “Fatal error compiling: 无效的目标发行版: 11“的解决
    springboot + layui + pageHepler 实现table 表格分页并且多行小计功能
  • 原文地址:https://blog.csdn.net/weixin_74318097/article/details/133313100