本文为拉勾网大前端高薪训练营第一期笔记
8.1.2 Vue Router原理实现
Vue router
初始化vue的时候选择router,会自动生成router相关代码
Vue.use(VueRouter)
use传参如果是函数,会调用函数注册组件,如果是对象的话会调用对象的install方法
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from '../views/Index.vue'
// 1. 注册路由插件
Vue.use(VueRouter)
// 路由规则
const routes = [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/blog',
name: 'Blog',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "blog" */ '../views/Blog.vue')
},
{
path: '/photo',
name: 'Photo',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "photo" */ '../views/Photo.vue')
}
]
// 2. 创建 router 对象
const router = new VueRouter({
routes
})
export default router
//template部分代码
<template>
<div id="app">
<div>
<img src="@/assets/logo.png" alt="">
</div>
<div id="nav">
<!-- 5. 创建链接 -->
<router-link to="/">Index</router-link> |
<router-link to="/blog">Blog</router-link> |
<router-link to="/photo">Photo</router-link>
</div>
<!-- 4. 创建路由组件的占位,匹配到的会在这里显示 -->
<router-view/>
</div>
</template>
//main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
// 3. 注册 router 对象,这里注册的话Vue实例会增加$route和$router属性
//$route包括路由参数 $router是VueRouter实例提供很多方法,常用push replace go
//插件里经常拿不到$route,但是能拿到$router,currentRoute可以获取当前路由规则
router,
render: h => h(App)
}).$mount('#app')
动态路由
路由配置
const routes = [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/blog',
name: 'Blog',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "blog" */ '../views/Blog.vue')
},
{
path: '/photo',
name: 'Photo',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "photo" */ '../views/Photo.vue')
}
]
两种方式获得id,推荐第二个,前面的配置开启props:true
<template>
<div>
<!-- 方式1: 通过当前路由规则,获取数据 -->
通过当前路由规则获取:{{ $route.params.id }}
<br>
<!-- 方式2:路由规则中开启 props 传参 -->
通过开启 props 获取:{{ id }}
</div>
</template>
嵌套路由
//layout.vue
<router-view></router-view>
//router/index.js
const routes = [
{
name: 'login',
path: '/login',
component: Login
},
// 嵌套路由
{
path: '/',
component: Layout,
children: [
{
name: 'index',
path: '',
component: Index
},
{
name: 'detail',
path: 'detail/:id',
props: true,
component: () => import('@/views/Detail.vue')
}
]
}
]
编程式导航
<template>
<div class="home">
<div id="nav">
<router-link to="/">Index</router-link>
</div>
<button @click="replace"> replace </button>
<button @click="goDetail"> Detail </button>
</div>
</template>
<script>
export default {
name: 'Index',
methods: {
replace () {
this.$router.replace('/login')
},
goDetail () {
this.$router.push({ name: 'Detail', params: { id: 1 } })
//可以通过name来跳转
}
}
}
</script>
hash模式和history模式区别
-
Hash模式是基于锚点,以及onhashchange事件
-
History模式是基于HTML5中的History API
- history.pushState() IE10以后才支持
- history.replaceState()
history模式如果后端不支持,会出现刷新页面找不到页面的express提醒
后端express支持的写法
const path = require('path') // 导入处理 history 模式的模块 const history = require('connect-history-api-fallback') // 导入 express const express = require('express') const app = express() // 注册处理 history 模式的中间件 app.use(history()) // 处理静态资源的中间件,网站根目录 ../web app.use(express.static(path.join(__dirname, '../web'))) // 开启服务器,端口是 3000 app.listen(3000, () => { console.log('服务器开启,端口:3000') })
静态文件后端nginx支持的方法
location / { root html; index index.html index.htm; try_files $uri $uri/ /index.html; }
Vue带编译器版本
会大10K左右,支持template,会把template编译成render函数
//vue.config.js
module.exports = {
runtimeCompiler: true
}
如果不用带编译版本的
render(h){
return h("a",{
attrs:{
href:this.to
},
on:{
click:this.clickhander
}
},[this.$slots.default])
},
methods:{
clickhander(e){
history.pushState({},"",this.to)
this.$router.data.current=this.to
e.preventDefault()
}
}
//用带编译器版本的写法 template:"<a :href='to'><slot></slot><>"