mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-30 09:27:13 +00:00
add custom scroll behavior example
This commit is contained in:
parent
d444f2a5b1
commit
a7ec4367f5
3
examples/custom-scroll-behavior/README.md
Normal file
3
examples/custom-scroll-behavior/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Custom scroll behavior with Nuxt.js
|
||||||
|
|
||||||
|
https://nuxtjs.org/examples/custom-scroll-behavior
|
54
examples/custom-scroll-behavior/assets/main.css
Normal file
54
examples/custom-scroll-behavior/assets/main.css
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
text-align: center;
|
||||||
|
/* padding-top: 200px; */
|
||||||
|
font-size: 20px;
|
||||||
|
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-enter-active, .page-leave-active {
|
||||||
|
transition: opacity .5s
|
||||||
|
}
|
||||||
|
.page-enter, .page-leave-active {
|
||||||
|
opacity: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
.bounce-enter-active {
|
||||||
|
animation: bounce-in .8s;
|
||||||
|
}
|
||||||
|
.bounce-leave-active {
|
||||||
|
animation: bounce-out .5s;
|
||||||
|
}
|
||||||
|
@keyframes bounce-in {
|
||||||
|
0% { transform: scale(0) }
|
||||||
|
50% { transform: scale(1.5) }
|
||||||
|
100% { transform: scale(1) }
|
||||||
|
}
|
||||||
|
@keyframes bounce-out {
|
||||||
|
0% { transform: scale(1) }
|
||||||
|
50% { transform: scale(1.5) }
|
||||||
|
100% { transform: scale(0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
.slide-left-enter,
|
||||||
|
.slide-right-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate(30px, 0);
|
||||||
|
}
|
||||||
|
.slide-left-leave-active,
|
||||||
|
.slide-right-enter {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate(-30px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter,
|
||||||
|
.fade-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.fade-leave-active,
|
||||||
|
.fade-enter {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
64
examples/custom-scroll-behavior/nuxt.config.js
Normal file
64
examples/custom-scroll-behavior/nuxt.config.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
const scrollBehavior = function (to, from, savedPosition, ...args) {
|
||||||
|
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
|
||||||
|
|
||||||
|
if (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
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no children detected
|
||||||
|
if (to.matched.length < 2) {
|
||||||
|
// scroll to the top of the page
|
||||||
|
position.x = 0
|
||||||
|
position.y = 0
|
||||||
|
} else if (to.matched.some((r) => r.components.default.options.scrollToTop)) {
|
||||||
|
// if one of the children has scrollToTop option set to true
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
build: {
|
||||||
|
vendor: ['axios']
|
||||||
|
},
|
||||||
|
css: ['~/assets/main.css'],
|
||||||
|
transition: {
|
||||||
|
afterLeave() {
|
||||||
|
this.$root.$emit('triggerScroll')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
scrollBehavior
|
||||||
|
}
|
||||||
|
}
|
12
examples/custom-scroll-behavior/package.json
Normal file
12
examples/custom-scroll-behavior/package.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "nuxt-routes-transitions",
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^0.15.3",
|
||||||
|
"nuxt": "latest"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"dev": "nuxt",
|
||||||
|
"build": "nuxt build",
|
||||||
|
"start": "nuxt start"
|
||||||
|
}
|
||||||
|
}
|
12
examples/custom-scroll-behavior/pages/about.vue
Normal file
12
examples/custom-scroll-behavior/pages/about.vue
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>About page</h1>
|
||||||
|
<nuxt-link to="/">Home page</nuxt-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
transition: 'bounce'
|
||||||
|
}
|
||||||
|
</script>
|
9
examples/custom-scroll-behavior/pages/index.vue
Normal file
9
examples/custom-scroll-behavior/pages/index.vue
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Home page</h1>
|
||||||
|
<p><nuxt-link to="/about">About page</nuxt-link></p>
|
||||||
|
<p><nuxt-link to="/users">Lists of users</nuxt-link></p>
|
||||||
|
<p><nuxt-link to="/long">Long page</nuxt-link></p>
|
||||||
|
<div class="spacer" style="width: 100%; height: 1000px"></div>
|
||||||
|
</div>
|
||||||
|
</template>
|
22
examples/custom-scroll-behavior/pages/long.vue
Normal file
22
examples/custom-scroll-behavior/pages/long.vue
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Long page</h1>
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam neque turpis, tempor vitae accumsan eget, bibendum eget dui. Vestibulum fringilla mi ac nunc malesuada accumsan. Proin mattis, ex vitae rhoncus dapibus, tellus tortor tincidunt metus, sed scelerisque dolor nunc rhoncus enim. Pellentesque semper interdum quam in placerat. Sed ut finibus mi. Aliquam placerat tellus ac tincidunt sodales. Quisque pharetra neque a risus placerat, sed suscipit felis mattis. Maecenas pretium efficitur fringilla. Sed commodo leo congue velit pretium, in consequat ex egestas. Pellentesque gravida vitae elit varius condimentum. Fusce in magna tellus. Proin in odio ac est elementum pharetra.</p>
|
||||||
|
<p>Vivamus dapibus libero sem, eu sagittis lorem hendrerit id. Suspendisse faucibus sapien quis cursus lobortis. Phasellus blandit tellus at arcu ornare fermentum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi ac massa sollicitudin, lacinia lacus porta, cursus mi. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc aliquam quis elit ut maximus. Integer blandit ipsum sed elit laoreet consequat. Pellentesque quis volutpat tellus, vitae finibus nulla. Etiam a porta orci. Morbi at libero sit amet tortor eleifend congue. Integer egestas fermentum lacinia. Curabitur dignissim, enim eget consectetur tempor, lacus felis auctor ante, in egestas arcu turpis ut tellus. Phasellus mattis dictum leo, a gravida purus tristique sed. Pellentesque sollicitudin arcu eu augue vehicula, molestie hendrerit sapien mollis.</p>
|
||||||
|
<p>Nunc ullamcorper magna nunc, vitae vestibulum est laoreet vel. Aliquam erat volutpat. Duis vehicula ligula at justo egestas posuere. Mauris pharetra nulla ac pretium eleifend. Mauris purus eros, venenatis sollicitudin ornare id, mattis in lorem. Curabitur tortor magna, viverra eget lorem ultricies, aliquam aliquam libero. Maecenas vestibulum id libero sed fermentum. Praesent consequat dui sed pellentesque commodo. Curabitur finibus purus vel purus mattis luctus. Nullam maximus dapibus orci, ac mattis diam egestas vel. Praesent lorem dolor, congue quis gravida commodo, rhoncus nec justo. In et elementum augue. Donec fringilla imperdiet magna, quis luctus leo placerat sed. Morbi scelerisque in sem eu dapibus. Sed interdum, felis luctus semper viverra, ex lorem posuere velit, in bibendum nunc dolor et diam.</p>
|
||||||
|
<p>Duis pulvinar lorem vel tempus pellentesque. Vivamus imperdiet imperdiet augue, ac rhoncus velit vulputate eu. Sed sed nulla risus. Curabitur ut velit consectetur, semper velit quis, elementum tellus. Ut eget ligula eget leo porta vestibulum. Curabitur ligula magna, rutrum ut enim vitae, gravida sollicitudin augue. Aliquam auctor gravida mauris, nec feugiat ipsum mollis vel. Vivamus nec aliquet ipsum, id scelerisque nibh. Vestibulum iaculis eleifend nunc, vitae efficitur massa egestas et. Ut pulvinar, purus eget viverra sodales, est mauris luctus metus, non luctus tellus diam in elit.</p>
|
||||||
|
<p>Quisque sollicitudin non urna non consectetur. Cras quis dapibus nisi. Maecenas maximus rhoncus neque, a lacinia urna egestas nec. Morbi molestie odio sit amet tempus cursus. Vivamus lorem nunc, malesuada et maximus id, imperdiet eget felis. Ut elementum fringilla velit in mattis. Morbi ut laoreet mi. Aliquam et odio dignissim, fermentum purus sit amet, facilisis lorem. Donec semper mi ut semper tristique. Sed in dolor placerat, porta elit in, tempor felis. Integer metus erat, tristique efficitur quam quis, finibus blandit magna. Nunc sit amet lorem dui. Suspendisse ut vulputate nisi. Integer sit amet sollicitudin libero.</p>
|
||||||
|
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam neque turpis, tempor vitae accumsan eget, bibendum eget dui. Vestibulum fringilla mi ac nunc malesuada accumsan. Proin mattis, ex vitae rhoncus dapibus, tellus tortor tincidunt metus, sed scelerisque dolor nunc rhoncus enim. Pellentesque semper interdum quam in placerat. Sed ut finibus mi. Aliquam placerat tellus ac tincidunt sodales. Quisque pharetra neque a risus placerat, sed suscipit felis mattis. Maecenas pretium efficitur fringilla. Sed commodo leo congue velit pretium, in consequat ex egestas. Pellentesque gravida vitae elit varius condimentum. Fusce in magna tellus. Proin in odio ac est elementum pharetra.</p>
|
||||||
|
<p>Vivamus dapibus libero sem, eu sagittis lorem hendrerit id. Suspendisse faucibus sapien quis cursus lobortis. Phasellus blandit tellus at arcu ornare fermentum. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi ac massa sollicitudin, lacinia lacus porta, cursus mi. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc aliquam quis elit ut maximus. Integer blandit ipsum sed elit laoreet consequat. Pellentesque quis volutpat tellus, vitae finibus nulla. Etiam a porta orci. Morbi at libero sit amet tortor eleifend congue. Integer egestas fermentum lacinia. Curabitur dignissim, enim eget consectetur tempor, lacus felis auctor ante, in egestas arcu turpis ut tellus. Phasellus mattis dictum leo, a gravida purus tristique sed. Pellentesque sollicitudin arcu eu augue vehicula, molestie hendrerit sapien mollis.</p>
|
||||||
|
<p>Nunc ullamcorper magna nunc, vitae vestibulum est laoreet vel. Aliquam erat volutpat. Duis vehicula ligula at justo egestas posuere. Mauris pharetra nulla ac pretium eleifend. Mauris purus eros, venenatis sollicitudin ornare id, mattis in lorem. Curabitur tortor magna, viverra eget lorem ultricies, aliquam aliquam libero. Maecenas vestibulum id libero sed fermentum. Praesent consequat dui sed pellentesque commodo. Curabitur finibus purus vel purus mattis luctus. Nullam maximus dapibus orci, ac mattis diam egestas vel. Praesent lorem dolor, congue quis gravida commodo, rhoncus nec justo. In et elementum augue. Donec fringilla imperdiet magna, quis luctus leo placerat sed. Morbi scelerisque in sem eu dapibus. Sed interdum, felis luctus semper viverra, ex lorem posuere velit, in bibendum nunc dolor et diam.</p>
|
||||||
|
<p>Duis pulvinar lorem vel tempus pellentesque. Vivamus imperdiet imperdiet augue, ac rhoncus velit vulputate eu. Sed sed nulla risus. Curabitur ut velit consectetur, semper velit quis, elementum tellus. Ut eget ligula eget leo porta vestibulum. Curabitur ligula magna, rutrum ut enim vitae, gravida sollicitudin augue. Aliquam auctor gravida mauris, nec feugiat ipsum mollis vel. Vivamus nec aliquet ipsum, id scelerisque nibh. Vestibulum iaculis eleifend nunc, vitae efficitur massa egestas et. Ut pulvinar, purus eget viverra sodales, est mauris luctus metus, non luctus tellus diam in elit.</p>
|
||||||
|
<p>Quisque sollicitudin non urna non consectetur. Cras quis dapibus nisi. Maecenas maximus rhoncus neque, a lacinia urna egestas nec. Morbi molestie odio sit amet tempus cursus. Vivamus lorem nunc, malesuada et maximus id, imperdiet eget felis. Ut elementum fringilla velit in mattis. Morbi ut laoreet mi. Aliquam et odio dignissim, fermentum purus sit amet, facilisis lorem. Donec semper mi ut semper tristique. Sed in dolor placerat, porta elit in, tempor felis. Integer metus erat, tristique efficitur quam quis, finibus blandit magna. Nunc sit amet lorem dui. Suspendisse ut vulputate nisi. Integer sit amet sollicitudin libero.</p>
|
||||||
|
<nuxt-link to="/">Home page</nuxt-link>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
transition: 'fade'
|
||||||
|
}
|
||||||
|
</script>
|
76
examples/custom-scroll-behavior/pages/users.vue
Normal file
76
examples/custom-scroll-behavior/pages/users.vue
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<nuxt-link v-if="page > 1" :to="'?page=' + (page - 1)">< Prev</nuxt-link>
|
||||||
|
<a v-else class="disabled">< Prev</a>
|
||||||
|
<span>{{ page }}/{{ totalPages }}</span>
|
||||||
|
<nuxt-link v-if="page < totalPages" :to="'?page=' + (page + 1)">Next ></nuxt-link>
|
||||||
|
<a v-else class="disabled">Next ></a>
|
||||||
|
<ul>
|
||||||
|
<li v-for="user in users" :key="user.id">
|
||||||
|
<img :src="user.avatar" class="avatar" />
|
||||||
|
<span>{{ user.first_name }} {{ user.last_name }}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p><nuxt-link to="/">Back home</nuxt-link></p>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Watch for $route.query.page to call Component methods (asyncData, fetch, validate, layout, etc.)
|
||||||
|
watchQuery: ['page'],
|
||||||
|
// Key for <nuxt-child> (transitions)
|
||||||
|
key: (to) => to.fullPath,
|
||||||
|
// Called to know which transition to apply
|
||||||
|
transition(to, from) {
|
||||||
|
if (!from) return 'slide-left'
|
||||||
|
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
|
||||||
|
},
|
||||||
|
async asyncData({ query }) {
|
||||||
|
const page = +query.page || 1
|
||||||
|
const { data } = await axios.get(`https://reqres.in/api/users?page=${page}`)
|
||||||
|
return {
|
||||||
|
page: +data.page,
|
||||||
|
totalPages: data.total_pages,
|
||||||
|
users: data.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
a {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 0 1em;
|
||||||
|
color: #34495e;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
a.disabled {
|
||||||
|
color: #ccc;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
margin: auto;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 400px;
|
||||||
|
padding-top: 40px;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
list-style-type: none;
|
||||||
|
width: 400px;
|
||||||
|
border: 1px #ddd solid;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
li img {
|
||||||
|
float: left;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
li span {
|
||||||
|
display: inline-block;
|
||||||
|
padding-top: 40px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue
Block a user