1. 起步
通过Vue-CLI脚手架快速搭建我们的vue开发环境,具体可参考:Vue基础(一):开发环境搭建(window),搭建完成后就可以开始今天的学习了。
运行我们的项目,进入到如下页面,我们的项目运行成功:
疑问:
我们没有写任何页面也没有做任何配置,怎么会访问到这个页面?
1.1 项目运行分析
当我们访问http://localhost:8080/时,默认会进入到项目的public/index.html
页面,这也是单页面应用的唯一入口。
-
index.html中只配置了id为app的这个div,后面vue会通过main.js来渲染这个div
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <!-- index.html中只配置了id为app的这个div,后面vue会通过main.js来渲染这个div --> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
-
此时vue会通过main.js中的配置进行渲染id为app的div
import Vue from 'vue' import App from './App.vue' import router from './router' import store from './store' Vue.config.productionTip = false //创建Vue组件,引入router、store以及App.vue new Vue({ router, store, render: h => h(App) //在这里将id为app的div渲染为App.vue组件 }).$mount('#app')
-
App.vue组件
我们默认访问的路径为/
根路径,此时Vue Router会在路由表中匹配我们的对应的路径,加载到对应vue组件,最后会在<router-view/>
中进行渲染。<template> <div id="app"> <div id="nav"> <!-- 使用 router-link 组件来导航. --> <!-- 通过传入 `to` 属性指定链接. --> <!-- <router-link> 默认会被渲染成一个 `<a>` 标签 --> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> </div> <!-- 路由出口 --> <!-- 路由匹配到的组件将渲染在这里 --> <router-view/> </div> </template>
注意:
<router-link>
标签类似于<a>
标签,作用也是用来做路由跳转 -
路由配置router/index.js
// 1. 使用模块化,导入Vue和VueRouter,要调用 Vue.use(VueRouter) import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' Vue.use(VueRouter) // 2. 定义路由 const routes = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', //使用懒加载方式,当访问这个路由路径时才去加载这个vue组件 component: () => import('../views/About.vue') } ] // 3. 创建 router 实例,然后传 `routes` 配置 const router = new VueRouter({ routes }) export default router
以上就是简单的路由访问时序分析
2. 动态路由匹配
模拟场景:例如我们系统中的顶部导航栏head.vue组件,这个组件每个用户进入都会访问这个组件,但是导航栏中显示的用户名不一致,我们可以使用动态路径参数达到这个效果,也可以实现组件复用:
- 定义路由
const routes = [
{
// 动态路径参数 以冒号开头,如这里的:name
path:"/head/:name",
component: () => import( '../views/Head.vue')
}
]
- 定义Head.vue组件
<template>
<!-- $route可以获取当前的路由对象 -->
<!-- $route.params可以获取所有的路径参数,这里获取路径参数的name值 -->
<div>{{$route.params.name}}</div>
</template>
-
页面输入
http://localhost:8080/#/head/wanik
访问结果如下:
相信大家已经发现我们访问的路径中怎么有个#
?
其实这是vue路由中的使用的默认hash模式,以下是官方解释,具体官方文档可点这里查看。vue-router 默认 hash 模式 —— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。
我们可以在router/index.js中这么配置:
const router = new VueRouter({
mode: 'history',
routes
})
3. 嵌套路由
我们创建两个组件,分别为Parent.vue和Child.vue,如下:
Parent.vue中嵌套了<router-view/>
<template>
<div>
我是父级组件Parent.vue
<router-view/>
</div>
</template>
Child.vue
<template>
<div>
我是子级组件Child.vue
</div>
</template>
接着我们定义路由表:
const routes = [
{ //定义父级路由
path:"/parent",
component: () => import("../views/Parent.vue"),
//使用children属性定义子组件路由
children:[
{
//当我们访问/parent/child路径时
//会将Child.vue组件渲染到Parent.vue中的<router-view/>中
path:"child",
component: () => import("../views/Child.vue")
}
]
}
]
演示结果:
4. 编程式的导航
除了使用<router-link to="/path"></router-link>
创建导航链接外,我们还可以在vue组件内部使用如:$router.push(...)
、$router.go(...)
、$router.replace(...)
、$router.back()
等方法
router.push :这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。
routter.replace:不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录。
router.go(n):这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
router.back:这个方法返回history上一次的记录,效果同router.go(-1)
5. 命名路由
我们在配置路由时给该路由设置name属性,如:
const routes = [
{
path: '/',
name: 'Home', //给该路由命名为Home
component: Home
},
{
path: '/about',
name: 'About', //给该路由命名为About
//使用懒加载方式,当访问这个路由路径时才去加载这个vue组件
component: () => import('../views/About.vue')
}
]
此时我们可以修改<router-link>
如下:
<template>
<div id="app">
<div id="nav">
<!--给 router-link 的 to 属性传一个对象-->
<router-link :to="{name:'Home'}">Home</router-link> |
<router-link :to="{name:'About'}">About</router-link>
</div>
<router-view/>
</div>
</template>
注意:
这里需要使用v-bind:to
(简写为:to
), 否则里面的值会被当做普通字符串处理
6. 命名视图
场景模拟:例如我们的主页面存在顶部,左侧和内容区域,此时我们不适用嵌套路由做,可以定义多个<router-view>
,并且给每个视图命名,如下:
<template>
<div id="app">
<router-view/>
<router-view name="sidebar"/>
<router-view name="main"/>
</div>
</template>
const routes = [
{
path: '/',
name: 'Home',
components:{
//如果没有命名的router-view将显示Head.vue
default: () =>import('../views/Head.vue'),
//命名为sidebar的router-view将显示SideBar.vue
sidebar: () =>import("../views/SideBar.vue"),
//命名为main的router-view将显示Main.vue
main: () =>import("../views/Main.vue")
}
}
]
运行结果显示如下:
7.重定向和别名
重定向
在路由配置中使用redirect属性设置重定向路径或命名组件
方式一:
const routes = [
{
path:"/hello", //定义/hello路由路径,当我们访问/hello路径时会重定向至`/`
redirect:"/"
}
]
方式二:
const routes = [
{
path:"/hello",
redirect:{ name: 'Home'} //重定向至路由名称为Home的组件
}
]
别名
通过alias属性设置别名,访问路径为/
、/main
、/home
结果一样
const routes = [
{
path: '/',
name: 'Home',
alias:['/mian',"/home"],
components:{
//如果没有命名的router-view将显示Head.vue
default: () =>import('../views/Head.vue'),
//命名为sidebar的router-view将显示SideBar.vue
sidebar: () =>import("../views/SideBar.vue"),
//命名为main的router-view将显示Main.vue
main: () =>import("../views/Main.vue")
}
}
]