若web服务器的 安置为10.0.0.1,该web服务器提供了3个供用户访问的页面,页面URI分别为
当用户使用https://10.0.0.1/about访问页面时,web服务器会受到请求,解析URL中的路径/about,程序会将请求交给路径对应的处理路径,完成“路由分发”
后端路由 由后台完成,即通过用户请求的url导航到具体的html页面
前端路由 是通过配置js文件,将上述工作在前端完成
history是html5新增的API,可以用来操作浏览器的session history
在html5的history API出现前,前端路由都是通过hash来实现,hash能够兼容低版本的浏览器
对于上述的URI例子,如果用hash来实现,他的URL规则中需要带上“#”
- https://10.0.0.1/
- https://10.0.0.1/#/about
- https://10.0.0.1/#/contract
web服务不会解析hash,即web服务会自动忽略“#”后面的内容,但是JavaScript可以通过windows.location.hash
读取到,其读取到路径之后再加以解析就可以相应不同路径的逻辑处理
前端路由的优点:
- 后端路由访问新页面需要向服务器发送请求,而前端路由则只是变换路径,没有网络延迟
- 某些场合,用ajax请求,页面内容刷新,但url不变,用户不能复制想要的地址。前端路由支持单页面应用
前端路由的缺点
- 浏览器饿前进、后退按钮会重新发送请求,没有合理理由缓存
用npm包方式安装
cnpm install vue-router --save
vue router是vue的一个插件,需要在vue的全局应用中通过Vue.use()
将他纳入Vue实例中。
在项目中,main.js
是程序的入口文件,所有的全局性配置都在这个文件中进行
提示:
在通过Vue-cli脚手架快速搭建想是,命令行交互会询问是否需要路由功能。
所以绝大部分项目在搭建时已经具备了路由功能,不需要再额外安装了。
通过Vue-cli脚手架搭建的项目,在src文件夹下会有router文件夹,内部有index.js文件,打开文件会看到以下引用
import Vue from 'vue'
import Router from 'vue-router'
Vue.use(Router)
在入口文件main.js中导入router中的index.js文件,即可使用路由配置的信息
import router from './router'
先建立一个路由器模块,主要用来配置和绑定相关信息。
在router文件夹下的index.js文件中使用new Router命令创建一个路由,一个路由是一个对象,一条路由的实现需要三部分:name、path、component。name是命名,path是路径,component是组件。
import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
// 把对应的组件或页面引入进来
import Login from '@/pages/login'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',//这里默认是跳转到HelloWorld组件,后期会改为项目首页
name: 'HelloWorld',
component: HelloWorld
}
},{
path:'/login',//登录页路径
name:'Login',
component:login
}//后续如果还有页面要跳转,就按照这样的格式继续书写
]
})
导入HelloWorld组件时,实际导入的是component/HelloWorld.vue
因为在webpack中配置了,所以可以省略vue后缀
在main,js
入口文件中启用该路由器。main.js
作为入口文件,使用import
可以把所有用到的包都导入这里,然后在Vue项目中去运用它们。创建和挂载根实例,通过router配置参数注入路由,从而让整个应用都有路由功能
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
// 将router加入
new Vue({
el: '#app',
router,
components: { App },
template: ' '
})
根据上述配置,路由匹配到的组件将会渲染到App.vue的
,
App.vue
的写法如下
App.vue
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
最后App.vue会渲染到index.html
index.html
<body>
<div id="app">div>
body>
这样,就会把渲染出来的页面挂载到id为app的div里
项目通常有一个首页。默认首先打开的是首页,要跳转到那个页面都可以设置路由路径完成跳转。
优势也需要路由器定义全局的重定向规则,全局的重定向会在匹配当前路径之前执行。
重定向也是通过routers配置来完成的
例:由“/a
”重定向到“/b
”
const router = new VueRouter({
router:[
{path:'/a',redirect:'/b'}
]
})
例:重定向的目标 可以是 一个命名的路由
const router = new VueRouter({
router:[
{path:'/a',redirect:{name:'foo'}}
]
})
例:重定向的目标 是 一个方法,动态返回重定向目标
const router = new VueRouter({
router:[
{path:'/a',redirect to => {
// 方法接收“目标路由”作为参数
// return重定向的“字符串路径/路径对象”
}}
]
})
在打包构建应用是,JavaScript包会变得非常大,影响页面加载。
如果能把不同路由对应的组件分割成不同的代码块,当路由被访问时才加载对应组件,就会比较高效。
结合Vue的异步组件和Webpack的代码分割功能,可以轻松实现路由的懒加载。
异步组件
在大型应用是,会需要将应用拆分为多个小的模块,按需从服务器下载。
Vue.js允许将组件定义为一个工厂函数,异步地解析组件的定义。
Vue.js只在组件需要渲染时,触发工厂函数,缓存结构,用于后来的再次渲染。
首先,可以将异步组件定义为返回一个Promise的工厂函数(该函数返回的Promise应该是resolve组件本身
const Foo = () => Promise.resolve({/*组件定义对象*/})
其次,在Webpack中,可以使用动态import语法来定义代码的分块点(split point)
import('./Foo.vue') //返回Promise
结合以上两点,就是定义一个能够被Webpack自动进行代码分割的异步组件的过程
const Foo=() =>import('./Foo.vue')
在路由配置中不需要改变,只需要像往常一样使用Foo组件即可
const router = new VueRouter({
routers:[
{path:'/foo',
component:Foo}
]
})
通过懒加载,不会一次性加载所有组件,而是访问到组件才加载,提高首次加载速度
// 引入组件header
const Header =()=>import('@/components/header');
//引入页面中的首页
const Index=()=>import('@/pages/index');
const Login=()=>import('@/pages/login');
组件支持用户在具有路由功能的应用中单击导航。
通过 to 属性可以指定目标地址,默认渲染成带有正确链接的标签,通过配置 tag 属性可以生成别的标签。
另外,当目标路由成功激活时,链接元素会自动设置一个表示激活的css类名。
其使用语法如下
<router-link v-bind:to="'home'"> Home router-link>
<a href="home"> Home a>
<router-link :to="'home'"> Home router-link>
<router-link :to="{path:'home'}"> Home router-link>
<router-link :to="{name:'user',params:{useId:123}}"> User router-link>
<router-link :to="{path:'register',query:{plan:'private'}}"> Register router-link>
- 无论是html5 history模式,还是hash模式,他们的表现行为一致,无需变动
- 在html5 history模式时,
会守卫单击事件,让浏览器不再重新加载页面
- 在html5 history模式时,使用base选项后,所有的to属性都不需要写基路径
单击ad-card模式后,会跳转到ticketDesc路径下,并且把参数id的值传过去。
其中,to的类型:string|Location。单击后,内部会立刻把to值传到router.push(),这个值可以是一个字符串或者是描述目标位置的对象。
required表示目标路径的连接
【例】
<div class='ad-card'>
<router-link :to="{path:'/ticketDesc',query:{id:headCard.id}}">
<div class="ad-hide">
<h3>{{headCard.itemName}}h3>
<p>{{headCard.minPrice}}元p>
div>
router-link>
div>
常用路由信息对象如下:
$route.path
/foo/bar
”$route.params
$route.query
/foo?user=1
,则有$route.query.user==1
;如果没有查询参数,则为空对象。$route.hash
$route.fullPath
$route.matched
页面间跳转通常是单击了某个按钮,这时就不能只用,还需要借助router的实例方法,通过编写
router.push(location)
要导航到不同的URL,则使用router.push方法。
该方法会向history栈添加一个新的记录,当用户单击浏览器后退按钮时,回到之前的URL。
当单击
时,会在内部调用router.push(…)方法,所以说单击
等同于调用router.push(…)
该方法的参数可以是一个字符串路径,也可以是一个描述地址的对象。例如:
router.push('home')//字符串
router.push({path:'home'})//对象
// 命名的路由
router.push({name:'user',params:{useId:123}})//->/user/123
// 带查询参数,变成/register?plan=private
router.push({path:'register',query:{plan:'private'}})
由一个页面跳转到另一个页面,需要携带一些数据,这时就需要用到这种带参数的路由跳转
router.replace(location)
router.replace和router.push很像,唯一的不同时他不会向history栈添加新纪录,而是跟他的方法名一样只替换掉当前的history记录
router.replace(……)等价于
router.go(n)
router.go方法是一个整数,表法在history记录中向前进多少步或向后退多少步
类似于window.history.go(n)
具体用法:
// 在浏览器记录中前进一步,等同于history.forward()
router.go(1)
// 后退一步,等同于 history.back()
router.go(-1)
// 前进三步
router.go(3)
// 如果history记录不够,就会失败
router.go(-100)
router.go(100)