十五、Vue-Router
1、认识路由
路由:通过互联网的网络把信息从源地址传输到目的地址的活动
官网:https://router.vuejs.org/zh/
1.1、URL 的 hash
1.2、HTML5 的 history 模式:pushState
1.3、HTML5 的 history 模式:replaceState
1.4、HTML5 的 history 模式:go
2、vue-router 基本使用
- vue-router 是Vue.js 官方的路由插件,它和vue.js是深度集成的,适合用于构建单页面应用
- 官方网站为:https://router.vuejs.org/zh/
- vue-router 是基于路由和组件的,路由用于设定访问路径,将路径和组件映射起来
- 在 vue-router 的单页面应用中,页面的路径的改变就是组件的切换
2.1、安装和使用 vue-router
- 安装 vue-router:
npm install vue-router --save
- 在模块化工程中使用它(因为是一个插件,所以可以通过Vue.use()来安装路由功能)
- 第一步:导入路由对象,并且调用 Vue.use(VueRouter)
- 第二步:创建路由实例,并且传入路由映射配置
- 第三步:在Vue实例汇总挂载创建的路由实例
使用 vue-router 的步骤:
第一步:创建路由组件
learnvuerouter/src/components/Home.vue
<template> <div> <h2>我是关于</h2> <p>我是首页内容,哈哈哈</p> </div> </template> <script> export default { name: "home" } </script> <style scoped> </style>
第二步:配置路由映射,
learnvuerouter/src/router/index.js
import Vue from 'vue' import Router from 'vue-router' // import HelloWorld from '@/components/HelloWorld' import Home from '../components/Home' import About from "../components/About"; // 1.通过 Vue.use(插件),安装插件 Vue.use(Router) // 2.创建VueRouter对象 const routes = [ { path: '/home', component: Home }, { path:'./about', component:About } ] export default router
第三步:使用路由:通过
<router-link>
和<router-view>
,learnvuerouter/src/router/index.js
<template> <div id="app"> <router-link to="/home">首页</router-link> <router-link to="/about">关于</router-link> <router-view></router-view> </div> </template> <script> export default { name: 'App' } </script> <style> </style>
2.1、路由的默认路径
2.3、router-link 属性
<router-link to="/home">首页</router-link>
:用于指定跳转的路径<router-link to="/about" tag="button">关于</router-link>
:指定<router-link>
之后渲染成什么组件,默认是 a标签,但此处更改为 button 标签<router-link to="/home" replace>首页</router-link>
:在指定 replace 的情况下,后退键返回不能返回到上一个页面中
3、vue-router 动态路由
3.1、路由的懒加载
- 当打包构建应用时,Javascript 包会变得非常大,影响页面加载
- 如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效
- 路由懒加载的主要作用就是将路由对应的组件打包成一个个的js代码块
- 只有在这个路由被访问到的时候,才加载对应的组件
- 未进行路由懒加载的效果
- 进行了路由懒加载之后的效果
3.2、懒加载的方式
const Home = ()=> import('../components/Home')
E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js 下修改使用懒加载方式
import Vue from 'vue'
import Router from 'vue-router'
// import HelloWorld from '@/components/HelloWorld'
/*
import Home from '../components/Home';
import About from "../components/About";
import User from "../components/User";
*/
// 路由懒加载方式导入路由
const Home = ()=> import('../components/Home')
const About = ()=> import('../components/About')
const User = ()=> import('../components/User')
// 1.通过 Vue.use(插件),安装插件
Vue.use(Router)
// 2.创建VueRouter对象
const routes = [
{
// 默认路径
path:'',
// redirect 重定向
redirect:'/home'
},
{
path: '/home',
component: Home
},
{
path:'/about',
component:About
},
{
path:'/user/:userId',
component: User
}
]
const router = new Router({
// 配置路由和组件之间的应用关系
routes,
mode:'history'
})
/*export default new Router({
routes: [
]
})*/
// 3.将 router 对象传入到Vue实例
export default router
4、vue-router 嵌套路由
4.1、实现嵌套路由的两个步骤
创建对应的子组件E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\HomeNews.vue
<template> <div> <ul> <li>新闻1</li> <li>新闻2</li> <li>新闻3</li> <li>新闻4</li> </ul> </div> </template> <script> export default { name: "HomeNews" } </script> <style scoped> </style>
在路由映射中配置对应的子路由,可以添加默认路径作为默认显示:E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js
// 路由懒加载方式导入路由 const Home = ()=> import('../components/Home') const HomeNews = ()=>import('../components/HomeNews') const HomeMessage = ()=>import('../components/HomeMessage') ... const routes = [ /*添加默认路径*/ { path: '', redirect: 'news' }, { // 默认路径 path:'', // redirect 重定向 redirect:'/home' }, { path: '/home', component: Home, // 配置子路由关系 children:[ { path:'news', component: HomeNews }, { path: 'message', component: HomeMessage } ] }, { path:'/about', component:About }, { path:'/user/:userId', component: User } ]
在组件内部使用
<router-view>
标签:E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\Home.vue<template> <div> <h2>我是首页</h2> <p>我是首页的内容,哈哈哈</p> <router-link to="/home/news">新闻</router-link> <router-link to="/home/message">消息</router-link> <router-view></router-view> </div> </template>
5、vue-router 参数传递
5.1、准备工作
创建新的组件 Profile.vue
配置路由映射
添加跳转的
<router-link>
5.2、传递参数的方式
方式一:params
- 配置路由格式:/router/:id
- 传递的方式:在 path 后面跟上对应的值
- 传递后形成的路径:/router/123,/router/abc
方式二:query
新建
E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\components\Profile.vue
<template> <div> <h2>我是Profile组件内容</h2> <h2>{ { $route.query}}</h2> <h2>{ { $route.query.name}}</h2> <h2>{ { $route.query.age}}</h2> <h2>{ { $route.query.height}}</h2> </div> </template> <script> export default { name: "Profile" } </script>
- 设置index.js
- 在`E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\App.vue`中添加组件并显示,传递后形成的路径:/router?id=123,/router?id=abc
<router-link :to="'/user/'+userId">用户</router-link>
<router-link :to="{path:'/profile',query:{name:'why',age:18,height:1.88}}">档案</router-link>
5.3、传递参数 —— JavaScript代码
<template>
<div id="app">
<router-link to="/home">首页</router-link>
<router-link to="/about">关于</router-link>
<!--
<router-link :to="'/user/'+userId">用户</router-link>
<!– <router-link to="/profile">档案</router-link>–>
<router-link :to="{path:'/profile',query:{name:'why',age:18,height:1.88}}">档案</router-link>
-->
<!-- 另外一种写法-->
<button @click="userClick">用户</button>
<button @click="profileClick">档案</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data(){
return{
userId:'lisi'
}
},
methods:{
userClick(){
this.$router.push('/user/' + this.userId)
},
profileClick(){
this.$router.push(
{
path:'/profile',
query:{
name:'kobe',
age:18,
height:1.88
}
}
)
}
}
}
</script>
6、vue-router 导航守卫
E:\html\WebStorm\project\project_Vuejs\LearnVuejs03\learnvuerouter\src\router\index.js
在该文件下
- 调用 beforeEach 函数
在 VueRouter对象中设置元数据作为导航的实现
// 2.创建VueRouter对象 const routes = [ { // 默认路径 path:'', // redirect 重定向 redirect:'/home' }, { path: '/home', component: Home, // 元数据 meta:{ title:'首页' }, // 配置子路由关系 children:[ /*添加默认路径*/ { path: '', redirect: 'news' }, { path:'news', component: HomeNews }, { path: 'message', component: HomeMessage } ] }, { path:'/about', component:About, // 元数据 meta:{ title:'关于' }, }, { path:'/user/:userId', component: User, // 元数据 meta:{ title:'用户' }, }, { path:'/profile', component:Profile, // 元数据 meta:{ title:'档案' }, } ]
7、keep-alive
作用:所有路径匹配到的视图组件都会被缓存,即保存上次浏览记录,可以使被包含的组件保留状态,或 避免重新渲染
十六、TabBar
1、TarBar案例的实现
npm init webpack tabbar
,创建项目,目录结构如下- 在base.css中设置基础样式,即清除浏览器自带样式
TabBarItem.vue 设置插槽并设置样式并导出
<template> <div class="tab-bar-item"> <slot name="item-icon"></slot> <slot name="item-text"></slot> <!-- <img src="../../assets/img/tabbar/shouye.svg" alt=""> <div>首页</div>--> </div> </template> <script> export default { name: "TabBarItem" } </script> <style scoped> .tab-bar-item { flex: 1; text-align: center; height: 49px; font-size: 14px; } .tab-bar-item img{ width: 24px; height: 24px; margin-top: 3px; /*将图片的默认3px去掉*/ vertical-align: middle; } </style>
TabBar.vue 中设置插槽并导出
<template> <div id="tab-bar"> <!-- 设置插槽--> <slot></slot> </div> </template> <script> export default { name: "TabBar" } </script> <style scoped> #tab-bar { display: flex; background-color: #f6f6f6; position: fixed; left: 0; right: 0; bottom: 0; /*设置阴影:x方向,y方向,阴影宽度,阴影颜色*/ box-shadow: 0 -1px 1px rgba(100,100,100,.1); } </style>
App.vue 中导入、注册、使用组件
```bash
首页
分类
购物车
我的
<style>
/*导入基本样式*/
@import "./assets/css/base.css";
</style>
```
2、TarBar案例的实现思路
- 1、封装TarBar组件
- 自定义TarBar组件,在App中使用
- 让TarBar处于底部,并且设置相关的样式
2、TarBar中显示的内容由外界决定
- 定义插槽
- flex布局平分TarBar
3、自定义TabBarItem.vue,可以传入图片和文字
- 定义TarBarItem,并且定义两个插槽:图片、文字
- 给两个插槽外层包装 div,用于设置样式
填充插槽,实现底部TarBar的效果
<template> <!-- 所有的Item都展示同一个图片,同一个文字--> <div class="tab-bar-item" @click="itemClick"> <div v-if="!isActive"><slot name="item-icon"></slot> </div> <div v-else><slot name="item-icon-active"></slot> </div> <div :style="activeStyle"> <slot name="item-text"></slot> </div> </div> </template> <script> export default { name: "TabBarItem", props:{ path:String, activeColor:{ type:String, default:'red' } }, data(){ return { // isActive:true } }, /*搞一个计算属性*/ computed:{ isActive(){ /*拿到活跃路由的path与当前路径的path作为对比*/ /* * /home -> item1(/home) = true * /home -> item2(/category) = false * indexOf()方法:寻找,找到的话不为-1*/ return this.$route.path.indexOf(this.path) !== -1 }, activeStyle(){ return this.isActive ? { color:this.activeColor} :{ } } }, methods:{ itemClick(){ this.$router.replace(this.path);// 该方法允许返回 } } } </script> <style scoped> .tab-bar-item { /*使盒子都有相同的长度*/ flex: 1; text-align: center; height: 49px; font-size: 14px; } .tab-bar-item img{ width: 24px; height: 24px; margin-top: 3px; /*将图片的默认3px去掉*/ vertical-align: middle; } /* !*设置 active 下的状态*! .active{ color: red; }*/ </style>
4、App.vue 使用组件
<template> <div id="app"> <!-- 3、使用组件--> <tab-bar> <tab-bar-item path="/home" activeColor="deeppink"> <img slot="item-icon" src="./assets/img/tabbar/home.svg" alt=""> <img slot="item-icon-active" src="./assets/img/tabbar/home_active.svg" alt=""> <div slot="item-text">首页</div> </tab-bar-item> <tab-bar-item path="/category" activeColor="deeppink"> <img slot="item-icon" src="./assets/img/tabbar/category.svg" alt=""> <img slot="item-icon-active" src="./assets/img/tabbar/category_active.svg" alt=""> <div slot="item-text">分类</div> </tab-bar-item> <tab-bar-item path="/cart" activeColor="deeppink"> <img slot="item-icon" src="./assets/img/tabbar/cart.svg" alt=""> <img slot="item-icon-active" src="./assets/img/tabbar/cart_active.svg" alt=""> <div slot="item-text">购物车</div> </tab-bar-item> <tab-bar-item path="/profile" activeColor="deeppink"> <img slot="item-icon" src="./assets/img/tabbar/profile.svg" alt=""> <img slot="item-icon-active" src="./assets/img/tabbar/profile_active.svg" alt=""> <div slot="item-text">我的</div> </tab-bar-item> </tab-bar> <router-view></router-view> </div> </template> <script> /*1、导入组件*/ import TabBar from "./components/tabbar/TabBar"; import TabBarItem from "./components/tabbar/TabBarItem"; export default { name: 'App', components:{ /*2、注册组件*/ TabBar, TabBarItem } } </script> <style> /*导入基本样式*/ @import "./assets/css/base.css"; </style>
4、index.js 中设置相关属性
3、给 TabBarItem 传入 active 图片
- 在 TabBarItem 组件中设置插槽用于存放图片以及文字,并设置active下的style属性为
color:red
- 在App.vue中设置两种状态下的的图片显示
文件路径的引用问题——取别名
情况二:HTML中的图片路径需要加~