Vue_Router
Vue Router 和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。根据用户请求的路径不同的页面,并返回不同的数据
一、路由的分离
- 前端路由
根据用户请求不同的url来展示不同的页面或者数据,前端路由不会涉及到后端请求,页面不会刷新。用户体验较好,一般用来做单页面开发(SPA)。
前端路由的底层原理:hashchange和H5中history API中的popState和replaceState来进行实现的。
- 后端路由
根据用户请求的路径来返回不同的数据或者页面,后端路由一般情况下都是用来做接口的,通过ajax请求的路径来返回相对应的数据。
二、Vue中路由的常用配置项
- mode
配置路由的模式,可选择:"hash"(默认) | "history" | "abstract"
- routes数组
数组中有N多个对象,每个对象都是一个路由的配置项
path : 匹配路由的路径
component : 路由路径匹配成功以后会显示相应的组件
redirect : 路由重定向
children:路由嵌套
meta : 路由元信息(路由携带的一些独有信息)
- Vue路由的内置组件
当VueRouter挂载到vm实例上时,会多出两个内置组件:
- router-view : 渲染路由匹配的组件,可结合其他组件使用:
<transition> <keep-alive> <router-view></router-view> </keep-alive> </transition>
router-link : 路由的跳转导航,底层原理用a标签实现的,属性内置组件。具有如下属性:
to属性指向目标地址,tag指定渲染之后的标签
注:一般情况下,当router-view写在根组件中时,这些页面都是一级路由。
三、Vue中使用插件的流程
- 安装
cnpm install vue-router -S
-
创建router文件夹并创建index.js文件
-
引入Vue和vue-router进行配置使用
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
let router = new VueRouter({
})
export default router
- 在入口文件main.js中引入,并挂载到vue上
import Vue from "vue";
import App from "./App.vue";
import router from "./router"
new Vue({
router,
render:h=>h(App)
}).$mount("#app")
四、路由跳转的方式有哪些?
- hash路由调整
<a></a>
- router-link
- 编程式导航(JS)
五、路由传值
不同的页面之间需要相互传递数据进行数据的请求或数据的渲染,因此需要路由传值。
- 动态路由传值
在定义路由的时候,在path路径处通过
/:
属性的方式来定义传递参数的属性。eg :
path:"/detail/:goodsName/:goodsPrice"
在路径跳转的地方通过
/值
传值eg :
<router-link :to="'/detail/'+item.name+'/'+item.price">{{item.name}}</router-link>
在接收参数的页面,通过
this.$route.params
的方式接收created(){ var { goodsName, goodsPrice } = this.$route.params; this.goodsName = goodsName; this.goodsPrice = goodsPrice; }
- query传值
通过url地址进行拼接,将数据传递给另一个路由
在路由跳转的时候,通过路径
?key=value&key=value
的方式将数据进行传值<router-link :to="'/detail?goodsName='+item.name+'&goodsPrice='+item.price">{{item.name}}</router-link> //或 <router-link :to="{name:'detail',query:{goodsName:item.name,goodsPrice:item.price}}">{{item.name}}</router-link>
在需要接收参数的页面,通过
this.$route.query
的方式进行接收created(){ var { goodsName, goodsPrice } = this.$route.query; this.goodsName = goodsName; this.goodsPrice = goodsPrice; }
- 动态路由和query传值之间的区别
动态路由传值,值是必须传递的 ; 而query传值,值是非必须的
动态路由在url中只会显示属性值(
eg:detail/lxc/18
),而query则会显示属性值和属性名(eg:detail?userName=lxc&age=18
)
- 路由解耦(只使用于动态路由)
在定义路由的时候,添加一个props属性为true,在path路径处通过
/:
属性的方式来定义传递参数的属性。{ path:"/detail/:goodsName/:goodsPrice", component:Detail, name:"detail", props:true }
在路径跳转的地方通过
/值
传值<router-link :to="{name:'detail',params:{goodsName:item.name,goodsPrice:item.price}}">{{item.name}}</router-link>
在接收参数的页面,通过
this.$route.params
的方式进行接收在需要接收参数的页面,通过props来进行接收
eg :
props: ["goodsName", "goodsPrice"]
- 编程式导航传值
通过JS的方式进行路由的跳转
this.$router.push()
eg : this.$router.push("/detail/"+name+'/'+price)
this.$router.go(n)
this.$router.back()
this.$router.forward()
this.$router.replace()
这里的前进后退方法要依赖于浏览器的浏览历史记录
- 嵌套路由(二级路由)
需要在base.config.js中配置文件别名:
resolve: {
extensions: [".vue", ".js"],
//别名的配置
alias: {
"@": path.join(__dirname, "../src"),
"@views": path.join(__dirname, "../src/views"),
"@assets": path.join(__dirname, "../src/assets"),
"@common": path.join(__dirname, "../src/common"),
"@components": path.join(__dirname, "../src/components"),
"@pages": path.join(__dirname, "../src/pages"),
"@router": path.join(__dirname, "../src/router"),
"@store": path.join(__dirname, "../src/store"),
"@utils": path.join(__dirname, "../src/utils"),
"@api": path.join(__dirname, "../src/api"),
}
},
- 配置二级路由
export default {
path: "/movie",
component: () => import('@views/movie'),
name: "movie",
meta: {
flag: true
},
children: [
{
path: "/movie",
redirect: "/movie/nowPlaying"
},
{
path: 'nowPlaying',
component:(resolve)=>require(["@/components/nowPlaying"], resolve),
name: "nowPlaying",
meta: {
flag: true
},
},
{
path: 'comingSoon',
component: () => import('@components/comingSoon'),
name: "coming",
meta: {
flag: true
}
},
]
}
- 异步组件
Vue 允许你以一个工厂函数的方式定义你的组件,这个工厂函数会异步解析你的组件定义。
上面的例子中用到了require和import(推荐)两种方式。
六、路由的生命周期
路由守卫,路由跳转前后的一些验证
- 全局的路由生命周期
-
beforeEach
注意:局部的路由守卫是在组件内部进行使用的,而全局的路由守卫是在路由的配置项中去使用的。
eg : 在路由配置需要验证的页面,meta属性中添加配置:requiredAuth:true
router.beforeEach((to,from,next)=>{ document.title = to.meta.title; if(to.meta.requiredAuth){ var token = localStorage.getItem("token"); if(token){ next(); }else{ next({name:"login",params:{toPath:to.path}}) } }else{ next(); } })
-
局部的路由生命周期
- beforeRouteEnter进入时(在beforeCreate创建之前)
参数:
- to : 即将要进入的目标(路由要到哪里去)
- from : 当前导航正要离开的路由(路由从哪里来)
- next : 必须要调用,进行管道中的下一个钩子。否则路由对应的组件不会渲染。
beforeRouteEnter(to,from,next){ console.log("路由进入",to,from,next); next(); }
使用场景:
-
验证用户是否登录
beforeRouteEnter(to,from,next){ if(to.meta.requiredAuth){ var token = localStorage.getItem("token"); if(token){ next(); }else{ //跳转到登录页面 next((vm)=>{ this.router.push("/login"); }) } }else{ next(); } }
-
验证用户的VIP是否到期/剩余时间
-
用户权限
-
消息提示
- beforeRouteUpdate更新时
当路由更新的时候会触发的守卫,一般情况下,在组件没有经历创建和销毁,但是路由发生改变时之后
beforeRouteUpdate(to,from,next){ var {name} = to.params; this.goodsName = name; next(); }
- 通过watch的方式监听
watch:{ "$route":{ handle(){ var {name} = to.params; this.goodsName = name; } } }
- beforeRouteLeave离开时
使用场景:
- 用户未支付
- 答题系统
- 记录历史记录
- 注销、切换账号
beforeRouterLeave(to,from,next){ var flag = confirm("确定要离开当前页面吗?"); if(flag){ next(); } }
网友评论