diff --git a/examples/scroll-behavior/app.js b/examples/scroll-behavior/app.js
index 81a539f0c..afdccb049 100644
--- a/examples/scroll-behavior/app.js
+++ b/examples/scroll-behavior/app.js
@@ -37,7 +37,8 @@ const scrollBehavior = function (to, from, savedPosition) {
position.offset = { y: 100 }
}
- if (document.querySelector(to.hash)) {
+ // bypass #1number check
+ if (/^#\d/.test(to.hash) || document.querySelector(to.hash)) {
return position
}
@@ -87,6 +88,7 @@ new Vue({
/bar
/bar#anchor
/bar#anchor2
+ /bar#1number
diff --git a/src/util/scroll.js b/src/util/scroll.js
index ec949c062..1d444f3ec 100644
--- a/src/util/scroll.js
+++ b/src/util/scroll.js
@@ -45,20 +45,27 @@ export function handleScroll (
// wait until re-render finishes before scrolling
router.app.$nextTick(() => {
const position = getScrollPosition()
- const shouldScroll = behavior.call(router, to, from, isPop ? position : null)
+ const shouldScroll = behavior.call(
+ router,
+ to,
+ from,
+ isPop ? position : null
+ )
if (!shouldScroll) {
return
}
if (typeof shouldScroll.then === 'function') {
- shouldScroll.then(shouldScroll => {
- scrollToPosition((shouldScroll: any), position)
- }).catch(err => {
- if (process.env.NODE_ENV !== 'production') {
- assert(false, err.toString())
- }
- })
+ shouldScroll
+ .then(shouldScroll => {
+ scrollToPosition((shouldScroll: any), position)
+ })
+ .catch(err => {
+ if (process.env.NODE_ENV !== 'production') {
+ assert(false, err.toString())
+ }
+ })
} else {
scrollToPosition(shouldScroll, position)
}
@@ -114,12 +121,22 @@ function isNumber (v: any): boolean {
return typeof v === 'number'
}
+const hashStartsWithNumberRE = /^#\d/
+
function scrollToPosition (shouldScroll, position) {
const isObject = typeof shouldScroll === 'object'
if (isObject && typeof shouldScroll.selector === 'string') {
- const el = document.querySelector(shouldScroll.selector)
+ // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
+ // but at the same time, it doesn't make much sense to select an element with an id and an extra selector
+ const el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
+ ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
+ : document.querySelector(shouldScroll.selector)
+
if (el) {
- let offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {}
+ let offset =
+ shouldScroll.offset && typeof shouldScroll.offset === 'object'
+ ? shouldScroll.offset
+ : {}
offset = normalizeOffset(offset)
position = getElementPosition(el, offset)
} else if (isValidPosition(shouldScroll)) {
diff --git a/test/e2e/specs/scroll-behavior.js b/test/e2e/specs/scroll-behavior.js
index 9ececb493..6cc371fee 100644
--- a/test/e2e/specs/scroll-behavior.js
+++ b/test/e2e/specs/scroll-behavior.js
@@ -11,7 +11,7 @@ module.exports = {
browser
.url('http://localhost:8080/scroll-behavior/')
.waitForElementVisible('#app', 1000)
- .assert.count('li a', 5)
+ .assert.count('li a', 6)
.assert.containsText('.view', 'home')
.execute(function () {
@@ -117,6 +117,16 @@ module.exports = {
null,
'scroll to anchor with offset'
)
+ .execute(function () {
+ document.querySelector('li:nth-child(6) a').click()
+ })
+ .assert.evaluate(
+ function () {
+ return document.getElementById('1number').getBoundingClientRect().top < 1
+ },
+ null,
+ 'scroll to anchor that starts with number'
+ )
.end()
}
}