Part3-1-2 Vue Router
Posted 沿着路走到底
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Part3-1-2 Vue Router相关的知识,希望对你有一定的参考价值。
Vue Router 基础使用
router/index.js
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
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
Vue.config.productionTip = false
new Vue({
// 3. 注册 router 对象
router,
render: h => h(App)
}).$mount('#app')
App.vue
<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>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
动态路由
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from '../views/Index.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Index',
component: Index
},
{
path: '/detail/:id',
name: 'Detail',
// 开启 props,会把 URL 中的参数传递给组件
// 在组件中通过 props 来接收 URL 参数
props: true,
// 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: "detail" */ '../views/Detail.vue')
}
]
const router = new VueRouter({
routes
})
export default router
App.vue
<template>
<div id="app">
<div id="nav">
<router-link to="/">Index</router-link> |
<router-link to="/detail/11">Detail</router-link>
</div>
<router-view/>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
Detail.vue
<template>
<div>
<!-- 方式1: 通过当前路由规则,获取数据 -->
通过当前路由规则获取:{{ $route.params.id }}
<br>
<!-- 方式2:路由规则中开启 props 传参 -->
通过开启 props 获取:{{ id }}
</div>
</template>
<script>
export default {
name: 'Detail',
props: ['id']
}
</script>
<style>
</style>
嵌套路由
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
// 加载组件
import Layout from '@/components/Layout.vue'
import Index from '@/views/Index.vue'
import Login from '@/views/Login.vue'
Vue.use(VueRouter)
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')
}
]
}
]
const router = new VueRouter({
routes
})
export default router
App.vue
<template>
<div id="app">
<div id="nav">
<router-view></router-view>
</div>
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
}
#nav a {
font-weight: bold;
color: #2c3e50;
}
#nav a.router-link-exact-active {
color: #42b983;
}
</style>
components\\Layout.vue
<template>
<div>
<div>
<img width="25%" src="@/assets/logo.png">
</div>
<div>
<router-view></router-view>
</div>
<div>
Footer
</div>
</div>
</template>
<script>
export default {
name: 'layout'
}
</script>
<style scoped>
</style>
Index.vue
<template>
<div>
这里是首页 <br>
<router-link to="login">登录</router-link> |
<router-link to="detail/5">详情</router-link>
</div>
</template>
<script>
export default {
name: 'Index'
}
</script>
<style>
</style>
编程式导航
index.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 } })
}
}
}
</script>
login.vue
<template>
<div>
用户名:<input type="text" /><br />
密 码:<input type="password" /><br />
<button @click="push"> push </button>
</div>
</template>
<script>
export default {
name: 'Login',
methods: {
push () {
this.$router.push('/')
// this.$router.push({ name: 'Home' })
}
}
}
</script>
<style>
</style>
detail.vue
<template>
<div>
路由参数:{{ id }}
<button @click="go"> go(-2) </button>
</div>
</template>
<script>
export default {
name: 'Detail',
props: ['id'],
methods: {
go () {
this.$router.go(-2)
}
}
}
</script>
<style>
</style>
Hash 模式和 History 模式的区别
History 模式的使用
frontend
router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
// 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: "about" */ '../views/About.vue')
},
{
path: '*',
name: '404',
component: () => import(/* webpackChunkName: "404" */ '../views/404.vue')
}
]
const router = new VueRouter({
mode: 'history',
routes
})
export default router
backend
Node.js
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
从官网下载 nginx 的压缩包
把压缩包解压到 c 盘根目录,c:\\nginx-1.18.0 文件夹
修改 conf\\nginx.conf 文件
location / {
root html;
index index.html index.htm;
#新添加内容 #尝试读取$uri(当前请求的路径),如果读取不到读取$uri/这个文件夹下的首页 #如果都获取不到返回根目录中的 index.html
try_files $uri $uri/ /index.html;
}
打开命令行,切换到目录 c:\\nginx-1.18.0
nginx 启动、重启和停止
# 启动
start nginx
# 重启
nginx -s reload # 停止
nginx -s stop
VueRouter 实现原理
Hash 模式
URL中 # 后面的内容作为路径地址
监听 hashchange 事件,当 hash 发生改变,会触发 hashchange 事件
在 hashchange 事件中,记录当前路由地址
根据当前路由地址找到对应组件重新渲染
History 模式
通过 history.pushState() 方法改变地址栏
pushState 仅仅改变地址栏,并将当前浏览器地址记录到访问历史中,但是不会向服务器发起请求
监听 popstate事件
popstate 可以监听到浏览器历史操作的变化,在popstate 处理函数中,可以记录改变后的地址
调用 pushState 或 replaceState,不会触发 popstate 事件
点击浏览器前进后退按钮,调用 history 的 back 或 forward 方法,才会触发 popstate
根据当前路由地址找到对应组件重新渲染
VueRouter 类图
属性:
options:记录构造函数中传入的对象 ( routes )
data:是一个对象,里面有个属性 current,用来记录当前路由地址,data对象是响应式的,因为当路由地址发生变化后,对应的组件要自动更新,使用 Vue.observable() 使 data 变成 响应式数据
routeMap:是一个对象,用来记录 路由地址和组件的对应关系,会将传入的路由规则(routes)解析到 routeMap
方法:
_install:静态方法,实现 Vue 的插件机制
initEvent:注册 popstate 事件,用来监听浏览器历史的变化
createRouteMap:初始化 routeMap 属性,将构造函数传入的路由规则转换成 键值对 的形式存储到 routeMap 里,键 就是 路由的地址,值 就是对应的组件
initComponents:创建 routeLink 和 routeView 这2个组件
Vue 的构建版本
运行时版:不支持 template 模板,需要打包的时候提前编译
完整版:包含运行时和编译器,体积比运行时版大10K左右,程序运行的时候把模板转换成 render 函数
配置完整版:在 vue.config.js 里配置属性,runtimeCompiler
module.exports = {
runtimeCompiler: true
}
1
以上是关于Part3-1-2 Vue Router的主要内容,如果未能解决你的问题,请参考以下文章