Преглед изворни кода

【我的作品】搜索框的输入行为经过debounce,触发列表更新,以及列表为空提示的显隐。

任一存 пре 4 година
родитељ
комит
c53a1d867c
2 измењених фајлова са 84 додато и 6 уклоњено
  1. 61 0
      src/utils/other.js
  2. 23 6
      src/views/material/works/index.vue

+ 61 - 0
src/utils/other.js

@@ -0,0 +1,61 @@
+/**
+ * 返回一个自带节流效果的函数,用res表示。
+ * 
+ * fn:需要被节流的函数
+ * interval:最短多长时间允许执行一次fn
+ * 
+ * 功能要点:
+ * 1.fn代码里如有this,res被执行时,this会指向res的调用者;
+ * 2.res被执行时的实参会映射到fn的形参;
+ * 3.第一次调用res时,会立即执行fn。
+ */
+ export function throttle(fn, interval) {
+  let lastRunTime = 0
+
+  return function (...args) {
+    let elapsedTime = Date.now() - lastRunTime
+    if (elapsedTime < interval) {
+      return
+    }
+
+    let context = this
+    lastRunTime = Date.now()
+    fn.apply(context, args)
+  }
+}
+
+/**
+ * 返回一个自带消抖效果的函数,用res表示。
+ * 
+ * fn: 需要被消抖的函数
+ * delay: 消抖时长
+ * isImmediateCall: 是在第一次调用时立即执行fn,还是在最后一次调用后等delay时长再调用fn
+ */
+ export function debounce(fn, delay, isImmediateCall = true) {
+  let timer = null
+  // 上次调用的时刻
+  let lastCallTime = 0
+
+  if (isImmediateCall) {
+    return function (...args) {
+      const context = this
+      const currentTime = Date.now()
+      if (currentTime - lastCallTime >= delay) {
+        fn.apply(context, args)
+      }
+      lastCallTime = currentTime
+    }
+  } else {
+    return function (...args) {
+      const context = this
+      const currentTime = Date.now()
+      if (currentTime - lastCallTime >= delay) {
+        clearTimeout(timer)
+        timer = setTimeout(() => {
+          fn.apply(context, args)
+        }, delay)
+      }
+      lastCallTime = currentTime
+    }
+  }
+}

+ 23 - 6
src/views/material/works/index.vue

@@ -56,11 +56,11 @@
         </div>
       </li>
     </ul>
-    <div class="nodata" v-if="list.length == 0 && !hasMoreData && searchKey">
+    <div class="nodata" v-if="list.length == 0 && !hasMoreData && lastestUsedSearchKey">
       <img :src="$noresult" alt="" />
       <span>未搜索到结果</span>
     </div>
-    <div class="nodata" v-if="list.length == 0 && !hasMoreData && !searchKey">
+    <div class="nodata" v-if="list.length == 0 && !hasMoreData && !lastestUsedSearchKey">
       <img :src="config.empty" alt="" />
       <span>您还没有作品,请先创建作品~</span>
       <button @click="add" class="upload-btn-in-table">创建作品</button>
@@ -80,6 +80,7 @@
 import share from '../popup/share'
 import preview from "@/components/preview";
 import config from "@/config";
+import { debounce } from "@/utils/other.js"
 
 import {
   addWorks,
@@ -100,6 +101,8 @@ export default {
       hasMoreData: true,
       isRequestingMoreData: false,
       searchKey:'',
+      // 因为searchKey的变化经过debounce、异步请求的延时,才会反映到数据列表的变化上,所以是否显示、显示哪种无数据提示,也要等到数据列表变化后,根据数据列表是否为空,以及引发本次变化的那个searchKey瞬时值来决定。本变量就是用来保存那个瞬时值。
+      lastestUsedSearchKey: '',
       showShare:false,
       showPreview:false,
       showItem:'',
@@ -109,12 +112,20 @@ export default {
   mounted(){
   },
   watch:{
-    // searchKey(){
-    //   this.paging.current = 1
-    //   this.getWorksList()
-    // }
+    searchKey: {
+      handler: function () {
+        this.refreshListDebounced()
+      },
+      immediate: false,
+    },
   },
   methods:{
+    refreshListDebounced: debounce(function() {
+      console.log('refresh');
+      this.list = []
+      this.isRequestingMoreData = false
+      this.hasMoreData = true
+    }, 700, false),
     openShare(data){
       getPanoInfo(data.id, (data) => {
         if (data.scenes.length<=0) {
@@ -153,6 +164,7 @@ export default {
               delWorks(item.id,()=>{
                 this.$msg.success("删除成功");
                 this.isRequestingMoreData = true
+                const lastestUsedSearchKey = this.searchKey
                 getWorksList(
                   {
                     pageNum: this.list.length + 1,
@@ -166,12 +178,14 @@ export default {
                       this.hasMoreData = false
                     }
                     this.isRequestingMoreData = false
+                    this.lastestUsedSearchKey = lastestUsedSearchKey
                     // TODO: 这是干啥呢?
                     this.$nextTick(()=>{
                       this.$bus.emit('refreshTips')
                     })
                   },
                   () => {
+                    this.lastestUsedSearchKey = lastestUsedSearchKey
                     this.isRequestingMoreData = false
                   }
                 )
@@ -181,6 +195,7 @@ export default {
     },
     requestMoreData() {
       this.isRequestingMoreData = true
+      const thisTimeSearchKey = this.searchKey
       getWorksList(
         {
           pageNum: Math.floor(this.list.length / config.PAGE_SIZE) + 1,
@@ -193,12 +208,14 @@ export default {
             this.hasMoreData = false
           }
           this.isRequestingMoreData = false
+          this.lastestUsedSearchKey = thisTimeSearchKey
           // TODO: 这是干啥呢?
           this.$nextTick(()=>{
             this.$bus.emit('refreshTips')
           })
         },
         () => {
+          this.lastestUsedSearchKey = thisTimeSearchKey
           this.isRequestingMoreData = false
         }
       );