Vue.js知识
路由
全局导航守卫
导航:“导航”表示路由正在发生改变。
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里面,所有路径匹配到的视图组件都会被缓存。
例子:
希望用户原先在浏览消息页面,然后跳转到其他页面再回来首页时,页面依然停留在消息页面。
- 首先需要将需要缓存的内容视图包含在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>
- 在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组件进行封装
- 首先在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>
- 其次要在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>
此时在页面的底部就出现了导航栏:
-
完成上述内容之后发现没有图标,可以到阿里巴巴矢量图标库下载svg图标, 将下载好的svg文件放在src/assets/img/tabbar下,注意:一个页面下载两个图标,分别为选中与未选中状态
-
导入图片文件
//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的相应位置放入插槽。
- 分离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>