Vue.js知识——路由(二)

x33g5p2x  于2021-11-21 转载在 Vue.js  
字(6.1k)|赞(0)|评价(0)|浏览(477)

路由

全局导航守卫

导航:“导航”表示路由正在发生改变。
vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

全局前置守卫

当有这么一个需求,当页面进行跳转的时候,最上方的页面标题也会跟着修改。

注册语法如下:

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})

紧接着前一个博客的路由文件:

//index.js
const routes = [
  {
    path: '/',
    redirect: '/home',
  },
  {
    path: '/home',
    component: Home,
    children:[
      {
        path:'/',
        redirect:'/home/news',
      },
      {
        path:'news',
        component:HomeNews,
        meta:{
          title:"首页-新闻"
        }
      },
      {
        path:'message',
        component:HomeMessage,
        meta:{
          title:"首页-消息"
        }
      }
    ],
    meta:{
      title:'首页'
    }
  },
  {
    path: '/about',
    component: About,
    meta:{
      title:'关于'
    }
  },
  {
    path: '/user/:userId',
    component: User,
    meta:{
      title:'用户'
    }
  }
]

const router = new VueRouter({
  routes,
  mode: "history",
  linkActiveClass: "active"
})

router.beforeEach((to,from,next) =>{
  document.title = to.meta.title
  next()
})

注意:在to这个对象中有一个matched属性,该属性是个数组,在索引为0的下的属性中也有一个meta属性,如果路由中有嵌套,在子路由中也是显示父路由的标题,上述的代码就应该改成:

router.beforeEach((to,from,next) =>{
  document.title = to.match[0].meta.title
  next()
})

meta : 元数据(描述数据的数据)

keep-alive

keep-alive是Vue内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染。

当组件在keep-alive内被切换时组件的activated、deactivated这两个生命周期钩子函数会被执行
被包裹在keep-alive中的组件的状态将会被保留。

router-view是一个组件,如果直接被包在keep-alive里面,所有路径匹配到的视图组件都会被缓存。

例子:
希望用户原先在浏览消息页面,然后跳转到其他页面再回来首页时,页面依然停留在消息页面。

  1. 首先需要将需要缓存的内容视图包含在keep-alive标签中
<!--App.vue-->
<template>
  <div>
    <router-link to='/home' active-class="active">首页</router-link>
    <router-link to='/about' active-class="active">关于</router-link>
    <router-link :to="'/user/'+userId" active-class="active">用户</router-link>
    <keep-alive>
      <router-view></router-view>
    </keep-alive>
  </div>
</template>
  1. 在Home.vue中定义activated函数,每次进入首页页面时,路由保存的路径是上次浏览的页面,定义beforeRouteLeave函数,用于保存每次在路由发生变化时,保存当前浏览的页面,以便下次再次进入时,浏览的依然是保存的页面。
export default {
  name: "Home",
  activated(){
    this.$router.push(this.path)
  },
  beforeRouteLeave(to,from,next){         
    this.path = this.$route.path
    next()
  }
}

keep-alive有两个重要的属性:

  • include - 字符串或者正则表达式,只有匹配的组件会被缓存
  • exclude - 字符串或者正则表达式,任何匹配的组件都不会被缓存

如果不想让用户这个组件缓存,就可以这样写

<keep-alive exclude="User">
      <router-view></router-view>
    </keep-alive>

TabBar

底部导航栏

为了能够让底部导航栏可以复用,所以要对TabBar组件进行封装

  1. 首先在components文件夹中创建tabbar的文件夹,在文件夹下再创建一个TabBar.vue组件
//TabBar.vue

<template>
  <div id="tab-bar">
      <div class="tab-bar-item">首页</div>
      <div class="tab-bar-item">分类</div>
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
</template>

<script> export default { name:"TabBar" } </script>

<style> #tab-bar{ display: flex; background-color: #f6f6f6; position: fixed; left: 0; right: 0; bottom: 0; box-shadow: 0 -10px 1px rgba(100,100,100,0.05); } .tab-bar-item{ flex: 1; text-align: center; height: 49px; } </style>
  1. 其次要在App.vue文件进行注册并使用
//App.vue

<template>
  <div id="app">
    <tab-bar></tab-bar>
  </div>
</template>

<script> import TabBar from './components/tabbar/TabBar.vue' export default { name:'App', components:{ TabBar } } </script>
<style> @import url('./assets/css/base.css'); //在base.css文件中设置了margin,padding都为0 </style>

此时在页面的底部就出现了导航栏:

  1. 完成上述内容之后发现没有图标,可以到阿里巴巴矢量图标库下载svg图标, 将下载好的svg文件放在src/assets/img/tabbar下,注意:一个页面下载两个图标,分别为选中与未选中状态
  2. 导入图片文件
//TabBar.vue

<template>
  <div id="tab-bar">
      <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/home.svg">
      <div>首页</div>
      </div>
      <div class="tab-bar-item">
      <img src="../../assets/img/tabbar/home.svg">
      <div>分类</div>
      </div>  //依次类推
      <div class="tab-bar-item">购物车</div>
      <div class="tab-bar-item">我的</div>
    </div>
</template>

<script> export default { name:"TabBar" } </script>

<style> #tab-bar{ display: flex; background-color: #f6f6f6; position: fixed; left: 0; right: 0; bottom: 0; box-shadow: 0 -10px 1px rgba(100,100,100,0.05); } .tab-bar-item{ flex: 1; text-align: center; height: 49px; } </style>

但是此时发现tabbar的组件内容非常复杂,如果有其他内容,就显非常凌乱,此时就需要将每一小个的tab-bar-item组装成一个组件,tabbar的相应位置放入插槽。

  1. 分离tabbar和tab-bar-item ,创建一个TabbarItem.vue文件夹
//tabbar.vue
<template>
  <div id="tab-bar">
    <slot></slot>   //放入插槽
  </div>
</template>

<script> export default { name: "TabBar", }; </script>

<style> #tab-bar { display: flex; background-color: #f6f6f6; position: fixed; left: 0; right: 0; bottom: 0; box-shadow: 0 -10px 1px rgba(100, 100, 100, 0.05); } </style>
//TabbarItem.vue
<template>
  <div class="tab-bar-item">
     <slot name="item-icon"></slot>
     <slot name="item-text"></slot>
  </div>
</template>

<script> export default { name: "TabBarItem" }; </script>

<style> .tab-bar-item { flex: 1; text-align: center; height: 49px; font-size: 14px; } .tab-bar-item img { width: 24px; height: 24px; margin-top: 3px; vertical-align: middle; margin-bottom: 2px; } </style>

要在App.vue进行注册,并使用

//App.vue
<template>
  <div id="app">
    <tab-bar>
      <tab-bar-item>
        <img slot="item-icon" src="./assets/img/tabbar/home.svg">
        <div slot="item-text">首页</div>
      </tab-bar-item>
      <tab-bar-item>
        <img slot="item-icon" src="./assets/img/tabbar/category.svg">
        <div slot="item-text">分类</div>
      </tab-bar-item>
      <tab-bar-item>
        <img slot="item-icon" src="./assets/img/tabbar/shopcart.svg">
        <div slot="item-text">购物车</div>
      </tab-bar-item>
      <tab-bar-item>
        <img slot="item-icon" src="./assets/img/tabbar/profile.svg">
        <div slot="item-text">我的</div>
      </tab-bar-item>
    </tab-bar>
  </div>
</template>

<script> import TabBar from './components/tabbar/TabBar.vue' import TabBarItem from './components/tabbar/TabBarItem.vue' export default { name:'App', components:{ TabBar, TabBarItem, } } </script>
<style> @import url('./assets/css/base.css'); </style>

相关文章