简介:这里的路由并不是指我们平时所说的硬件路由器,这里的路由就是
SPA(单页应用)
的路径管理器
。再通俗的说,vue-router就是WebApp的链接路径管理系统。
路由用于设定访问路径,并将路径和组件映射起来。传统的页面应用,是用一些超链接来实现页面切换和跳转的。在vue-router单页面应用中,则是路径之间的切换,也就是组件的切换。路由模块的本质 就是建立起url和页面之间的映射关系
。
实现原理
SPA(single page application):单一页面应用程序,只有一个完整的页面;它在加载页面时,不会加载整个页面,而是只更新某个指定的容器中内容。单页面应用(SPA)的核心之一是: 更新视图而不重新请求页面;vue-router在实现单页面前端路由时,提供了两种方式:Hash模式和History模式;根据mode参数来决定采用哪一种方式。
npm install vue-router --save
大家如果留心观察就会发现,之前我们做的页面的 URL 里有一个 # 号,这个 # 号有什么含义呢?
vue-router 默认 hash 模式
—— 使用 URL 的 hash 来模拟一个完整的 URL,于是当 URL 改变时,页面不会重新加载
。 hash(#)是URL 的锚点,代表的是网页中的一个位置,单单改变#后的部分,浏览器只会滚动到相应位置,不会重新加载网页,也就是说hash 出现在 URL 中,但不会被包含在 http 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面
;同时每一次改变#后的部分,都会在浏览器的访问历史中增加一个记录,使用”后退”按钮,就可以回到上一个位置;所以说Hash模式通过锚点值的改变,根据不同的值,渲染指定DOM位置的不同数据。hash 模式的原理是 onhashchange 事件(监测hash值变化),可以在 window 对象上监听这个事件
。
由于hash模式会在url中自带#,如果不想要很丑的 hash,我们可以用路由的 history 模式
,只需要在配置路由规则时,加入"mode: ‘history’",这种模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。这两个方法应用于浏览器记录栈,在当前已有的 back、forward、go 基础之上,它们提供了对历史记录修改的功能。只是当它们执行修改时,虽然改变了当前的 URL ,但浏览器不会立即向后端发送请求
。
当你使用 history 模式时,URL 就像正常的 url,例如 http://yoursite.com/user/id,比较好看!
不过这种模式要玩好,还需要后台配置支持。因为我们的应用是个单页客户端应用,如果后台没有正确的配置,当用户在浏览器直接访问 http://oursite.com/user/id 就会返回 404,这就不好看了。
所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。
export const routes = [
{path: "/", name: "homeLink", component:Home}
{path: "/register", name: "registerLink", component: Register},
{path: "/login", name: "loginLink", component: Login},
{path: "*", redirect: "/"}]
此处就设置如果URL输入错误或者是URL 匹配不到任何静态资源,就自动跳到到Home页面
1:下载
2:在main.js中引入 import VueRouter from ‘vue-router’;
3:安装插件Vue.use(VueRouter);
4:创建路由对象并配置路由规则[{path:’/home’,component:Home}]});
5:将其路由对象传递给Vue的实例,options中加入 router:router
6:在app.vue中留坑
// 配置路由相关的信息,main.js文件中引入
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
// 1.通过Vue.use(插件), 安装插件
Vue.use(VueRouter)
// 2.创建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')
}
]
// 配置路由和组件之间的应用关系
const router = new VueRouter({
//配置模式为history
mode: 'history',
base: process.env.BASE_URL,
routes
})
// 3.将router对象传入到Vue实例
export default router
将这两者console.log打印出来:
$route 是“路由信息对象”
包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。
① $route.path
字符串,对应当前路由的路径,总是解析为绝对路径,如 “/order”。
② $route.params
一个 key/value 对象,包含了 动态片段 和 全匹配片段,
如果没有路由参数,就是一个空对象。
③ $route.query
一个 key/value 对象,表示 URL 查询参数。
例如,对于路径 /foo?user=1,则有 $route.query.user为1,
如果没有查询参数,则是个空对象。
④ $route.hash
当前路由的 hash 值 (不带 #) ,如果没有 hash 值,则为空字符串。
⑤ $route.fullPath
完成解析后的 URL,包含查询参数和 hash 的完整路径。
⑥ $route.matched
数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
⑦ $route.name
当前路径名字
$router 是“路由实例”对象
即使用 new VueRouter创建的实例,包括了路由的跳转方法,钩子函数等
$router常见跳转方法:
<button @click="goToMenu" class="btn btn-success">Let's order!</button>
.....
<script>
export default{
methods:{
goToMenu(){
this.$router.go(-1)//跳转到上一次浏览的页面
this.$router.replace('/menu')//指定跳转的地址
this.$router.replace({name:'menuLink'})//指定跳转路由的名字下
this.$router.push('/menu')//通过push进行跳转
this.$router.push({name:'menuLink'})//通过push进行跳转路由的名字下
}
}
}
</script>
$router.push
和$router.replace
的区别:
to属性:配置的path值,如果要导航到默认首页,只需要写成 to="/" ,
# 点击跳转到“/”路径,默认为a标签
<router-link to="/">Homerouter-link> |
tag属性:决定渲染类型
# 点击跳转到"/",类型修改为button按钮
<router-link to="/" tag="button">Homerouter-link> |
replace属性:不会留下history记录
# 点击跳转到"/"后,不能在浏览器中使用返回上一个页面
<router-link to="/" tag="button" replace>Homerouter-link> |
active-class属性:通常不会使用
# 点击跳转到"/"后,不能在浏览器中使用返回上一个页面
<router-link to="/" replace active-class="active">Homerouter-link> |
redirect: ' '
重定向到主页import Vue from 'vue'
// 导入使用路由
import Router from 'vue-router'
// 导入刚才编写的组件
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'
//1.通过Vue.use(插件),安装插件
Vue.use(Router)
//2.创建VueRouter对象,然后把对象传入到vue实例(main.js)。export导出
export default new Router({
//配置路由和组件之间的关系
routes: [
{
//默认重定向
path: '',
redirect:'login'
},
{
//path路径、component被导入的组件的映射、name
path: '/login',
name: 'Login',
component: Login
},
{
path: '/index',
name: 'AppIndex',
component: AppIndex
}
]
})
mode: 'history',
import Vue from 'vue'
import Router from 'vue-router'
import AppIndex from '@/components/home/AppIndex'
import Login from '@/components/Login'
Vue.use(Router)
export default new Router({
//修改配置为history模式
mode: 'history',
routes: [
{
path: '/login',
name: 'Login',
component: Login
},
{
path: '/index',
name: 'AppIndex',
component: AppIndex
}
]
})
简介:比如在写商品详情页面的时候,页面结构都一样,只是商品id的不同,所以这个时候就可以用动态路由动态
动态路由的官方文档
可以在一个路由中设置多段“路径参数”,对应的值都会设置到$route.params
中
$route
指的是活跃状态下的路由,而不是$router
模式 1
1.先动手试一下上面表格中第一个模式的实现,在我们之前创建的my-first-project的src文件夹下新建一个文件夹并命名为view
然后在文件夹下新建test.vue
2.打开test.vue文件
3.到my-project->src->router->index.js文件,打开并输入
在这里说明一下,$router.params.testId的意思,当然是获取当前路由的参数
6.运行项目,打开浏览器,输入localhost:8080
模式 2
2.修改test.vue文件
简介:当打包构建应用时候,JS包会变得非常大,影响页面加载,如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候加载就更加高效了。结合
Vue 的异步组件
和Webpack 的代码分割功能
,轻松实现路由组件的懒加载。
问题出现在与:
如果我们一次性在服务器请求下来这个页面,可能需要花费一定的时间,甚至用户访问时候会出现空白的情况,如何避免这个问题就需要路由懒加载(尤其是vue这种单页面应用文件!!!造成进入首页时,需要加载的内容过多)
俗话讲就是:用到时再加载,解决vue第一次加载时间过长的问题
vue-router懒加载的实现非常简单,在配置路由的时候components从原先的写组件名改为resolve => require([URL], resolve)
这种格式即可
不使用懒加载写法:
import Vue from 'vue'
import Router from 'vue-router'
import Parent from '@/components/Parent'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Parent',
component: Parent
}
]
})
使用懒加载写法:
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Parent',
component: resolve => require(['@/components/Parent'], resolve)
}
]
})
或者
import Vue from 'vue'
import Router from 'vue-router'
//导入并且懒加载
const Parent =() => import('../components/Parent')
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'Parent',
component: Parent
}
]
})
把组件按组分块
有时候我们想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用 命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4)。
const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')
Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。
简介:就是在一个页面中通过路由嵌套实现访问不同内容。如/home/message和/home/news,可以在同一个页面中切换展示
1. 编写好子组件和主组件
2. 在index.js添加children字段配置映射关系
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
//children是拼接上url的
children: [{path: '/h1', name: 'H1', component: H1},
{path: '/h2', name: 'H2', component: H2}
]
}
]
3.确定routerview好展示位置
在主组件中添加routerview标签
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<router-view></router-view>
</div>
</template>
4.在主组件中增加链接
<router-link :to="{name:'HelloWorld'}">主页</router-link>
<router-link :to="{name:'H1'}">H1页面</router-link>
<router-link :to="{name:'H2'}">H2页面</router-link>
实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL中各段动态路径也按某种结构对应嵌套的各层组件,例如:
如何实现下图效果(H1页面和H2页面嵌套在主页中)?
1.首先用标签增加了两个新的导航链接
<router-link :to="{name:'HelloWorld'}">主页</router-link>
<router-link :to="{name:'H1'}">H1页面</router-link>
<router-link :to="{name:'H2'}">H2页面</router-link>
2.在HelloWorld.vue加入标签,给子模板提供插入位置
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<router-view></router-view>
</div>
</template>
3.在components目录下新建两个组件模板 H1.vue 和 H2.vue。两者内容类似,以下是H1.vue页面内容:
<template>
<div class="hello">
<h1>{{ msg }}</h1>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'I am H1 page,Welcome to H1'
}
}
}
</script>
4.修改router/index.js代码,子路由的写法是在原有的路由配置下加入children字段。
routes: [
{
path: '/',
name: 'HelloWorld',
component: HelloWorld,
children: [{path: '/h1', name: 'H1', component: H1},//子路由的必须在HelloWorld.vue中出现
{path: '/h2', name: 'H2', component: H2}
]
}
]
声明式的导航
和编程式的导航router.push(...)
都可以传参,本文主要介绍前者的传参方法,同样的规则也适用于编程式的导航
name
传递参数($route.name)
在路由文件src/router/index.js里配置name属性
routes: [
{
path: '/',
name: 'Hello',
component: Hello
}
]
模板里(src/App.vue)用 {{ $route.name}}$route.name
来接收 比如:
,就可以访问该路由页面的时候显示标题
标签中的:to
传参:to指的是v-blind:to
此方法传参传的是一个对象
,这种传参方法的基本语法
<router-link :to="{name:xxx,params:{key:value}}">valueString</router-link>
1.比如先在src/App.vue文件中编写对象传参
<router-link :to="{name:'hi1',params:{username:'jspang',id:'555'}}">Hi页面1</router-link>
2.然后把src/router/index.js文件里给hi1配置的路由起个name,就叫hi1
{path:'/hi1',name:'hi1',component:Hi1}
3.最后在模板里(src/components/Hi1.vue)用$route.params.username进行接收.
{{$route.params.username}}-{{$route.params.id}}
我们在/src/router/index.js文件里配置路由
{
path:'/params/:newsId/:newsTitle',
component:Params
}
我们需要传递参数是新闻ID(newsId)和新闻标题(newsTitle).所以我们在路由配置文件里制定了这两个值。
在src/components目录下建立我们params.vue组件,也可以说是页面。我们在页面里输出了url传递的的新闻ID和新闻标题。
<template>
<div>
<h2>{{ msg }}</h2>
<p>新闻ID:{{ $route.params.newsId}}</p>
<p>新闻标题:{{ $route.params.newsTitle}}</p>
</div>
</template>
<script>
export default {
name: 'params',
data () {
return {
msg: 'params page'
}
}
}
</script>
在App.vue文件里加入我们的
标签。这时候我们可以直接利用url传值了
query
来传递参数<router-link :to="{ name:'Query',query: { queryId: status }}" >
router-link跳转Query
</router-link>
对应路由配置:
{
path: '/query',
name: 'Query',
component: Query
}
于是我们可以获取参数:
this.$route.query.queryId
一个完整的URL=协议+域名+端口号+路径+资源+搜索词+哈希
# 传输协议是用来完成客户端和服务器端之间数据传输的
# 传输协议可分为三类
1.http:超文本传输协议
2.https:http ssl,它比http更加安全
3.ftp:资源文件传输协议
# 问号传参(可有可无)
把一些值通过 “key=value” 的方式放在一个URL的末尾,通过?传递;
作用:
1、在ajax请求中,我们可以通过问号传递参数的方式,在客户端把一些信息传递给服务器,服务器根据传递信息的不一样,返回不同的数据;
2、清除ajax get方法的缓存,?math_random=0.123456;
3、通过URL传递参数的方式,实现页面之间的通信;
HASH值(可有可无)
作用
1、可做页面中的锚点定位
2、在单页应用开发中作为前端路由使用(Vue Router、React Router);
—end