主要思路經過自定義指令,在視圖初始化完成後,綁定scroll事件。當scrollTop + clientHeight >= scrollHeight時(此時滾定條到了底部)觸發loadMore事件,css
<template> <div class="index" v-scroll="loadMore"> <!-- 列表數據傳遞給子組件,loading表示是否正在加載數據,避免在請求時屢次觸發 --> <my-item :lists="lists" :loading="loading" /> </div> </template> <script> import MyItem from '~/components/Item.vue' export default { name: 'Index', created () { // 初始化數據 this.$store.dispatch('GET_INDEX_LISTS') this.lists = this.$store.state.lists }, data() { return { lists: [], page: 1, loading: false } }, directives: { scroll: { bind: function (el, binding){ window.addEventListener('scroll', function() { if(document.documentElement.scrollTop + document.documentElement.clientHeight >= document.documentElement.scrollHeight) { let loadData = binding.value loadData() } }) } } }, methods: { async loadMore(){ if(!this.loading){ this.loading = true // 請求下一頁數據 await this.$store.dispatch('GET_INDEX_LISTS', { page: this.page++ }) // 從新填充數據 this.lists = this.lists.concat(this.$store.state.lists) this.loading = false } } }, components: { MyItem } } </script>
附上一個css loading動畫 , Loading.vue:vue
<template> <div class="loading"> <div class="loader-inner line-scale"> <div></div> <div></div> <div></div> <div></div> <div></div> </div> </div> </template> <style> .loading { text-align: center; } .loader-inner { display: inline-block; } @-webkit-keyframes line-scale { 0% { -webkit-transform: scaley(1); transform: scaley(1); } 50% { -webkit-transform: scaley(0.4); transform: scaley(0.4); } 100% { -webkit-transform: scaley(1); transform: scaley(1); } } @keyframes line-scale { 0% { -webkit-transform: scaley(1); transform: scaley(1); } 50% { -webkit-transform: scaley(0.4); transform: scaley(0.4); } 100% { -webkit-transform: scaley(1); transform: scaley(1); } } .line-scale > div:nth-child(1) { -webkit-animation: line-scale 1s 0.1s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); animation: line-scale 1s 0.1s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); } .line-scale > div:nth-child(2) { -webkit-animation: line-scale 1s 0.2s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); animation: line-scale 1s 0.2s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); } .line-scale > div:nth-child(3) { ![](http://images2017.cnblogs.com/blog/1027889/201712/1027889-20171206110307066-486062764.png) -webkit-animation: line-scale 1s 0.3s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); animation: line-scale 1s 0.3s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); } .line-scale > div:nth-child(4) { -webkit-animation: line-scale 1s 0.4s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); animation: line-scale 1s 0.4s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); } .line-scale > div:nth-child(5) { -webkit-animation: line-scale 1s 0.5s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); animation: line-scale 1s 0.5s infinite cubic-bezier(0.2, 0.68, 0.18, 1.08); } .line-scale > div { background-color: #fe0061; width: 4px; height: 30px; border-radius: 2px; margin: 2px; -webkit-animation-fill-mode: both; animation-fill-mode: both; display: inline-block; } </style>
加載效果圖:
web