路由
- 实现单页面应用,只有一个页面,页面更新不跳转页面,而是局部刷新(切换)
- 使用a标签,多页面应用,页面跳转会刷新
安装
安装vue路由,是一个必须依赖
npm install vue-router --save
把下面代码复制进去main.js
里面,并且一定要用Vue.use
来明确安装
main.js
// 引入路由模块
import VueRouter from 'vue-router'
// 显式安装该模块
Vue.use(VueRouter)
初阶路由案例
项目结构图,使用vue create vue-project
命令生成vue脚手架
components
存一个页面中的各个部分组件,pages
存导入components
中组件组成页面的组件,定义的路由配好对应pages
组件路径实现跳转,通过App.vue
的<router-view></router-view>
标签导入路由对应组件内容
定义路由组件
在src
文件内创建一个pages文件夹,放路由组件=>页面组件
Katsuki.Vue
<template>
<div>
<Xheader />
<Xsearch />
<Xpanel />
</div>
</template>
<script>
// 引用组件
import Xheader from '../components/Xheader.vue'
import Xsearch from '../components/Xsearch.vue'
import Xpanel from '../components/Xpanel.vue'
export default {
components: {
Xheader,
Xsearch,
Xpanel
}
}
</script>
Kasami.vue
<template>
<div>
<Xheader />
</div>
</template>
<script>
// 引用组件
import Xheader from '../components/Xheader.vue'
export default {
components: {
Xheader
}
}
</script>
定义路由&实例路由&注入router
main.js
import Vue from 'vue'
import App from './App.vue'
//微信样式
import 'weui'
//全局样式
import './styles/app.css'
// 引入路由模块
import VueRouter from 'vue-router'
// 显示安装该模块
Vue.use(VueRouter)
// 定义路由
// Katsuki路由
import Katsuki from './pages/Katsuki.vue'
// Kasami路由
import Kasami from './pages/Kasami.vue'
// 配置路由
const routes = [
// 重定向路由,比如刚进页面的时候,默认跳转的路由位置
{
path: '/',
redirect: '/katsuki'
},
// 设置路由
{ path: '/katsuki', component: Katsuki },
{ path: '/kasami', component: Kasami }
]
//实例路由配置
const router = new VueRouter({
routes
})
// 注入上面定义的router
// Root容器
new Vue({
render: h => h(App),
// 挂载路由
router,
}).$mount('#app')
放置router-view
router-view根据上面路由配置的规则,让组件出现
App.vue
<template>
<div id="app">
<router-view></router-view>
<Xfooter />
</div>
</template>
<script>
import Xfooter from './components/Xfooter.vue'
export default {
name: 'app',
components: {
Xfooter
}
}
</script>
<style>
</style>
实现点击底部按键切换路由
Xfooter样式图,使用weui样式的底部栏
使用<router-link to="/路由"></router-link>
替代a标签切换
Xfooter.vue
<template>
<div class="weui-tabbar">
<router-link to="/katsuki" href="javascript:;" class="weui-tabbar__item weui-bar__item_on">
<span style="display: inline-block;position: relative;">
<img :src="iconTabbar" alt class="weui-tabbar__icon">
<span class="weui-badge" style="position: absolute;top: -2px;right: -13px;">18</span>
</span>
<p class="weui-tabbar__label">Katsuki</p>
</router-link>
<router-link to="/kasami" href="javascript:;" class="weui-tabbar__item">
<img :src="iconTabbar" alt class="weui-tabbar__icon">
<p class="weui-tabbar__label">Kasami</p>
</router-link>
<a href="javascript:;" class="weui-tabbar__item">
<span style="display: inline-block;position: relative;">
<img :src="iconTabbar" alt class="weui-tabbar__icon">
<span class="weui-badge weui-badge_dot" style="position: absolute;top: 0;right: -6px;"></span>
</span>
<p class="weui-tabbar__label">发现</p>
</a>
<a href="javascript:;" class="weui-tabbar__item">
<img :src="iconTabbar" alt class="weui-tabbar__icon">
<p class="weui-tabbar__label">我</p>
</a>
</div>
</template>
<script>
import iconTabbar from "../assets/icon_tabbar.png";
export default {
data() {
return {
iconTabbar
};
}
</script>
<style scoped>
.weui-tabbar {
position: fixed;
bottom: 0;
left: 0;
}
</style>
项目运行,url出现的/#/
及其之后到?
前的部分就是路由
路由切换点击时,因切换而删除的组件会触发生命周期中的销毁方法destoryed()
。总之router-view就等同于一个舞台,进场就会执行组件生命周期的编译、挂载,数据更改触发更新,离场就触发销毁
嵌套路由
附带的知识点:命名路由、路由重定向、H5 History模式、编程式导航、导航全局守卫(最有用)
在上面的案例的基础上进行修改
pages页面组件中添加Detail.vue
文件,为一层路由组件
main.js
import Vue from 'vue'
//微信样式
import 'weui'
//全局样式
import './styles/app.css'
// 引入路由模块
import VueRouter from 'vue-router'
// 显式安装该模块
Vue.use(VueRouter)
//一层路由
//首页路由
import App from './App.vue'
//详情页路由
import Detail from './pages/Detail.vue'
//二层路由
// Katsuki路由
import Katsuki from './pages/Katsuki.vue'
// Kasami路由
import Kasami from './pages/Kasami.vue'
// 配置路由
const routes = [
{
path: '/app',
// 路由命名,方便跳转
name: 'app',
component: App,
children: [
// 嵌套路由里层的path要删掉 /
{
path: 'katsuki',
name: 'katsuki',
component: Katsuki,
// 路由传参,把一些参数固定的值写在这
// 就可以this.meta.age拿到
meta: {
age: '18'
}
},
{
path: 'kasami',
// 下面的编程式导航使用这个命名为例
name: 'kasami',
component: Kasami
meta: {
age: '17'
}
}
]
},
// 就是可以在:id里接受一个不固定的值
// 可以放多个如 path: '/detail/:id/:name'
// 下面的 Xpanel.vue 对应使用
{
path: '/detail/:id',
name: 'detail',
component: Detail
},
// 重定向路由,刚进页面的时候,默认跳转的路由位置
// 与之前的不同,使用命名路由方式
{
path: '/',
redirect: {
name: 'katsuki'
}
}
]
// 实例该路由配置
const router = new VueRouter({
// h5history路由模式,作用就是url地址的 # 去除,工作中不是特殊情况基本用不上
// 有兼容性的问题,去除 # 服务器就会认为这是文件夹路径,不是路由
// mode: 'history',
// 建议用默认的哈希模式,不写就是该模式
mode: 'hash',
routes
})
// Root容器
new Vue({
// 原挂载App修改为router-view
render: h => h('router-view'),
// 挂载路由
router,
}).$mount('#app')
Xpanel.vue
设置router-link"
让/app
路由跳转到/detail
路由
Xpanel.vue 假设该组件拿到数据进行v-for生成
<template>
<router-link :to="`/detail/${index}`"
v-for="(d,index) in datas"
:key="index"
href="javascript:void(0);"
>
<!-- 相关内容渲染 -->
</router-link>
</template>
<script>
export default {
data() {
return {
datas: [假装有数据]
};
}
};
</script>
Detail.vue
:/detail
路由页面组件,所有路由的信息都可以在组件的$route
拿到
Detail.vue
<template>
<p>
<!-- 直接引入方式,打包时会压缩进webpack,一般用这种方式压缩精灵图 -->
<img :src="picKatsuki" alt>
<!-- 单张图片用https://xxx/katsuki.jpg方式请求 -->
<img src="https://xxx/katsuki.jpg" alt>
</p>
</template>
<script>
import picKatsuki from "pic_katsuki";
export default {
data() {
return {
picKatsuki
};
},
created() {
// 进入路由时触发
// 获取url上的参数
console.log(this.$route);
// 编程式导航
console.log(this.$router);
}
};
</script>
Xfooter.vue
的router-link
的路由导向进行修改
<router-link to="/app/katsuki"></router-link>
编程式导航,就是用函数方式跳转
<a @click="toKasami"></a>
<script>
export default {
methods: {
toKasami() {
// 未使用路由命名的跳转
this.$router.push('/app/kasami');
// 根据命名路由来进行跳转
this.$router.push({ name: "kasami" });
}
}
};
</script>
在上面的基础上进一步模块化,创建router.js
专门处理路由,在main.js
中导入
pages中创建Sign.vue
登录页面组件,用于路由守卫
router.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
//一层路由
import App from '../App.vue'
import Detail from '../pages/Detail.vue'
// 登录路由
import Sign from '../pages/Sign.vue'
//二层路由
import Katsuki from '../pages/Katsuki.vue'
import Kasami from '../pages/Kasami.vue'
// 配置路由
const routes = [
{
path: '/app',
name: 'app',
component: App,
children: [
{
path: 'katsuki',
name: 'katsuki',
component: Katsuki
},
{
path: 'kasami',
name: 'kasami',
component: Kasami
}
]
},
{
path: '/detail/:id',
name: 'detail',
component: Detail
},
{
// 登录路由配置
path: '/sign',
name: 'sign',
component: Sign
},
{
path: '/',
redirect: {
name: 'katsuki'
}
}
]
// 实例路由
const router = new VueRouter({
mode: 'hash',
routes
})
// 路由守卫
// to:将前往的页面路由 from:从哪个页面来的路由 next:下一步操作
router.beforeEach((to, from, next) => {
let token = localStorage.getItem("token");
// 这里用伪token方式验证,在浏览器控制台的localStorage进行设置token值
// 如果token是123的话进去目标页面,否则返回'/sign'页面
if (token == 123 || to.path == '/sign') {
next()
} else {
// 如果失败跳转登录页面
router.push({
name: "sign"
})
}
// 用定时器测试守卫是否执行
// setTimeout(()=>{
// next()
// },3000)
})
export default router
main.js
import Vue from 'vue'
// 引入路由模块
import router from './configs/router.js'
//微信样式
import 'weui'
//全局样式
import './styles/app.css'
// Root容器
new Vue({
//挂载修改为router-view
render: h => h('router-view'),
// 挂载路由
router,
}).$mount('#app')