首页前端开发VUEVue3 重构函数透传示例解析

Vue3 重构函数透传示例解析

时间2024-02-11 05:10:03发布访客分类VUE浏览240
导读:收集整理的这篇文章主要介绍了Vue3 重构函数透传示例解析,觉得挺不错的,现在分享给大家,也给大家做个参考。 目录一、来源列表页面+下拉刷新和上拉加载+占位图(无数据+断网)...二、使...
收集整理的这篇文章主要介绍了Vue3 重构函数透传示例解析,觉得挺不错的,现在分享给大家,也给大家做个参考。
目录
  • 一、来源
    • 列表页面+下拉刷新和上拉加载+占位图(无数据+断网)...
  • 二、使用示例
    • 最后、总结

      一、来源

      之前做 vue 手机端需求开发时,遇到多个相似列表页面:

      列表页面+下拉刷新和上拉加载+占位图(无数据+断网)...

      就想能不能复用同一个页面,传入不同的数据和单元格即可;经过一个多月的思考(查询js 的特性 + Vue3官方文档),最终在官方文档:

      找到解决办法: 属性透传方法

      原理如下:

      二、使用示例

      1、VRefreshListDemo.vue

      template>
            navbar    class="navbar"    isleftarrow    navBarTITle="数据透传"    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 '@/@R_512_480@s/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();
      }
          );
          // 初始创建页面刚进来加载一次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('离开 MessageInteractivePage.vue');
      }
          );
      const props = defineProps({
        requestFC: {
          type: Function,    required: true,    description: '接口请求方法',  }
      ,  requestErrorFC: {
          type: Function,    description: '接口请求错误回调方法',  }
      ,  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 请求失败;
           0无数据;
           1 正常列表,有数据;
          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;
          // 下拉刷新加载状态结束    isSuccess.value = false;
          // 下拉刷新成功失败    loading.value = false;
          // 加载状态结束    finished.value = true;
          // 数据全部加载完成    $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;
          // 加载状态结束      finished.value = true;
          // 数据全部加载完成      netStatus.value = 0;
                return;
          }
          if (items.length) {
                list.push(...items);
          }
          console.log(`${
      location.hash}
       list:${
      list.length}
      , items:${
      items.length}
          `);
              loading.value = false;
          // 加载状态结束    finished.value = (items.length  props.pageSize);
      // 数据全部加载完成    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;
          // 数据全部加载完成    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;
      // 加载状态结束  }
      }
          ;
          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>
          

      最后、总结

      1、此文重构方法的意义在于我可以通过封装一个列表组件,然后同类页面只需要传请求方法即可,极大的提高开发效率(vue 中组件亦可是页面);

      2、核心是通过 Vue3 属性支持 Function 进而实现函数透传,虽然官方文档只是一笔带过,但确实是核心特性之一;

      3、Function 类型无论在 Swift、Dart/Flutter、JS/TS 中都是一等公民;可以帮助我们扩展代码重构边界。在实现此次封装之前我也不知道能做到什么程度,不过最终效果非常理想;

      4、姐妹篇 Flutter 重构: 属性透传/函数透传

      以上就是Vue3 重构函数透传示例解析的详细内容,更多关于Vue3 重构函数透传的资料请关注其它相关文章!

      您可能感兴趣的文章:
      • vue前端重构computed及watch组件通信等实用技巧整理
      • 测试平台开发vue组件化重构前端代码
      • 使用vue3重构拼图游戏的实现示例
      • 记一次用ts+vuecli4重构项目的实现
      • 使用vue重构资讯页面的实例代码解析
      • 利用vue重构有赞商城的思路以及总结整理

      声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


      若转载请注明出处: Vue3 重构函数透传示例解析
      本文地址: https://pptw.com/jishu/609361.html
      Vue实现DOM元素拖放互换位置示例 vant-List-@load事件一直触发的解决

      游客 回复需填写必要信息