vue路由的使用
本文目录
route和router区别
route 是用来获取路由信息的,router是用来操作路由的。
router是vueRouter的一个全局实例对象,包含所有的路由
route是当前激活的路由对象(局部的对象),包含当前url解析得到的数据,可以获取对应的name,path,params,query
this.$router.currentRoute = this.$route
路由跳转
router目录index.js
export default new Router({
// 默认使用hash模式的路由,地址栏中URL带有 # 形式
// mode: 'history',
routes: [
{
path: '/Home',
name: 'Home',
component: Home
},
{
path: '/About',
name: 'About',
component: About
},
{
path: '/News',
name: 'News',
component: News
}
]
})
声明式
想在一个页面嵌套子路由,并且不跳转页面的时候,子页面就会渲染在router-view中
-
无参模式
//路由入口 <router-link to="/About">About</router-link> //视图出口 <router-view></router-view>
-
传参模式
<router-link to="/About?name=xxx">About</router-link>
<router-link to="/About?id=666&title=你好">About3</router-link> <router-link :to="{ path: '/About', query: { id: 666, title: '你好' } }">About4</router-link> <router-link :to="`/About/${n.aid}`">{{ n.name }} 1</router-link> <router-link :to="{ name: 'About', params: { id: n.aid, name: n.name, }, }"> {{ n.name }} 2 </router-link>
query
和?name=xxx
增加显式参数,浏览器地址栏信息会附带参数信息params
增加隐式参数- 要使用
/${n.aid}
必须在index.js
中增加对应的路由规则。{ path: '/About/:aid', name: 'About', component: About },
编程式
-
get第一种,浏览器地址栏信息会附带
?name=xxx
// About <button @click="get1">get1</button> get1(){ this.$router.push("/News?name=xcv"); } // News console.log(this.$route.query); {name: 'xcv'}
-
get第二种,浏览器地址栏信息会附带
?name=xxx
// About <button @click="get2">get2</button> get2(){ this.$router.push({ path: '/News', query: {name: 'xcv'} }); }, // News console.log(this.$route.query); {name: 'xcv'}
-
post
// About post(){ this.$router.push({ name: 'News', params: {name: 'xcv'} }); } // News console.log(this.$route.params); {name: 'xcv'}
post传参刷新会导致数据丢失
使用this.$route.params接收参数
URL地址栏传参隐藏
路由重定向
index.js
,使用redirect,用户在访问地址 A 的时候,强制用户跳转到地址 C
routes: [
{
path: '/',
redirect: '/Home',
},
...
404路由
routes: [
...
{
path: '*',
component: NotFound
}
]
嵌套路由
index.js
,children下的path不带/
export default new Router({
routes: [
...
{
path: '/News',
name: 'News',
component: News,
children: [
{
path: 'Top',
name: 'Top',
component: Top,
},
{
path: 'Bottom',
name: 'Bottom',
component: Bottom,
}
]
},
...
]
})
News.vue
- to 写全路径
- :to 使用"{name: ‘Top’}"
- path 写全路径
- name 使用name属性
<button @click="getChild1">getChild1</button>
<button @click="getChild2">getChild2</button>
// 方式1
<router-link to="/News/Top">to-top</router-link>
// 方式2
<router-link :to="{name: 'Top'}">to-top2</router-link>
// 方式3
getChild1(){
this.$router.push({
path: '/News/Top'
});
},
// 方式4
getChild2(){
this.$router.push({
name: 'Bottom',
});
}
动态路由
路由规则中有部分规则是动态变化的,有路由参数
index.js
export default new Router({
routes: [
...
{
path: '/About/:aid?',
name: 'About',
component: About
},
...
]
})
加?
表示可传可不传,不加?
则必须传
Home.vue
<router-link to="/About/123">About2</router-link>
// About.vue
params: {aid: '123'}
path: "/About/123"
同时加载多个子路由
index.js
,children中使用components
export default new Router({
...
routes: [
{
path: '/News',
name: 'News',
component: News,
children: [
{
path: '',
components: {
'Top': Top,
'Bottom': Bottom
}
},
]
},
...
]
})
News.vue中,router-view
使用name属性
// 默认显示的路由
<router-view name="Top"></router-view>
<router-view name="Bottom"></router-view>
push和replace
-
this.$router.push
跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面 -
this.$router.replace
跳转到指定的url,但是这个方法不会向history里面添加新的记录,点击返回,会跳转到上上一个页面,(A----->B----->C 结果B被C替换 A----->C)<reouter-link :to="..." replace></router-link> this.$router.replace({path: '/homo'}) this.$router.push({path: '/homo', replace: true})
forward,back和go
-
this.$router.forward()
路由前进 -
this.$router.back()
路由后退 -
this.$router.go(n)
当前页面向前或向后跳转多少个页面,n可为正数可为负数
hash模式和history模式
前端路由的核心,在于 —— 改变视图的同时不会向后端发出请求,hash 模式和 history 模式都属于浏览器自身的特性
默认是hash模式,浏览器localhost:8080/#/Home
history模式,浏览器localhost:8080/Home
export default new Router({
// 默认使用hash模式的路由,地址栏中URL带有 # 形式
// mode: 'history',
routes: [
...
]
})
hash
路由的哈希模式利用了window.onhashchange
事件,也就是哈希值(#后面的值)如果有变化,浏览器并不会重新发起请求,而是会触发 onhashchange 事件
//http://127.0.0.1:8001/01-hash.html?a=100&b=20#/aaa/bbb
location.protocal // 'http:'
localtion.hostname // '127.0.0.1'
location.host // '127.0.0.1:8001'
location.port //8001
location.pathname //'01-hash.html'
location.serach // '?a=100&b=20'
location.hash // '#/aaa/bbb'
- hash变化会触发网页跳转,即浏览器的前进和后退。
- hash 可以改变 url ,但是不会触发页面重新加载(hash的改变是记录在 window.history 中),即不会刷新页面。即所有页面的跳转都是在客户端进行操作。因此,这并不算是一次 http 请求,所以这种模式不利于 SEO 优化。hash 只能修改 # 后面的部分,所以只能跳转到与当前 url 同文档的 url 。
- hash 通过 window.onhashchange 的方式,来监听 hash 的改变,借此实现无刷新跳转的功能。
- hash 永远不会提交到 server 端(可以理解为只在前端自生自灭)。
history
history API 是 H5 提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL 地址而不重新发起请求。
history.pushState:往历史记录堆栈顶部添加一条记录
history.replaceState:更改当前的历史记录
- 新的 url 可以是与当前 url 同源的任意 url ,也可以是与当前 url 一样的地址,但是这样会导致的一个问题是,会把重复的这一次操作记录到栈当中。
- 通过 history.state ,添加任意类型的数据到记录中。
- 可以额外设置 title 属性,以便后续使用。
- 通过 pushState 、 replaceState 来实现无刷新跳转的功能,虽然改变了当前的 URL,但浏览器不会向后端发送请求。
总结
-
对于 hash 模式来说, 它虽然看着是改变了 url ,但不会被包括在 http 请求中,改变 hash 并没有真正地改变 url ,所以页面路径还是之前的路径, nginx 也就不会拦截
-
在使用 history 模式时,需要通过服务端来允许地址可访问
-
to B 的系统推荐用 hash ,相对简单且容易使用,且因为 hash 对 url 规范不敏感
-
to C 的系统,可以考虑选择 H5 history ,但是需要服务端支持
-
hash模式下,仅hash符号之前的内容会被包含在请求中,如http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
-
history模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如http://www.abc.com/book/id如果后端缺少对/book/id的路由处理,将返回 404 错误,需要后台配置支持,要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html页面。
路由守卫
- router.beforeEach: 全局前置路由守卫,每次路由切换之前被调用,可以做权限拦截
- router.afterEach: 全局后置路由守卫,每次路由切换之后调用, 可用于切换document.title
- router.beforeEnter: 独享路由守卫,只有前置,没有后置,写在routes配置项里
- router.beforeRouteEnter: 组件内路由守卫, 写在组件中,路过路由规则进入该组件时被调用
- crouter.beforeRouteLeave: 组件内路由守卫, 写在组件中,路过路由规则离开该组件时被调用
全局守卫
const router = new Router({
...
routes: [
{
path: '/All',
name: 'All',
component: All,
meta:{
isAuth: true //需要鉴权
},
},
...
]
})
// 配置在实例对象外 初始化时调用,每次发生路由变化前调用
router.beforeEach((to,from,next)=>{
console.log('beforeEach',to,from)
if(to.meta.isAuth){ //判断当前路由是否需要进行权限控制
if(localStorage.getItem('user') === 'ghn'){ //权限控制的具体规则
next() //放行
}else{
alert('暂无权限查看')
// next({name:'guanyu'})
}
}else{
next() //放行
}
})
//全局后置守卫:初始化时执行、每次路由切换后执行
router.afterEach((to,from)=>{
console.log('afterEach',to,from)
if(to.meta.title){
document.title = to.meta.title //修改网页的title
}else{
document.title = 'vue_test'
}
})
export default router
独享守卫
配置路由的时候给路由加入
const router = new Router({
...
routes: [
{
path: '/All',
name: 'All',
component: All,
//独享守卫
beforeEnter:(to,form,next)=>{
if (to.meta.isAuth) {//判断当前路由是否需要权限控制
if(localStorage.getItem('user') === 'ghn'){//权限控制的具体规则
next()//旅行
}else{
alert('暂无权限查看')
}
} else {
next();
}
},
meta:{
isAuth: true //需要鉴权
},
},
...
]
})
组件内守卫
export default {
name: "All",
data() {
return {}
},
components: {},
methods: {},
// 组件内守卫
// 进入守卫,通过路由规则,进入该组件时被调用
beforeRouteEnter(to, from, next) {
// ...
console.log("enter");
next();
},
// 离开守卫,通过路由规则,离开该组件时被调用
beforeRouteLeave(to, from, next) {
// ...
console.log("leave");
next();
},
mounted() {
console.log(this.$route);
},
computed: {},
created() {
},
destroyed() {
},
}
</script>