-
-
Notifications
You must be signed in to change notification settings - Fork 5.1k
/
app.js
103 lines (92 loc) · 2.87 KB
/
app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const Home = { template: '<div class="home">home</div>' }
const Foo = { template: '<div class="foo">foo</div>' }
const Bar = {
template: `
<div class="bar">
bar
<div style="height:1500px"></div>
<p id="anchor" style="height:500px">Anchor</p>
<p id="anchor2" style="height:500px">Anchor2</p>
<p id="1number">with number</p>
</div>
`
}
// scrollBehavior:
// - only available in html5 history mode
// - defaults to no scroll behavior
// - return false to prevent scroll
const scrollBehavior = function (to, from, savedPosition) {
if (savedPosition) {
// savedPosition is only available for popstate navigations.
return savedPosition
} else {
const position = {}
// scroll to anchor by returning the selector
if (to.hash) {
position.selector = to.hash
// specify offset of the element
if (to.hash === '#anchor2') {
position.offset = { y: 100 }
}
// bypass #1number check
if (/^#\d/.test(to.hash) || document.querySelector(to.hash)) {
return position
}
// if the returned position is falsy or an empty object,
// will retain current scroll position.
return false
}
return new Promise(resolve => {
// check if any matched route config has meta that requires scrolling to top
if (to.matched.some(m => m.meta.scrollToTop)) {
// coords will be used if no selector is provided,
// or if the selector didn't match any element.
position.x = 0
position.y = 0
}
// wait for the out transition to complete (if necessary)
this.app.$root.$once('triggerScroll', () => {
// if the resolved position is falsy or an empty object,
// will retain current scroll position.
resolve(position)
})
})
}
}
const router = new VueRouter({
mode: 'history',
base: __dirname,
scrollBehavior,
routes: [
{ path: '/', component: Home, meta: { scrollToTop: true }},
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar, meta: { scrollToTop: true }}
]
})
new Vue({
router,
template: `
<div id="app">
<h1>Scroll Behavior</h1>
<ul>
<li><router-link to="/">/</router-link></li>
<li><router-link to="/foo">/foo</router-link></li>
<li><router-link to="/bar">/bar</router-link></li>
<li><router-link to="/bar#anchor">/bar#anchor</router-link></li>
<li><router-link to="/bar#anchor2">/bar#anchor2</router-link></li>
<li><router-link to="/bar#1number">/bar#1number</router-link></li>
</ul>
<transition name="fade" mode="out-in" @after-leave="afterLeave">
<router-view class="view"></router-view>
</transition>
</div>
`,
methods: {
afterLeave () {
this.$root.$emit('triggerScroll')
}
}
}).$mount('#app')