Vue-Router
原理
vue-router
的原理就是通过对URL
地址变化的监听,继而对不同的组件进行渲染
HTML5 History 模式
vue-router
默认 hash
模式 —— 使用 URL
的 hash
来模拟一个完整的 URL
,于是当 URL
改变时,页面不会重新加载。
history
模式需要后台配置支持(配置Nginx
)。如果后台没有正确的配置,当用户在浏览器直接访问url
就会返回 404
hash
- 原理是
onhashchage
事件,可以在window
对象上监听这个事件
window.onhashchange = function (event) { console.log(event.oldURL, event.newURL) let hash = location.hash.slice(1) }
- 原理是
history
location / {
try_files $uri $uri/ @router index index.html;
}
location @router {
rewrite ^.*$ /index.html last;
}
$route和$router的区别
$route
是路由信息对象,包括path
,params
,hash
,query
,fullPath
,matched
,name
等路由信息参数。$router
是路由实例对象,包括了路由的跳转方法,钩子函数等
路由懒加载
const Foo = () => import('./Foo.vue')
const router = new VueRouter({
routes: [
{ path: '/foo', component: Foo }
]
})
把组件按组分块
const Foo = () => import(/* webpackChunkName: "foo" */ './Foo.vue') //foo[hash].js
const Bar = () => import(/* webpackChunkName: "bar" */ './Bar.vue') //bar[hasg].js
Vue-Router钩子函数
首页可以控制导航跳转,
beforeEach
,afterEach
等,一般用于页面title
的修改。一些需要登录才能调整页面的重定向功能。
beforeEach
主要有3个参数to
,from
,next
。to
:route
即将进入的目标路由对象。from
:route
当前导航正要离开的路由。next
:function
一定要调用该方法resolve
这个钩子。执行效果依赖next
方法的调用参数。可以控制网页的跳转
路由跳转
<router-link :to="...">
- 编程式:
router.push(...)
该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
注意:如果提供了 path
,params
会被忽略,上述例子中的 query
并不属于这种情况。取而代之的是下面例子的做法,你需要提供路由的 name
或手写完整的带有参数的 path:
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
params和query的区别
query
要用path
来引入,params
要用name
来引入,接收参数都是类似的,分别是this.$route.query.name
和this.$route.params.name
url
地址显示:query
更加类似于我们ajax
中get
传参,params
则类似于post
,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示
注意点:query
刷新不会丢失query
里面的数据,params
刷新会丢失params
里面的数据。
怎么重定向页面
const router = new VueRouter({
routes: [
{ path: '/a', redirect: '/b' },
{ path: '/a', redirect: { name: 'b' }},
{
path: '/a',
redirect: to =>{
const { hash, params, query } = to
if (query.to === 'foo') {
return { path: '/foo', query: null }
}else{
return '/b'
}
}
}
]
})
怎么配置404页面
const router = new VueRouter({
routes: [
{
path: '*', redirect: {path: '/'}
}
]
})
切换路由时,需要保存草稿的功能,怎么实现呢
<keep-alive :include="include">
<router-view></router-view>
</keep-alive>
其中
include
可以是个数组,数组内容为**路由的name
**选项的值
路由导航守卫和Vue实例生命周期钩子函数的执行顺序
路由导航守卫都是在Vue实例生命周期钩子函数之前执行的
在afterEach钩子中可以使用next()吗
不可以,不接受next
的参数
在beforeRouteEnter导航守卫中可以用this吗
不可以,因为守卫在导航确认前被调用,因此即将登场的新组件还没被创建
可以通过传一个回调给next
来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数
beforeRouteEnter(to, from, next) {
next(vm => {
console.log(vm)
})
}
怎么在组件中监听路由参数的变化
有两种方法可以监听路由参数的变化,但是只能用在包含<router-view />
的组件内
watch: {
'$route'(to, from) {
//这里监听
},
},
beforeRouteUpdate (to, from, next) {
//这里监听
},
切换路由后,新页面要滚动到顶部或保持原先的滚动位置怎么做呢
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else {
return { x: 0, y: 0 };
}
}
});
Vue路由怎么跳转打开新窗口
const obj = {
path: xxx,//路由地址
query: {
mid: data.id//可以带参数
}
};
const {href} = this.$router.resolve(obj);
window.open(href, '_blank');