本文共 10802 字,大约阅读时间需要 36 分钟。
https://www.icketang.com/static/img/banner_news.jpg?num=10&color=red#title
协议 https://
域名 www.baidu.com
端口号 :443
路径 /static/img/
搜索词 ?num=10&color=red
哈希 #title
前三个部分的改变会导致跨域的问题。
前五个部分的改变会导致浏览器端向服务器端发送新的请求。
只有hash的改变不会导致浏览器端向服务器端发送新的请求。
浏览器不发出请求,也就不会刷新页面。每次 hash 值的变化,会触发hashchange
这个事件,通过这个事件我们就可以知道 hash 值发生了哪些变化。然后我们便可以监听hashchange
来实现更新页面部分内容的操作:
// 监听路由变化window.addEventListener('hashchange', router)// 路由方法function router() { // console.log(location.hash) // 截取组件的名称 let page = location.hash.slice(2); // 更新页面 app.page = page;}// 页面加载完成执行router();
因为HTML5标准发布,多了两个 API,pushState()
和 replaceState()。
通过这两个 API (1)可以改变 url 地址且不会发送请求,(2)不仅可以读取历史记录栈,还可以对浏览器历史记录栈进行修改。
除此之外,还有popState().当浏览器跳转到新的状态时,将触发popState事件.
修改历史状态
包括了pushState
,replaceState
两个方法,这两个方法接收三个参数:stateObj,title,url
window.history.pushState(stateObject, title, URL)window.history.replaceState(stateObject, title, URL)
切换历史状态
包括back
,forward
,go
三个方法,对应浏览器的前进forward,后退back,跳转go操作。 有同学说了,(谷歌)浏览器只有前进和后退,没有跳转,嗯,在前进后退上长按鼠标,会出来所有当前窗口的历史记录,从而可以跳转(也许叫跳更合适):
history.go(-2);//后退两次
history.go(2);//前进两次
history.back(); //后退
hsitory.forward(); //前进
区别:
当用户刷新页面之类的操作时,浏览器会给服务器发送请求,所以这个实现需要服务器的支持,需要把所有路由都重定向到根页面。
history模式怕啥
不怕前进,不怕后退,就怕刷新,(如果后端没有准备的话),因为刷新是实实在在地去请求服务器的。在history模式下,你可以自由的修改path。history模式最终的路由都体现在url的pathname中,这部分是会传到服务器端的,因此需要服务端对每一个可能的path值都作相应的映射。
当刷新时,如果服务器中没有相应的响应或者资源,会分分钟刷出一个404来。
使用路由共分六步:
第一步 在模块化开发中,通过use方法安装路由
第二步 定义路由渲染位置。
通过router-view组件
第三步 定义页面组件。
路由简化了组件的定义
只需要定义extend参数对象集合
第四步 定义路由规则:
路由规则是一个数组,每一个成员代表一条规则,是一个对象:
path 定义规则,类似express中的路由规则
用/切割路径,默认是静态路由
静态路由:是一个一对一的路由规则
例如 /home/ickt 只对应 /home/ickt
在名称的前面,添加:就是一个动态路由规则了
动态路由:是一个一对多的路由规则,
例如 /list/:page
匹配 /list/10 /list/100 /list/abc
不匹配 /list /list/10/20 /detail/10
component 渲染的组件对象
name 组件名称
...
第五步 实例化路由,并传递路由规则:routes
第六步 在vue实例化对象中,注册路由,通过router属性。
默认路由
当没有匹配到路径,希望渲染默认页面的时候,可以使用默认路由。
直接将path匹配*即可。
路由重定向
当我们输入一个地址,想渲染另外一个页面。此时可以使用路由重定向技术。
通过path匹配地址
通过redirect属性配置重定向的地址。
// 引入vueimport Vue from 'vue';// 引入路由import Router from 'vue-router';// 1 安装路由Vue.use(Router);// 3 定义组件let Home = { template: 'header
home page
' }let List = { template: 'list page
' }let Detail = { template: 'detail page
' }// 4 定义规则let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home, name: 'home' }, // 列表页 { path: '/list/:page', component: List, name: 'list' }, // 详情页 { path: '/detail/:id', component: Detail, name: 'detail' }, // 路由重定向 { path: '/ickt', redirect: '/detail/ickt' }, // 默认路由 { path: '*', component: Home }];// 5 实例化路由 将规则传递进来let router = new Router({ routes })// 实例化let app = new Vue({ // 6 注册路由 router, // 视图 el: '#app', // 数据 data: {}})
我们在vue实例化对象中,注册了router,此时所有的组件都会继承两个属性:$router, $route
添加给组件实例化对象自身,并设置了特性,所以即可在模板中使用,也可以在组件中使用。
$router 代表路由实例化对象,管理路由,提供了一些操作路由的方法:
$route 存路由信息
fullPath 完整路径
hash 路由上的的hash(hash路由中url上第二个#后面的)
path 路径
query search数据(被解析成了对象)
params 动态路由数据(被解析成了对象)
我们在定义路由规则的时候,
可以设置props属性,可以为渲染的组件,传递属性数据
此时组件要通过props属性接收数据
props: true 将动态路由数据直接传递给组件,
props: fn
函数参数是route对象
返回值对象中的属性会传递给组件。
let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home}, // 列表页 { path: '/list/:page', component: List, // 函数传递多个属性 props(route) { // console.log(arguments) return { id: route.params.itemId, articleTitle: route.query.draft } } } ];
跳转到ist页面时:
this.$router.push({ path: "/article/" + id, query: { articleTitle: "文章1" }})
在list页面组件上接收参数:
props: { id: String, articleTitle: String}
在页面的某个区域切换子页面,我们可以使用子路由。
使用子路由分成两步
第一步 定义子路由的渲染位置
在父路由模板中,通过router-view来定义
第二步 在路由规则中,我们通过children属性定义子路由配置
是一个数组,每一个成员代表是一个子路由配置对象,
可以配置:path, component, name, redirect, props, children ...
path可以是绝对路径,也可以是相对路径
如果是绝对路径:以/开头的
完整路径:子路由路径
如果是相对路径:不是以/开头的
完整路径:父路由路径+子路由路径
// 引入vueimport Vue from 'vue';// 引入路由import Router from 'vue-router';// 1 安装路由Vue.use(Router);// 3 定义组件let Home = { template: 'header
home page
' }let List = { template: '' }let Detail = { template: 'list page
detail page
' }//子路由页面let Nav = { template: 'nav page
' }// 4 定义规则let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home, name: 'home' }, // 列表页 { path: '/list/:page', component: List, name: 'list' }, // 详情页 { path: '/detail/:id', component: Detail, name: 'detail' //定义子路由 children:[ //绝对路径 {path:"/demo",componet:Nav} //相对路径 {path:"/demo/:nav", componet:nav} ] }, ];// 5 实例化路由 将规则传递进来let router = new Router({ routes })// 实例化let app = new Vue({ // 6 注册路由 router, // 视图 el: '#app', // 数据 data: {}})
我们通过mode属性定义路由模块
默认是hash路由,
我们可以设置成history路由(基于path切换页面的)
这种模式需要服务器端的配置
我们在实例化路由的时候,配置路由模式
我们在切换页面的时候,可以设置滚动条位置
通过scrollbehavior方法设置滚动条位置
第一个参数表示当前路数据由对象
第二个按时表示上一个路由数据对象
第三个参数表示当前滚动条位置
返回值就是设置的滚动条位置
x 代表水平方向滚动条位置
y 代表垂直方向滚动条位置
// 5 实例化路由let router = new Router({ routes, // 路由模式 // mode: 'history', // 设置滚动条位置 获取跳转跳转新页面时的位置 // scrollBehavior() { // // console.log(arguments) // return { // x: 0, // y: 200 // } // }})
路由导航是用来切换路由的。
html中切换页面通过a标签的href属性
js中切换页面通过location对象
为了简化页面的切换,vue提供了路由导航组件:router-link。
to 必须的,用来设置地址,
即使是hash路由,不要加#
tag 用来设置渲染的元素
默认渲染成a标签
v-text 设置内容
是指令,属性值是js环境
内容还可以直接写在组件内
// 引入vueimport Vue from 'vue';// 引入路由import Router from 'vue-router';// 引入样式import './demo.scss';// 1 安装路由Vue.use(Router);// 4 定义规则let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home, name: 'home' }, // 列表页 { path: '/list/:page', component: List, name: 'list', }, // 详情页 { path: '/detail/:id', component: Detail, name: 'detail', }, ];// 5 实例化路由let router = new Router({ routes,})// 实例化let app = new Vue({ // 6 注册路由 router, // 视图 el: '#app', // 数据 data: {}})home list
路由过渡允许我们在切换页面的时候,添加过渡动画,
使用方式跟以前使用过渡的方式是一样的。
通过transition组件使用,通过name属性定义过渡名称。
我们可以使用mode属性设置过渡模式
例如:out-in模式
// 引入vueimport Vue from 'vue';// 引入路由import Router from 'vue-router';// 引入样式import './demo.scss';// 1 安装路由Vue.use(Router);// 3 定义组件let Home = { template: 'home page
' }let List = { template: 'list page
' }let Detail = { template: 'detail page
' }// 4 定义规则let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home, name: 'home' }, // 列表页 { path: '/list/:page', component: List, name: 'list', }, // 详情页 { path: '/detail/:id', component: Detail, name: 'detail', }, ];// 5 实例化路由let router = new Router({ routes,})// 实例化let app = new Vue({ // 6 注册路由 router, // 视图 el: '#app', // 数据 data: {}})
为了保证watch长期有效,我们可以使用keep-alive组件。
// 引入vueimport Vue from 'vue';// 引入路由import Router from 'vue-router';// 1 安装路由Vue.use(Router);// 3 定义组件let Home = { template: ' home page
' }let List = { // 接收属性数据 props: [ 'page', 'color', 'num' ], template: ``, // 局部路由守卫 to: Route:即将要进入的目标 路由对象 from: Route: 当前导航正要离开的路由 // beforeRouteEnter(route, oldRoute, next) { // console.log(arguments); // // next方法必须执行 // next(); // }, // watch监听器监听路由变化 watch: { $route() { console.log(arguments) } }, // 组件创建完成 created() { console.log(this, this.$route) }}let Detail = { template: `list page
}// 4 定义规则let routes = [ // 每一个成员代表一条规则 { path: '/home', component: Home, name: 'home' }, // 列表页 { path: '/list/:page', component: List, name: 'list', }, // 详情页 { path: '/detail/:id', component: Detail, name: 'detail', } ];// 5 实例化路由let router = new Router({ routes, })// 全局路由守卫// router.afterEach((...arg) => console.log(arg))// router.beforeEach((route, oldRoute, next) => {// console.log(route, oldRoute, next)// // next方法必须执行,否则看不到新的页面// next();// })// 实例化let app = new Vue({ // 6 注册路由 router, // 视图 el: '#app', // 数据 data: {}})console.log(Vue.version)detail page
vue-router有哪几种导航钩子( 导航守卫 )?
1、全局守卫: router.beforeEach
2、全局解析守卫: router.beforeResolve
3、全局后置钩子: router.afterEach
4、路由独享的守卫: beforeEnter
5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave
导航表示路由正在发生改变,vue-router 提供的导航守卫主要用来:通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。
注意:参数或查询的改变并不会触发进入/离开的导航守卫。 你可以通过 观察 $route 对象 来应对这些变化,或使用 beforeRouteUpdate的组件内守卫。
1、全局守卫:
const router = new VueRouter({ ... }) router.beforeEach((to, from, next) => { // ...})
当一个导航触发时,全局前置守卫
按照创建顺序调用。守卫是异步解析执行,此时导航在所有守卫 resolve 完之前
一直处于等待中
。
每个守卫方法接收三个参数:
to: Route:
即将要进入的目标 路由对象
from: Route:
当前导航正要离开的路由
next: Function:
一定要调用该方法来resolve
这个钩子。执行效果依赖 next 方法的调用参数。
next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是confirmed (确认的)。
next(false): 中断当前的导航。如果浏览器的 URL 改变了 (可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
next(’/’) 或者 next({ path: ‘/’ }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。你可以向 next 传递任意位置对象,且允许设置诸如 replace: true、name: ‘home’ 之类的选项以及任何用在router-link的 to prop或 router.push中的选项。
next(error): (2.4.0+) 如果传入 next 的参数是一个 Error 实例,则导航会被终止且该错误会被传递给 router.onError()注册过的回调。
确保要调用 next方法,否则钩子就不会被 resolved
2、全局解析守卫:
在 2.5.0+ 你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,区别是:在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。
3、全局后置钩子
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身: router.afterEach((to, from) => { // ...})
4、路由独享的守卫
const router = new VueRouter({ routes: [ { path: '/foo', component: Foo, beforeEnter: (to, from, next) => { // ... } } ]})
这些守卫与全局前置守卫的方法参数是一样的。
5、组件内的守卫
beforeRouteUpdate (2.2 新增)
beforeRouteLeave
const Foo = { template: `...`, beforeRouteEnter (to, from, next) { // 在渲染该组件的对应路由被 confirm 前调用 // 不!能!获取组件实例 `this` // 因为当守卫执行前,组件实例还没被创建 }, //不过,你可以通过传一个回调给 next来访问组件实例。 //在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数。 beforeRouteEnter (to, from, next) { next(vm => { // 通过 `vm` 访问组件实例 }) }, beforeRouteUpdate (to, from, next) { // 在当前路由改变,但是该组件被复用时调用 // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候, // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。 // 可以访问组件实例 `this` }, beforeRouteLeave (to, from, next) { // 导航离开该组件的对应路由时调用 // 可以访问组件实例 `this` }}
注意:beforeRouteEnter 是支持给next 传递回调的唯一守卫。对于beforeRouteUpdate 和 beforeRouteLeave 来说,this 已经可用了,所以不支持传递回调,因为没有必要了:
beforeRouteUpdate (to, from, next) { // just use `this` this.name = to.params.name next()}
离开守卫beforeRouteLeave:通常用来禁止用户在还未保存修改前突然离开。该导航可以通过 next(false) 来取消:
beforeRouteLeave (to, from , next) { const answer = window.confirm('Do you really want to leave? you have unsaved changes!') if (answer) { next() } else { next(false) }}
转载地址:http://klven.baihongyu.com/