Vue Router 实现原理
Vue Router使用步骤
基础路由
接下来我会通过代码的形式为大家展现路由的基本用法
- 创建router对象,router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 路由组件
import index from '@/views/index'
// 组成插件
Vue.use(VueRouter)
// 路由规则
const routes = [
{
name: 'index',
path: '/',
component: index
}
]
// 路由对象
const router = new VueRouter({
routes
})
export default router
- 注册注册router对象,在main.js文件内操作
import router from './router'
new Vue({
render: h => h(App),
router
}).$mount('#app')
- 创建路由占位, 在需要用到路由的文件中,例如App.vue文件
<router-view></router-view>
- 最后一步创建链接
<router-link to="./">首页</router-link>
<router-link :to="{name: 'index'}">首页</router-link>
动态路由
<template>
<div>
// 方式一: 通过路由规则获取的数据
通过当前路由规则匹配获取: {
{
$route.params.id}}
// 方式二: 不仅可以通过路由,还有通过父组件传递(推荐)
通过开启 props 获取: {
{
id}}
</div>
</template>
<script>
export default {
name: 'Detail',
props: ['id']
}
</script>
const routes = [
{
name: 'Detail',
path: '/detail/:id', // :id是占位符,传入对应的id,
// 开启props会把url中的参数传递给组件,在组件内通过props来接收url参数
props: true,
// 路由懒加载,当需要访问该路由时加载组件
// webpackChunkName 这个参数在我 前端模块打包工具Webpack中有介绍(魔法注释,自定义打包名)
component: () => import(/* webpackChunkName: "detail" */ '../views/Detail.vue')
}
]
嵌套路由
const routes = [
{
name: 'Login',
path: '/login',
component: () => import('@/views/Login.vue')
},
// 嵌套路由
{
path: '/',
component: () => import('@/components/Layout.vue'), // 公共组件
children: [
{
name: 'index',
path: '', // 如果为空则访问父路径('/')时会默认将父组件合并加载该组件
component: () => import('@/views/Index.vue'), // 跟上边公共组件合并
},
{
name: 'detail',
path: 'detail/:id', // 相对路径
props: true,
component: () => import('@/view/Detail.vue'), // 跟上边公共组件合并
}
]
}
]
编程式导航
-
跳转路由但不记录历史
this.$router.replace('/login')
-
会记录历史跳转
this.$router.push('/')
-
会记录历史跳转切传递参数id为1
this.$router.push({name: 'Detail', params: { id: 1 }})
-
后退到上上一次页面,后退2次
this.$router.go(-2)
Hash模式和History模式
表现形式区别
-
Hash模式
https://xuanhe.com/#/detail?age=18
-
History模式
https://xuanhe.com/detail/18
原理的区别
- Hash模式是基于锚点,以及onhashchange事件,通过锚点的值作为路由地址,当地址发生变化后,发生onhashchange事件
- History模式是基于HTML5中的History API
- history.pushState() 不会向服务端发送请求,只会改变浏览器地址,并且将地址记录在历史记录中
- history.replaceState() 同上,但是不会保存记录
- 监听popstate事件监听浏览器的变化,但是调用history.pushState()和history.replaceState()不会触发该事件,只有在点击浏览器的回退按钮(或者在Javascript代码中调用history.back()或者history.forward()方法)才会出发
关于popstate的用法详情 popstate
注意: History模式需要服务器的支持
-
单页应用中,服务端不存在的地址会返回找不到该页面(刷新页面的操作会向服务器发送请求)
-
在服务器端要配置除了静态资源外都返回单页应用的index.html
-
node中使用一个插件处理history模式
connect-history-api-fallback
- nginx中配置
server {
listen 80; # 端口号
server_name localhost; # 域名(一般是线上地址)
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html; # 根目录
index index.html ind