VUE===(4)Element Tree树形图,路由设置


一、Element Tree树形图 后台 前台

1. 后台


/**
 * @author zhangyifan
 * @version 8.0
 * @description:
 * @date 2021/12/11 9:56
 */
@Service
public class MenuServiceImpl implements MenuService {
    @Resource
    private MenuMapper menuMapper;

    @Override
    public List<TreeNode> queryTreeData() {
        //第义绑定所有数据后的
        List<TreeNode> returnTreeNodeList=new ArrayList<>();
        //查询所有的菜单列表
        List<TreeNode> treeNodes = menuMapper.queryAll();
        //判断是否为空
        if (treeNodes!=null&&treeNodes.size()>0){
            //循环查询一级菜单
            for (TreeNode treeNode:treeNodes){
                if (treeNode.getParentId()==0){
                    //把一级菜单放入返回集合
                    returnTreeNodeList.add(treeNode);
                    //递归查找子菜单
                    bindChildren(treeNode,treeNodes);
                }
            }
        }
        return returnTreeNodeList;
    }

    /**
     * 递归查询子菜单并绑定
     * @param currentNode
     * @param treeNodeList
     */
    private void bindChildren(TreeNode currentNode,List<TreeNode> treeNodeList){
        for (TreeNode treeNode:treeNodeList){
            //查找当前节点
            if (treeNode.getParentId()==currentNode.getId()){
                //获取当前节点集合
                List<TreeNode> chil= currentNode.getChildren();
                //如果是第一次就实例化子节点
                if (chil==null){
                    chil=new ArrayList<TreeNode>();
                }
                chil.add(treeNode);
                currentNode.setChildren(chil);
                //报错  ArrayList不允许  查询和删除同时进行
                //treeNodeList.remove(treeNode);
                //自己调用自己,为当前循环节点再找孩子
                bindChildren(treeNode,treeNodeList);
            }
        }

    }
}

2. 前台

<template>
  <div>
    <el-container>
      <el-header>
        <!-- 头部组建 -->
        <Header />
      </el-header>
      <el-container>
        <el-aside width="200px">
          <!-- 左边树形图位置-->
          <LeftTree></LeftTree>
        </el-aside>
        <el-main>
          <div>
            <router-view />
          </div>
        </el-main>
      </el-container>
      <el-footer>Footer</el-footer>
    </el-container>
  </div>
</template>
<script>
import Header from "@/components/header.vue";
import LeftTree from "../components/LetfTree.vue";

export default {
  //注册属性 父传子 数据传递
  props: {},
  data() {
    return {}; //定义数据
  },
  //created在模板渲染成html前调用,通常在这里初始化某些属性,然后再渲染视图
  created() {},
  computed: {},
  //方法事件处理
  methods: {},
  //组件注册
  components: {
    LeftTree,
    Header,
  },
};
</script>
 
<style>
.el-header,
.el-footer {
  background-color: #cdb79e;
  color: #d3dce6;
  text-align: center;
  line-height: 60px;
}

.el-aside {
  background-color: #f5fffa;
  color: #d3dce6;
  text-align: center;
  line-height: 200px;
}

.el-main {
  background-color: #e9eef3;
  color: #d3dce6;
  text-align: center;
  line-height: 160px;
}

body > .el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}
</style>

<template>
    <div>
      <el-tree :data="treData" :props="defaultProps" @node-click="handleNodeClick"></el-tree> 
      <!-- //element官网复制 -->
    </div>
</template>
<script>
export default {
//注册属性 父传子 数据传递
    props: { 
   },
   data() {
      return { 
         treData: []
         ,defaultProps: {
            children: 'children',
            label: 'label'
         }
      }//定义数据
   },
//created在模板渲染成html前调用,通常在这里初始化某些属性,然后再渲染视图
   created(){ 
      this.loadData();
   },
//方法事件处理
   methods:{ 
       //封装一个通用请求并加载数据的方法
      loadData(){
         var _this=this;
         this.$http.get("/menu/queryTreeData")
         .then(function(response){
              _this.treData = response.data.data;
         })
      },
       handleNodeClick(data) {//判空
            if(data.url!=null&&data.url!=''&&data.url!='null'&&data.url!=undefined){
          this.$router.push(data.url);
        } 
        console.log(data);
      }

   },
//组件注册
 components: { 
},
}
</script>
<style>

</style>

二、路由设置

1.路由

Vue Router 是 Vue.js 官方的路由管理器。Vue.js 路由允许我们通过不同的 URL 访问不同的内容。根据 url 锚点路径,在容器中加载不同的模块,本质作用是做页面导航。通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)(单页面应用开发)

  • 一种特殊的Web应用。它将所有的活动局限于一个Web页面中,仅在该Web页面初始化时加载相应的HTML、JavaScript、CSS。
  • 一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转,而是利用JavaScript动态的变换HTML(采用的是div切换显示和隐藏),从而实现UI与用户的交互

2、路由配置

1、路由功能的引入\

路由官网

直接下载 / CDN
CDN:https://unpkg.com/vue-router@3.0.1/dist/vue-router.js
使用 vue-router.js 库来引入路由功能模块
NPM

npm install vue-router

2、一级路由的配置

在这里插入图片描述

3、在@vue/cli创建的项目中,路由用法如下。

1、安装路由 npm install vue-router

2、在src目录下创建router文件夹,并在其内创建index.js作为vue路由功能模块js文件
2.1:定义路由所需的组件(.vue文件)
2.2:创建 router 实例,然后传 routes 配置
2.3:定义路由
2.4:默认输出路由对象
3、在main.js中,实例化vue对象时,注册路由
在这里插入图片描述
4、在页面定义导航和路由出口
#src/router/index.js

4、在一个模块化工程中使用它,必须要通过 Vue.use() 明确地安装路由功能:

import Vue from ‘vue’
import App from ‘./App.vue’
import router from ‘./router’

1.引入定义好的路由所需组件
1.1:import Home from ‘…/views/Home.vue’
1.2:配置路由时按需引入

2.创建router实例,传入routes配置项。你还可以传别的配置参数,详细配置信息可参阅手册

const router = new VueRouter({ routes:[] //定义路由配置
mode:“hash” | “history” | “abstract” //定义路由模式
//hash: 使用 URL hash 值来作路由。支持所有浏览器
//history: 依赖 HTML5 History API 和服务器配置
//abstract: 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。 … });

3.定义路由。每个路由应该映射一个组件
routes:是一个数组,数组成员是一个个对象,包含每个路由的具体配置,详细配置信息可参阅手册

const router = new VueRouter({        
		routes:[    
				{                
					path:String //定义路由路径                
					name:String //定义命名路由                
					component:Component //路由所映射的组件,1.直接导入引用 2:路由懒加载                
					//component:Home,               
					 //conponent:()=>import('./../views/Home.vue')                 
					 children:Array //定义嵌套路由,子路由                
					 redirect:String|Location|Function //路由重定向  
					   }       
				]   
		}
			);

在这里插入图片描述

4.默认输出路由对象

 export default router;

#src/main.js
#通过注入路由器,我们可以在任何组件内通过 this. r o u t e r 访问路由器,也可以通过 t h i s . router 访问路由器,也可以通过 this. router访问路由器,也可以通过this.route 访问当前路由​

import router from './router'
new Vue({  
router,  
render: h => h(App)
}).$mount('#app')

#App.vue

5、在页面定义导航

//使用 router-link 组件来导航
//通过传入 to 属性指定链接(目标地址)
// 默认会被渲染成一个 <a> 标签home
#router-link有很多属性,具体参阅文档
to:目标地址
tag:指定何种标签,同样它还是会监听点击,触发导航。默认a
active-class:设置链接激活时使用的 CSS 类名
exact:精确匹配模式
要注意,当 对应的路由匹配成功,将自动设置 class 属性值 .router-link-active​

2.定义路由出口
//路由匹配到的组件将渲染在这里

<router-view></router-view>

3、二级路由(嵌套路由)

在这里插入图片描述

二级路由配置

 routes:[
     {        
     path:'/home',        
     children:[            
     // 二级路由,path分配,前面不要有 /            
     //redirect 重定向            
     {path:'/',redirect:'/home/tv'},            
     {path:'tv',component:()=>import('./../components/tv.vue')},            
     {path:'music',component:()=>import('./../components/music.vue')}
             ] 
                 }
                 ]

在一级路由组件模版中定义二级路由导航和路由出口

<!--  在一级路由组件模版中,定义二级路由导航 -->
<router-link to='/home/tv'>tv</router-link>
<!--  在一级路由组件模版中,定义二级路由出口-->
<router-view></router-view>

4、动态路由匹配(路由传参)

我们经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,我们有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用“动态路径参数”来达到这个效果:

const router = new VueRouter({
  routes: [
     // 动态路径参数 以冒号开头    
     { path: '/user/:id', component: User } 
  ]
})
//现在呢,像 /user/foo 和 /user/bar 都将映射到相同的路由

<router-link to='/user/uid00001'>张三</router-link>
<router-link to='/user/uid00002'>李四</router-link>

//一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,我们可以更新 User 的模板,输出当前用户的 ID:
<div>User {{ $route.params.id }}</div>

在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。使用 props 将组件和路由解耦:
const User = {
  props: ['id'],
  template: '<div>User {{ id }}</div>'}
const router = new VueRouter({
  routes: [    
  { path: '/user/:id', component: User, props: true }  ]})

5、编程式路由

除了使用 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

router.push()

#在 Vue 实例内部,你可以通过 r o u t e r 访问路由实例。因此你可以调用 t h i s . router 访问路由实例。 因此你可以调用 this. router访问路由实例。因此你可以调用this.router.push。
在这里插入图片描述
想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。当你点击 时,这个方法会在内部调用,所以说,点击 等同于调用 router.push(…)。
声明式 | 编程式
| router.push(…)
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

router.replace()

跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
声明式 | 编程式
| router.replace(…)

// 在浏览器记录中前进一步,等同于 history.forward()
router.go(1)
// 后退一步记录,等同于 history.back()
 router.go(-1)
 // 前进 3 步记录
router.go(3)// 如果 history 记录不够用,那就默默地失败呗
router.go(-100)
router.go(100)
 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Network porter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值