Skip to content

Commit 799ceca

Browse files
committedJul 8, 2019
feat(scroll): handle id selectors starting with a number
Closes #2163
1 parent 8df4123 commit 799ceca

File tree

3 files changed

+41
-12
lines changed

3 files changed

+41
-12
lines changed
 

‎examples/scroll-behavior/app.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ const scrollBehavior = function (to, from, savedPosition) {
3737
position.offset = { y: 100 }
3838
}
3939

40-
if (document.querySelector(to.hash)) {
40+
// bypass #1number check
41+
if (/^#\d/.test(to.hash) || document.querySelector(to.hash)) {
4142
return position
4243
}
4344

@@ -87,6 +88,7 @@ new Vue({
8788
<li><router-link to="/bar">/bar</router-link></li>
8889
<li><router-link to="/bar#anchor">/bar#anchor</router-link></li>
8990
<li><router-link to="/bar#anchor2">/bar#anchor2</router-link></li>
91+
<li><router-link to="/bar#1number">/bar#1number</router-link></li>
9092
</ul>
9193
<transition name="fade" mode="out-in" @after-leave="afterLeave">
9294
<router-view class="view"></router-view>

‎src/util/scroll.js

+27-10
Original file line numberDiff line numberDiff line change
@@ -45,20 +45,27 @@ export function handleScroll (
4545
// wait until re-render finishes before scrolling
4646
router.app.$nextTick(() => {
4747
const position = getScrollPosition()
48-
const shouldScroll = behavior.call(router, to, from, isPop ? position : null)
48+
const shouldScroll = behavior.call(
49+
router,
50+
to,
51+
from,
52+
isPop ? position : null
53+
)
4954

5055
if (!shouldScroll) {
5156
return
5257
}
5358

5459
if (typeof shouldScroll.then === 'function') {
55-
shouldScroll.then(shouldScroll => {
56-
scrollToPosition((shouldScroll: any), position)
57-
}).catch(err => {
58-
if (process.env.NODE_ENV !== 'production') {
59-
assert(false, err.toString())
60-
}
61-
})
60+
shouldScroll
61+
.then(shouldScroll => {
62+
scrollToPosition((shouldScroll: any), position)
63+
})
64+
.catch(err => {
65+
if (process.env.NODE_ENV !== 'production') {
66+
assert(false, err.toString())
67+
}
68+
})
6269
} else {
6370
scrollToPosition(shouldScroll, position)
6471
}
@@ -114,12 +121,22 @@ function isNumber (v: any): boolean {
114121
return typeof v === 'number'
115122
}
116123

124+
const hashStartsWithNumberRE = /^#\d/
125+
117126
function scrollToPosition (shouldScroll, position) {
118127
const isObject = typeof shouldScroll === 'object'
119128
if (isObject && typeof shouldScroll.selector === 'string') {
120-
const el = document.querySelector(shouldScroll.selector)
129+
// getElementById would still fail if the selector contains a more complicated query like #main[data-attr]
130+
// but at the same time, it doesn't make much sense to select an element with an id and an extra selector
131+
const el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line
132+
? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line
133+
: document.querySelector(shouldScroll.selector)
134+
121135
if (el) {
122-
let offset = shouldScroll.offset && typeof shouldScroll.offset === 'object' ? shouldScroll.offset : {}
136+
let offset =
137+
shouldScroll.offset && typeof shouldScroll.offset === 'object'
138+
? shouldScroll.offset
139+
: {}
123140
offset = normalizeOffset(offset)
124141
position = getElementPosition(el, offset)
125142
} else if (isValidPosition(shouldScroll)) {

‎test/e2e/specs/scroll-behavior.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ module.exports = {
1111
browser
1212
.url('http://localhost:8080/scroll-behavior/')
1313
.waitForElementVisible('#app', 1000)
14-
.assert.count('li a', 5)
14+
.assert.count('li a', 6)
1515
.assert.containsText('.view', 'home')
1616

1717
.execute(function () {
@@ -117,6 +117,16 @@ module.exports = {
117117
null,
118118
'scroll to anchor with offset'
119119
)
120+
.execute(function () {
121+
document.querySelector('li:nth-child(6) a').click()
122+
})
123+
.assert.evaluate(
124+
function () {
125+
return document.getElementById('1number').getBoundingClientRect().top < 1
126+
},
127+
null,
128+
'scroll to anchor that starts with number'
129+
)
120130
.end()
121131
}
122132
}

0 commit comments

Comments
 (0)