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

Vue3?重構(gòu)函數(shù)透?jìng)魇纠馕?/h1>
 更新時(shí)間:2023年02月17日 11:48:24   作者:SoaringHeart  
這篇文章主要為大家介紹了Vue3?重構(gòu)函數(shù)透?jìng)魇纠馕?/div>

一、來(lái)源

之前做 vue 手機(jī)端需求開(kāi)發(fā)時(shí),遇到多個(gè)相似列表頁(yè)面:

列表頁(yè)面+下拉刷新和上拉加載+占位圖(無(wú)數(shù)據(jù)+斷網(wǎng))...

就想能不能復(fù)用同一個(gè)頁(yè)面,傳入不同的數(shù)據(jù)和單元格即可;經(jīng)過(guò)一個(gè)多月的思考(查詢(xún)js 的特性 + Vue3官方文檔),最終在官方文檔:

找到解決辦法: 屬性透?jìng)鞣椒?/strong>

原理如下:

二、使用示例

1、VRefreshListDemo.vue

<template>
  <navbar
    class="navbar"
    isleftarrow
    navBarTitle="數(shù)據(jù)透?jìng)?
    closeWebview
    isFixed
  />
  <VRefreshList
    :requestFC="requestFC"
    :requestErrorFC="requestErrorFC"
    :requestParamsChange="tag"
    :pageIndexInitial="pageIndexInitial"
  >
    <template v-slot="slotProps">
      <MessageInteractiveCell 
        class="page-view__cell"
        v-for="(e, index) in slotProps.list" :key="index"
        :imgUrl="deliverDataObj(e)?.activityUserIcon"
        :imgUrlRight="getResizedAliOSSImageUrl(e, 64)"
        :text="formatContentTitle(e)"
        :detailText="formatContentDetails(e)"
        :tag="formatDateNoYear(e.pushTime)"
        @click="clickCell(e)"
      >
      </MessageInteractiveCell>
    </template>
  </VRefreshList>
</template>
<script setup>
import navbar from '@/components/navbar.vue';
import VRefreshList from './VRefreshList.vue';
import MessageInteractiveCell from '@/views/message/components/MessageInteractiveCell.vue';
import { getCurrentInstance, ref, reactive, computed, watch, onMounted, onActivated} from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { Toast } from 'vant';
import { useStore } from 'vuex';
import { DropdownMenu, DropdownItem } from 'vant';
import { NET_MSG_ERROR } from '@/service/request/apiMessage';
import { hasNet, goToPage, goToPageForResult } from '@/utils/uplusApi';
import * as RQ from '@/service/request/request.js';
import * as MessageContant from '@/views/message/MessageContant.js';
import { 
  formatDateWithYear,
  formatDateNoYear,
  jumpURL, 
  getResizedAliOSSImageUrl, 
  deliverDataObj,
} from '@/views/message/MessageCommonUtil';
import icon_interactive from '@/assets/images/icon_interactive_base64';
import icon_like from '@/assets/images/icon_like_base64';
import icon_evaluation from '@/assets/images/icon_evaluation_base64';
const store = useStore();
const currentInstance = getCurrentInstance();
const { $platform, $vtoast, $debounce, $gio} = currentInstance.appContext.config.globalProperties;
onBeforeRouteLeave(() => {
  $vtoast.clear();
});
// 初始創(chuàng)建頁(yè)面剛進(jìn)來(lái)加載一次
onMounted(() => {
  // console.log('MessageList -> onMounted');
  // $vtoast.loading({});
  // onRefresh();
});
onActivated(() => {
  console.log('ContentList.vue -> onActivated');
  // $vtoast.loading({});
  // onMore();
});
const businessType = ref(store.getters.msgType || '0');
const pageIndexInitial = ref(1);
/// 獲取歷史消息
async function requestFC(options) {
  const {isRefresh, page, pageSize, lastObj} = options;
  console.log(`VRefreshListDemo requestFC:${JSON.stringify(isRefresh)},${page}`);
  const timestamp = Date.now();
  let msgTime = formatDateWithYear(timestamp);
  if (!isRefresh && lastObj) {
    msgTime = lastObj.pushTime;
  }
  const params = {
    msgTime: msgTime,
    queryTag: 1,
    querySize: pageSize,
    businessType: businessType.value,
  };
  if (['20'].includes(businessType.value) && 
  store.getters.msgBelong && 
  store.getters.msgBelongType) {
    params.belong = store.getters.msgBelong;
    params.belongType = store.getters.msgBelongType;
  }
  const items = await RQ.getMsgHistory(params);
  return items;
}
async function requestErrorFC(error) {
  Toast(JSON.stringify(error));
}
const clickCell = (obj) => {
  if (!hasNet.value) {
    Toast(NET_MSG_ERROR);
    return;
  }
  const url = formatContentReviewPage(obj);
  jumpURL(url);
};
function formatContentTitle(e) {
  const activityUserObj = deliverDataObj(e);
  // const result = decodeURIComponent(activityUserObj?.activityUserNickName ?? '');
  const result = decodeURIComponent(e.message.data.body.view?.title ?? '-');
  return result;
}
function formatContentDetails(e) {
  const result = decodeURIComponent(e.message.data.body.view?.title ?? '-');
  return result;
}
function formatContentReviewPage(e) {
  const result = e.message.data.body.extData?.reviewPage;
  return result;
}
</script>
<style scoped lang='scss'>
.page-view{
  position: relative;
  margin-top: 46px;
  height: calc(100vh - 46px);
  overflow: scroll;
}
.navbar{
  height: 46px;
}
:deep .van-pull-refresh{
  top: 46px;
}
</style>

2、VRefreshList.vue 源碼

VRefreshCustom 是“上拉刷新和下拉加載+占位圖”的封裝

<template>
  <VRefreshCustom
    v-model:refreshing="refreshing"
    v-model:loading="loading"
    :onRefresh="onRefresh"
    :loadMore="onMore"
    :finished="finished"
    :loadingText="loadingText"	
    :finishedText="finishedText"
    :netStatus="netStatus"
    :clickVNet="clickVNet"
    :isSuccess="isSuccess"
  >
    <slot :list="list"></slot>
  </VRefreshCustom>
</template>
<script setup>
import VRefreshCustom from './VRefreshCustomNew.vue';
import { getCurrentInstance, ref, reactive, computed, watch, onMounted, onActivated} from 'vue';
import { onBeforeRouteLeave } from 'vue-router';
import { Toast } from 'vant';
import { NET_MSG_ERROR } from '@/service/request/apiMessage';
import { hasNet, goToPage, goToPageForResult } from '@/utils/uplusApi';
const currentInstance = getCurrentInstance();
const { $platform, $vtoast, } = currentInstance.appContext.config.globalProperties;
onBeforeRouteLeave(() => {
  $vtoast.clear();
  console.log('離開(kāi) MessageInteractivePage.vue');
});
const props = defineProps({
  requestFC: {
    type: Function,
    required: true,
    description: '接口請(qǐng)求方法',
  },
  requestErrorFC: {
    type: Function,
    description: '接口請(qǐng)求錯(cuò)誤回調(diào)方法',
  },
  pageIndexInitial: {
    type: Number,
    default: 1,
  },
  pageSize: {
    type: Number,
    default: 30,
  },
  requestParamsChange: {
    type: String,
  },
  loadingText: {
    type: String,
    default: '',
  },
  finishedText: {
    type: String,
    default: '',
  },
});
const pageIndex = ref(props.pageIndexInitial);
const refreshing = ref(false);
const isSuccess = ref(false);
const loading = ref(false);
const finished = ref(false);
/// -1 請(qǐng)求失敗; 0無(wú)數(shù)據(jù); 1 正常列表,有數(shù)據(jù);
const netStatus = ref(1);
const list = reactive([]);
const clickVNet = () => {
  $vtoast.loading({});
  onRefresh();
};
///下拉刷新
const onRefresh = async () => {
  console.log('VRefreshList onRefresh');
  pageIndex.value = props.pageIndexInitial;
  if (!hasNet.value) {
    // netStatus.value = -1;
    refreshing.value = false;// 下拉刷新加載狀態(tài)結(jié)束
    isSuccess.value = false;// 下拉刷新成功失敗
    loading.value = false;// 加載狀態(tài)結(jié)束
    finished.value = true;// 數(shù)據(jù)全部加載完成
    $vtoast.clear();
    Toast(NET_MSG_ERROR);
    return;
  }
  refreshing.value = true;
  loading.value = false;
  requestList(true);
};
// 上拉獲取更多
const onMore = async () => {
  console.log('VRefreshList onMore');
  pageIndex.value++;
  refreshing.value = false;
  loading.value = true;
  requestList(false);
};
/// 獲取歷史消息
const requestList = async () => {
  try {
    netStatus.value = 1;
    const params = {
      isRefresh: refreshing.value,
      page: pageIndex.value,
      pageSize: props.pageSize,
      lastObj: list.length > 0 ? list[list.length - 1] : undefined,
    };
    const items = await props.requestFC(params);
    // console.log(`VRefreshList items:${items.length}`);
    if (refreshing.value) {
      list.splice(0, list.length);
    }
    if (list.length === 0 && items.length === 0) {
      refreshing.value = false;
      isSuccess.value = true;
      loading.value = false;// 加載狀態(tài)結(jié)束
      finished.value = true;// 數(shù)據(jù)全部加載完成
      netStatus.value = 0;
      return;
    }
    if (items.length) {
      list.push(...items);
    }
    console.log(`${location.hash} list:${list.length}, items:${items.length}`);
    loading.value = false;// 加載狀態(tài)結(jié)束
    finished.value = (items.length < props.pageSize);// 數(shù)據(jù)全部加載完成
    if(refreshing.value){
      isSuccess.value = true;
    }
    netStatus.value = list.length === 0 ? 0 : 1;
  } catch (error) {
    console.log(`${location.hash} error: ${JSON.stringify(error)}, 
    refreshing: ${refreshing.value},
    hasNet.value:${hasNet.value}`);
    finished.value = true;// 數(shù)據(jù)全部加載完成
    isSuccess.value = false;// 下拉刷新成功失敗
    if (!hasNet.value) {
      netStatus.value = -1;
    } else {
      netStatus.value = 0;
    }
    if (!error) {
      return;
    }
    props.requestErrorFC && await props.requestErrorFC(error);
  } finally {
    $vtoast.clear();
    refreshing.value = false;
    loading.value = false;// 加載狀態(tài)結(jié)束
  }
};
watch(() => props.requestParamsChange, (newValue, oldValue) => {
  console.log('watch requestParamsChange', newValue, oldValue);
  if (newValue !== oldValue) {
    scrollToTop(listEl);
    onRefresh();
  }
});
watch(() => hasNet.value, (newValue, oldValue) => {
  // console.log('hasNet.value', newValue, oldValue);
  if (newValue) {
    onRefresh();
  }
});
let listEl;
onMounted(() => {
  listEl = document.getElementById('van-list');
  // console.log(listEl);
});
const scrollToTop = (e) => e.scrollIntoView({ block: 'start' });
</script>

最后、總結(jié)

1、此文重構(gòu)方法的意義在于我可以通過(guò)封裝一個(gè)列表組件,然后同類(lèi)頁(yè)面只需要傳請(qǐng)求方法即可,極大的提高開(kāi)發(fā)效率(vue 中組件亦可是頁(yè)面);

2、核心是通過(guò) Vue3 屬性支持 Function 進(jìn)而實(shí)現(xiàn)函數(shù)透?jìng)?,雖然官方文檔只是一筆帶過(guò),但確實(shí)是核心特性之一;

3、Function 類(lèi)型無(wú)論在 Swift、Dart/Flutter、JS/TS 中都是一等公民;可以幫助我們擴(kuò)展代碼重構(gòu)邊界。在實(shí)現(xiàn)此次封裝之前我也不知道能做到什么程度,不過(guò)最終效果非常理想;

4、姐妹篇 Flutter 重構(gòu): 屬性透?jìng)?函數(shù)透?jìng)?/a>

以上就是Vue3 重構(gòu)函數(shù)透?jìng)魇纠馕龅脑敿?xì)內(nèi)容,更多關(guān)于Vue3 重構(gòu)函數(shù)透?jìng)鞯馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Vue 3開(kāi)發(fā)中VueUse強(qiáng)大Hooks庫(kù)

    Vue 3開(kāi)發(fā)中VueUse強(qiáng)大Hooks庫(kù)

    VueUse提供了一個(gè)豐富且強(qiáng)大的Hooks庫(kù),可以幫助開(kāi)發(fā)者快速實(shí)現(xiàn)各種功能,提高開(kāi)發(fā)效率,本文來(lái)詳細(xì)的介紹一下,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • vue項(xiàng)目下npm或yarn下安裝echarts多個(gè)版本方式

    vue項(xiàng)目下npm或yarn下安裝echarts多個(gè)版本方式

    這篇文章主要介紹了vue項(xiàng)目下npm或yarn下安裝echarts多個(gè)版本方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • vue3中router路由以及vuex的store使用解析

    vue3中router路由以及vuex的store使用解析

    這篇文章主要介紹了vue3中router路由以及vuex的store使用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • vue2中的keep-alive使用總結(jié)及注意事項(xiàng)

    vue2中的keep-alive使用總結(jié)及注意事項(xiàng)

    vue2.0提供了一個(gè)keep-alive組件用來(lái)緩存組件,避免多次加載相應(yīng)的組件,減少性能消耗。本文給大家介紹vue2中的keep-alive使用總結(jié)及注意事項(xiàng),需要的朋友參考下吧
    2017-12-12
  • elementUI select組件使用及注意事項(xiàng)詳解

    elementUI select組件使用及注意事項(xiàng)詳解

    這篇文章主要介紹了elementUI select組件使用及注意事項(xiàng)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2019-05-05
  • Vue腳手架的創(chuàng)建超詳解步驟

    Vue腳手架的創(chuàng)建超詳解步驟

    這篇文章主要給大家介紹了關(guān)于Vue腳手架創(chuàng)建的相關(guān)資料,Vue腳手架是vue官方提供的標(biāo)準(zhǔn)化開(kāi)發(fā)工具(平臺(tái)),文中通過(guò)代碼以及圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • vue指令中的v-once用法

    vue指令中的v-once用法

    這篇文章主要介紹了vue指令中的v-once用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • 前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)

    前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)

    當(dāng)我們遇到定位展示的時(shí)候會(huì)出現(xiàn)使用地圖展示的需求,下面這篇文章主要給大家介紹了關(guān)于前端項(xiàng)目中如何使用百度地圖api(含實(shí)例)的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-06-06
  • vite多頁(yè)面配置項(xiàng)目實(shí)戰(zhàn)

    vite多頁(yè)面配置項(xiàng)目實(shí)戰(zhàn)

    vite官方文檔中有關(guān)于多頁(yè)面應(yīng)用模式如果配置的說(shuō)明,下面這篇文章主要給大家介紹了關(guān)于vite多頁(yè)面配置的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-04-04
  • 聊聊element-ui 側(cè)邊欄的router問(wèn)題

    聊聊element-ui 側(cè)邊欄的router問(wèn)題

    這篇文章主要介紹了關(guān)于element-ui 側(cè)邊欄的router問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05

最新評(píng)論

海淀区| 万宁市| 浑源县| 通城县| 翼城县| 海安县| 介休市| 南和县| 阿坝县| 黑山县| 建平县| 盘山县| 海林市| 汤阴县| 夏津县| 沙洋县| 沾益县| 陵川县| 永吉县| 盱眙县| 清流县| 桐城市| 双江| 阳江市| 长武县| 乌兰浩特市| 萝北县| 金阳县| 陵水| 镇原县| 台中县| 离岛区| 左贡县| 莱阳市| 于田县| 内黄县| 呼图壁县| 嘉峪关市| 郁南县| 万源市| 黎城县|