router锚点和html锚点,hash模式下Vue-router页面返回锚点(scroll behavior)实现

在普通页面中,点击浏览器的返回按钮,在返回到上一页时会处在上次浏览的位置。单页面应用中,由于始终是同一个页面, 因此需要自行实现页面返回时的锚点。Vue-router的Scroll Behavior可以用于解决这个问题,但是只能应用在HTML5 history模式。本文实现了在hash模式下的锚点跳转。

锚点位置存储

Vue-router要求在HTML5 history模式下,是为了使用pushState、replaceState API以及popstate事件:

1

2

3

4

5

6

7

8

9// Vue-router中的push方法

push (location: RawLocation, onComplete?: Function, onAbort?: Function) {

const { current: fromRoute } = this

this.transitionTo(location, route => {

pushState(cleanPath(this.base + route.fullPath))// 存储页面锚点位置

handleScroll(this.router, route, fromRoute, false)

onComplete && onComplete(route)

}, onAbort)

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17// pushState方法

export function pushState (url?: string, replace?: boolean){

saveScrollPosition()

// try...catch the pushState call to get around Safari

// DOM Exception 18 where it limits to 100 pushState calls

const history = window.history

try {

if (replace) {

history.replaceState({ key: _key }, '', url)

} else {

_key = genKey()

history.pushState({ key: _key }, '', url)

}

} catch (e) {

window.location[replace ? 'replace' : 'assign'](url)

}

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16export function setupScroll (){

window.addEventListener('popstate', e => {

saveScrollPosition();

if (e.state && e.state.key) {

setStateKey(e.state.key);

}

})

}

window.addEventListener('popstate', e => {

this.transitionTo(getLocation(this.base), route => {

if (expectScroll) {

handleScroll(router, route, this.current, true)

}

})

})

在hash模式下需要我们自己记录锚点位置。可以维护一个与history相同的数组,每次页面跳转时在Vue-router提供的钩子函数中遍历数组,存储锚点位置。

锚点滚动

Vue-router本身提供了scrollBehavior方法,用来进行锚点跳转。但是该方法只能用在HTML5 history模式下。研究了一下其源码:vue-router/src/util/scroll.js,发现也是使用window.scrollTo()来进行页面的滚动。重要的是设置滚动的时机,应当在下一个页面绘制完成后进行跳转(wait until re-render finishes before scrolling)。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24// wait until re-render finishes before scrolling

router.app.$nextTick(() => {

let position = getScrollPosition();

const shouldScroll = behavior(to, from, isPop ? position : null);

if (!shouldScroll) {

return;

}

const isObject = typeof shouldScroll === 'object';

if (isObject && typeof shouldScroll.selector === 'string') {

const el = document.querySelector(shouldScroll.selector);

if (el) {

position = getElementPosition(el);

} else if (isValidPosition(shouldScroll)) {

position = normalizePosition(shouldScroll);

}

}

else if (isObject && isValidPosition(shouldScroll)) {

position = normalizePosition(shouldScroll);

}

if (position) {

window.scrollTo(position.x, position.y);

}

})

我们目前已经自行记录了锚点,因此可以在router中模仿一个跳转过程:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16router.beforeEach((to, from, next) => {

next();

// 重要的是设置跳转的时机。过早的话页面还没加载完成,高度不够导致不能滚动。过晚的话会造成页面的闪烁。

router.app.$nextTick(() => {

// 获取history数组中的最后一个browserHistoryLast

if (to.fullPath === browserHistoryLast.path

&& browserHistoryLast.pos) {

document.body.scrollTop = browserHistoryLast.pos;

}

else {

document.body.scrollTop = 0;

}

});

});

在router的钩子函数中,调用next之后,在$nextTick中进行页面的滚动,即可达到和scrollBehavior相似的效果。

需要注意的是,各个页面的数据应当存储在vuex中,不能每次进入页面都发送请求(即使不锚点也应当这么做)。否侧因为返回时页面还在请求数据,不能达到锚点的效果。

关于过场动画

如果页面跳转有过场动画存在,非常容易在锚点滚动时发生闪烁。尝试了几种方式,都没能达到很好效果。

尝试过的方法的思路在这里记录一下,这些方法都会有很大的抖动闪烁,根本原因还是页面跳转的时机不对:

返回到有存储pos的旧页面时,在onTransitionAfterEnter中将页面滚动到记录的位置。打开新页面时,在onTransitionBeforeStart中将页面滚动设置为0,确保新页面在顶部。

vue-router的过渡动画使用的是absolute定位+transform。因此尝试了给页面设置top值来消除闪烁。在跳转前给当前页面设置与目标页面滚动位置相同的top值,在滚动结束后由于不再是absolute定位,top值不再生效,没有闪烁发生。在返回时,列表页会首先绝对定位到首页要滚动的位置(此时会有闪烁),之后直接跳转到首页。闪烁集中在返回过渡效果之前。

其他问题全局mixin中不能写组件中的过渡钩子,如beforeRouteEnter等,会报错。

computed只有在vuex中的变量变化时,才会进行更新。import进来的值不行。

在onTransitionBeforeStart修改变量,不会使from页面中的computed更新。如果想要在页面跳转时更新from页面的computed,需要在router的钩子函数中进行修改,在this.$nextTick中调用next()。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/426352.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医疗:OA(6)

办公自动化(Office Automation,简称OA),是将计算机、通信等现代化技术运用到传统办公方式,进而形成的一种新型办公方式。办公自动化利用现代化设备和信息化技术,代替办公人员传统的部分手动或重复性业务活动…

高中计算机教师招聘试题,中小学信息技术教师招聘考试真题及答案.doc

中小学信息技术教师招聘考试真题及答案一、选择题(60个)1、网页都是按照一种描述文档的标记规则编写而成的,这套标记规则叫做:CA、URLB、HTTPC、HTMLD、FTP2、Basic语言属于:CA、机器语言B、汇编语言C、高级语言D、低级语言3、下列哪一个控件…

项目管理(3):备战pmp

1组织结构与项目管理 2职能型组织的优缺点 优点 简单对专家更易于管理,管理更具灵活性只向一个上司汇报项目人员有“家”——他们在部门里工作,部门给予相应的技术支持员工可以不断得到提高缺点 项目经理没有足够的权力没有明确的责任人客户可能找不到专…

【leetcode】16 3Sum Closest

描述 给定一个数字集合 S 以及一个数字 target,需要从集合中找出3个数字的和与这个 target的值最接近(绝对值最小) 样例 Input: S [-1, 2, 1, -4], target 1Output: 2 思路 首先排序,之后确定一个数字的前提下,再利用…

计算机组装维护教学总结,计算机组装与维护教学总结.doc

计算机组装与维护教学总结《计算机组装与维修》教学总结《计算机组装与维修》是职业学校计算机应用专业的一门主干专业课程.本课程是实践性较强的理论课程,其主要任务是使学生了解计算机各部件的分类、性能、选购方法,理解各主要部件的硬件结构、相互联系和作用,使学生掌握计算…

项目管理(4):备战pmp

1单个项目管理过程 如何实现项目管理? 通过“过程”processes实现 大多数情况下,大多数项目都有共同的项目管理过程 项目管理知识提供的是good practice 应用这些过程能大大提高项目成功的机会 项目经理与项目团队的责任 确定哪些过程适用于具体给…

HTML第七章总结

Getting started with CSS 前言 CSS 的 rule 作者做了一个非常形象的比喻,将 CSS 必做 renovate the house,在这里,CSS 包括了三个部分: Selector:the location of the HTML elementProperty:properties in that locationStyle:li…

项目管理(5):备战pmp

1项目干系人 Stakeholder 积极参与项目,或其利益因项目的实施或完成而受到积极或消极影响的个人或组织 他们会对项目的目标和结果施加影响 项目管理需要 识别项目干系人 确定各项目干系人的要求、期望、能发挥的作用 对其影响力尽量加以管理 如果有分歧怎么办…

js操作css样式

Div.style.width”100px"在div标签内我们添加了一个style属性,并设定了width值,这种写法会给标签带来大量的style属性,跟实际项目是不服的 获取css样式的方法:window.getComputedStyle()获取经过计算机计算的所有属性&#x…

html表白照片墙,【原创】【申精】用python去告白 绘制照片墙(自定义格式)

[Python] 纯文本查看 复制代码# -*- coding: utf-8 -*-from PIL import Imageimport os, syssave_image_name "New.png"raw_name "raw.bmp"res_file ".\\res" # 资源照片路径mw 100 # 单个照片的尺寸def load_raw(raw_name, data_list, _siz…

项目管理(6):备战pmp

项目整体管理 定义: 识别、定义、结合、统一与协调项目管理过程组中的各个过程以及项目管理活动 在各个相互冲突的目标与方案之间权衡取舍 在项目管理中发挥明显的重要作用 Eg:应急计划的成本估算成本管理时间管理风险管理 基本任务: …

使用offsetof对结构体指针偏移操作

题目来自于COMP20003 Tutorial 2: Program m ing Challenge 2.2 The technology stack at Hidebound Inc. uses a subset of C w hich doesnt have the . or ->operators, as the higher-ups heard shortcuts like this w ere useful in an activity called &quo…

项目管理(7):备战pmp

1.2制定项目初步范围说明书 项目范围说明书(初步) 目的: 登记项目及其产品和服务的特征与边界,以及验收与范围控制的方法 内容: 项目与产品的目标 产品或服务的要求与特性 产品验收标准 项目边界 项目要求与可…

旅馆客未满 计算机术语,前厅测试题

《前厅服务》单元测试一一、单项选择题(每题1分,共50分)1、按照人类生产、生活、社会实践活动领域的不同,道德可划分为三个组成部分,其中不包括()。A、职业道德B、家庭美德C、社会良知D、社会公德2、职业道德是人们在长期的职业活动中形成的(…

2018 java蓝桥杯校赛题目

1.【问题描述】 100 可以表示为带分数的形式:100 3 69258 / 714还可以表示为:100 82 3546 / 197注意特征:带分数中,数字1~9分别出现且只出现一次(不包含0)。类似这样的带分数,100 有 11 种表…

计算机操作系统(7):进程的基本概念

2.1 进程的基本概念 程序的顺序执行及其特征程序的并发执行及其特征进程的特征与状态进程控制块 2.1.1 程序的顺序执行及其特征 顺序执行包含两层含义: 在单道批处理系统中,对于多个用户程序来说,所有程序是依次执行的。(外部顺序性) 对…

无法打开计算机上的event log服务,Win7系统下启用Windows event log服务发生4201错误的正确解决方法...

Windows event log服务会把程序与系统发送的错误消息记录在日志中,其中还包含了部分有用的诊断信息,近期有Win7用户在启用windows event log服务的时候,发生4201错误提示框。那么该如何解决该问题?下面装机之家分享一下Win7系统下…

广义线性模型的计算机应用技术学院,SPSS数据分析—广义线性模型

我们前面介绍的一般线性模型、Logistic回归模型、对数线性模型、Poisson回归模型等,实际上均属于广义线性模型的范畴,广义线性模型包含的范围非常广泛,原因在于其对于因变量、因变量的概率分布等条件的限制放宽,使其应用范围加大。…

没有时间

请理解时间是运动的表现 转载于:https://www.cnblogs.com/eiya/p/10053311.html

中国第一个计算机病毒什么时候,新中国成立以来的第一例电脑病毒小球病毒是在1988年发现...

扩展阅读:1988年,随着软件交流,石头和小球病毒跟随软盘悄悄地通过香港和美国进入了中国内地,并在人们的懵懂之间在大型企业和研究所间广为传播。小球病毒是国内发现的第一个计算机病毒。发作条件是当系统时钟处于半点或整点&#…