最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue瀑布流組件實現(xiàn)上拉加載更多

 更新時間:2020年03月10日 09:17:54   作者:BenjaminShih  
這篇文章主要為大家詳細(xì)介紹了vue瀑布流組件實現(xiàn)上拉加載更多,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下

最近在做移動端h5頁面,所以分頁什么的就不能按照傳統(tǒng)pc端的分頁器的思維去做了,這么小的屏幕去點擊也不太方便一般來講移動端都是上拉加載更多,符合正常使用習(xí)慣。

首先簡單寫一下模板部分的html代碼,,很簡單清晰的邏輯:

<template>
 <div class="loadmore">
 <div class="loadmore__body">
  <slot></slot>
 </div>
 <div class="loadmore__footer">
  <span v-if="loading">
  <i class="tc-loading"></i>
  <span>正在加載</span>
  </span>
  <span v-else-if="loadable">上拉加載更多</span>
  <span v-else>沒有更多了</span>
 </div>
 </div>
</template>

然后就是業(yè)務(wù)部分了

在動手寫組件之前,先理清需求:

加載頁面 -> 滑到底部 -> 上拉一定距離 -> 加載第二頁 -> 繼續(xù)前面步驟 -> 沒有更多

這是一個用戶交互邏輯,而我們需要將其映射為代碼邏輯:

首屏自動加載第一頁 -> 滑動到底部&&按下時候滑動距離Y軸有一定偏移量 -> 請求后端加載第二頁 -> 根據(jù)返回字段判斷是否還有下一頁

有了代碼邏輯,主干就出來了,加載和判斷由事件來控制,而又作為一個vue組件,我們需要配合vue生命周期來掛載事件和銷毀事件

export default {
 mounted() {
  // 確定容器
  // 容器綁定事件
 },
 beforeDestory() {
  // 解綁事件
 },
}

如果沒有解綁的話,每次你加載組件,就會綁定一次事件…

然后我們需要一些核心事件回調(diào)方法來在合適的時間加載數(shù)據(jù)渲染頁面, 回想一下,第一我們需要http獲取數(shù)據(jù)的load函數(shù),然后我們需要三個綁定事件的回調(diào)函數(shù)pointDown(), pointMove(), pointUp(),分別對應(yīng)用戶按下、移動、彈起手指操作:

export default {
 ···
 methods:{
  /**
  * 加載一組數(shù)據(jù)的方法
  */
  load() {
   // 設(shè)置options
  this.$axios.request(options).then((res) => {
   // 獲取數(shù)據(jù)后的處理
  }).catch((e) => {
   // 異常處理
  })
  },
  /**
  * 鼠標(biāo)按下事件處理函數(shù)
  * @param {Object} e - 事件對象
  */
  pointerdown(e) {
  // 獲取按下的位置
  this.pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  },
  /**
  * 鼠標(biāo)移動事件處理函數(shù)
  * @param {Object} e - 事件對象
  */
  pointermove(e) {
  const container = this.$container
  const pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  const moveY = pageY - this.pageY

  // 如果已經(jīng)向下滾動到頁面最底部
  if (moveY < 0 && (container.scrollTop + Math.min(
   global.innerHeight,
   container.clientHeight,
  )) >= container.scrollHeight) {
   // 阻止原生的上拉拖動會露出頁面底部空白區(qū)域的行為(主要針對iOS版微信)
   e.preventDefault()

   // 如果上拉距離超過50像素,則加載下一頁
   if (moveY < -50) {
   this.pageY = pageY
   this.load()
   }
  }
  },
  /**
  * 鼠標(biāo)松開事件處理函數(shù)
  */
  pointerup() {
  // 這邊就是取消拖動狀態(tài),需要注意在拖動過程中不要再次觸發(fā)一些事件回調(diào),否側(cè)亂套
  this.dragging = false
  },
 },
 ···
}

基本上主干已經(jīng)算完工了,一些props傳入或者一些邏輯控制細(xì)節(jié)需要再額外添加,貼出整個組件的源碼:

<template>
 <div class="loadmore">
 <!-- <div class="loadmore__header"></div> -->
 <div class="loadmore__body">
  <slot></slot>
 </div>
 <div class="loadmore__footer">
  <span v-if="loading">
  <i class="tc-loading"></i>
  <span>正在加載</span>
  </span>
  <span v-else-if="loadable">上拉加載更多</span>
  <span v-else>沒有更多了</span>
 </div>
 </div>
</template>

<script type="text/babel">
 import axios from 'axios'

 const CancelToken = axios.CancelToken

 export default {
 data() {
  return {
  /**
   * 總頁數(shù)(由服務(wù)端返回)
   * @type {number}
   */
  count: 0,

  /**
   * 是否正在拖拽中
   * @type {boolean}
   */
  dragging: false,

  /**
   * 已加載次數(shù)
   * @type {number}
   */
  times: 0,

  /**
   * 已開始記載
   * @type {boolean}
   */
  started: false,

  /**
   * 正在加載中
   * @type {boolean}
   */
  loading: false,
  }
 },

 props: {
  /**
  * 初始化后自動開始加載數(shù)據(jù)
  */
  autoload: {
  type: Boolean,
  default: true,
  },

  /**
  * 離組件最近的可滾動父級元素(用于監(jiān)聽事件及獲取滾動條位置)
  */
  container: {
  // Selector or Element
  default: 'body',
  },

  /**
  * 禁用組件
  */
  disabled: {
  type: Boolean,
  default: false,
  },

  /**
  * Axios請求參數(shù)配置對象
  * {@link https://github.com/mzabriskie/axios#request-config}
  */
  options: {
  type: Object,
  default: null,
  },

  /**
  * 起始頁碼
  */
  page: {
  type: Number,
  default: 1,
  },

  /**
  * 每頁加載數(shù)據(jù)條數(shù)
  */
  rows: {
  type: Number,
  default: 10,
  },

  /**
  * 數(shù)據(jù)加載請求地址
  */
  url: {
  type: String,
  default: '',
  },
 },

 computed: {
  /**
  * 是否可以加載
  * @returns {boolean} 是與否
  */
  loadable() {
  return !this.disabled && (!this.started || (this.page + this.times) <= this.count)
  },
 },

 mounted() {
  let container = this.container

  if (container) {
  if (typeof container === 'string') {
   container = document.querySelector(container)
  } else if (!container.querySelector) {
   container = document.body
  }
  }

  if (!container) {
  container = document.body
  }

  this.$container = container
  this.onPointerDown = this.pointerdown.bind(this)
  this.onPointerMove = this.pointermove.bind(this)
  this.onPointerUp = this.pointerup.bind(this)

  if (global.PointerEvent) {
  container.addEventListener('pointerdown', this.onPointerDown, false)
  container.addEventListener('pointermove', this.onPointerMove, false)
  container.addEventListener('pointerup', this.onPointerUp, false)
  container.addEventListener('pointercancel', this.onPointerUp, false)
  } else {
  container.addEventListener('touchstart', this.onPointerDown, false)
  container.addEventListener('touchmove', this.onPointerMove, false)
  container.addEventListener('touchend', this.onPointerUp, false)
  container.addEventListener('touchcancel', this.onPointerUp, false)
  container.addEventListener('mousedown', this.onPointerDown, false)
  container.addEventListener('mousemove', this.onPointerMove, false)
  container.addEventListener('mouseup', this.onPointerUp, false)
  }

  if (this.autoload) {
  this.load()
  }
 },

 // eslint-disable-next-line
 beforeDestroy() {
  const container = this.$container

  if (global.PointerEvent) {
  container.removeEventListener('pointerdown', this.onPointerDown, false)
  container.removeEventListener('pointermove', this.onPointerMove, false)
  container.removeEventListener('pointerup', this.onPointerUp, false)
  container.removeEventListener('pointercancel', this.onPointerUp, false)
  } else {
  container.removeEventListener('touchstart', this.onPointerDown, false)
  container.removeEventListener('touchmove', this.onPointerMove, false)
  container.removeEventListener('touchend', this.onPointerUp, false)
  container.removeEventListener('touchcancel', this.onPointerUp, false)
  container.removeEventListener('mousedown', this.onPointerDown, false)
  container.removeEventListener('mousemove', this.onPointerMove, false)
  container.removeEventListener('mouseup', this.onPointerUp, false)
  }

  if (this.loading && this.cancel) {
  this.cancel()
  }
 },

 methods: {
  /**
  * 加載一組數(shù)據(jù)的方法
  */
  load() {
  if (this.disabled || this.loading) {
   return
  }

  this.started = true
  this.loading = true

  const params = {
   currentPage: this.page + this.times,
   pageSize: this.rows,
  }
  const options = Object.assign({}, this.options, {
   url: this.url,
   cancelToken: new CancelToken((cancel) => {
   this.cancel = cancel
   }),
  })

  if (String(options.method).toUpperCase() === 'POST') {
   options.data = Object.assign({}, options.data, params)
  } else {
   options.params = Object.assign({}, options.params, params)
  }

  this.$axios.request(options).then((res) => {
   const data = res.result

   this.times += 1
   this.loading = false
   this.count = data.pageCount
   this.$emit('success', data.list)
   this.$emit('complete')
  }).catch((e) => {
   this.loading = false
   this.$emit('error', e)
   this.$emit('complete')
  })
  },

  /**
  * 重置加載相關(guān)變量
  */
  reset() {
  this.count = 0
  this.times = 0
  this.started = false
  this.loading = false
  },

  /**
  *重新開始加載
  */
  restart() {
  this.reset()
  this.load()
  },

  /**
  * 鼠標(biāo)按下事件處理函數(shù)
  * @param {Object} e - 事件對象
  */
  pointerdown(e) {
  if (this.disabled || !this.loadable || this.loading) {
   return
  }

  this.dragging = true
  this.pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  },

  /**
  * 鼠標(biāo)移動事件處理函數(shù)
  * @param {Object} e - 事件對象
  */
  pointermove(e) {
  if (!this.dragging) {
   return
  }

  const container = this.$container
  const pageY = e.changedTouches ? e.changedTouches[0].pageY : e.pageY
  const moveY = pageY - this.pageY

  // 如果已經(jīng)向下滾動到頁面最底部
  if (moveY < 0 && (container.scrollTop + Math.min(
   global.innerHeight,
   container.clientHeight,
  )) >= container.scrollHeight) {
   // 阻止原生的上拉拖動會露出頁面底部空白區(qū)域的行為(主要針對iOS版微信)
   e.preventDefault()

   // 如果上拉距離超過50像素,則加載下一頁
   if (moveY < -50) {
   this.pageY = pageY
   this.load()
   }
  }
  },

  /**
  * 鼠標(biāo)松開事件處理函數(shù)
  */
  pointerup() {
  this.dragging = false
  },
 },
 }
</script>

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Vue移動端項目實現(xiàn)使用手機預(yù)覽調(diào)試操作

    Vue移動端項目實現(xiàn)使用手機預(yù)覽調(diào)試操作

    這篇文章主要介紹了Vue移動端項目實現(xiàn)使用手機預(yù)覽調(diào)試操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-07-07
  • Vue中使用Echarts響應(yīng)式布局flexible.js+rem適配方案詳解

    Vue中使用Echarts響應(yīng)式布局flexible.js+rem適配方案詳解

    這篇文章主要介紹了Vue中使用Echarts響應(yīng)式布局flexible.js+rem適配方案詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-01-01
  • Vue 通過自定義指令回顧v-內(nèi)置指令(小結(jié))

    Vue 通過自定義指令回顧v-內(nèi)置指令(小結(jié))

    這篇文章主要介紹了Vue 通過自定義指令回顧v-內(nèi)置指令(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • Vue中加載天地圖的離線地圖基本步驟

    Vue中加載天地圖的離線地圖基本步驟

    這篇文章主要給大家介紹了關(guān)于Vue中加載天地圖的離線地圖的基本步驟,Vue天地圖離線地圖是指基于Vue框架開發(fā)的應(yīng)用程序,使用天地圖離線地圖服務(wù)提供商提供的地圖數(shù)據(jù),可以在沒有網(wǎng)絡(luò)的情況下使用地圖功能,需要的朋友可以參考下
    2023-10-10
  • vue+SpringBoot使用WebSocket方式

    vue+SpringBoot使用WebSocket方式

    WebSocket是一種全雙工通信協(xié)議,通過HTTP升級機制建立連接,支持實時雙向數(shù)據(jù)傳輸,示例代碼展示了如何在Java Spring Boot和Vue.js中實現(xiàn)WebSocket服務(wù)和客戶端
    2025-02-02
  • 關(guān)于element-ui?select?下拉框位置錯亂問題解決

    關(guān)于element-ui?select?下拉框位置錯亂問題解決

    這篇文章主要介紹了關(guān)于element-ui?select?下拉框位置錯亂問題解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • Vue2.x如何解決Element組件el-tooltip滾動時錯位不消失的問題

    Vue2.x如何解決Element組件el-tooltip滾動時錯位不消失的問題

    這篇文章主要介紹了Vue2.x如何解決Element組件el-tooltip滾動時錯位不消失的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • vue 綁定對象,數(shù)組之?dāng)?shù)據(jù)無法動態(tài)渲染案例詳解

    vue 綁定對象,數(shù)組之?dāng)?shù)據(jù)無法動態(tài)渲染案例詳解

    這篇文章主要介紹了vue 綁定對象,數(shù)組之?dāng)?shù)據(jù)無法動態(tài)渲染案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09
  • vue編譯器util工具使用方法示例

    vue編譯器util工具使用方法示例

    這篇文章主要為大家介紹了vue編譯器util工具使用方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • 詳解vuejs2.0 select 動態(tài)綁定下拉框支持多選

    詳解vuejs2.0 select 動態(tài)綁定下拉框支持多選

    這篇文章主要介紹了vuejs2.0 select動態(tài)綁定下拉框 ,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評論

南澳县| 南和县| 新密市| 阳高县| 徐水县| 中西区| 梅河口市| 玉屏| 盐山县| 长武县| 玉树县| 喀什市| 叙永县| 静安区| 蓬安县| 普陀区| 江津市| 东平县| 新绛县| 荔波县| 涡阳县| 剑阁县| 静安区| 烟台市| 眉山市| 察雅县| 五家渠市| 政和县| 上蔡县| 荔浦县| 乌鲁木齐市| 且末县| 察哈| 图木舒克市| 普兰店市| 光泽县| 仪征市| 河西区| 永登县| 手机| 德江县|