自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

讓我看看有多少人不知道Vue3中也能實(shí)現(xiàn)高階組件HOC

開發(fā) 前端
這篇文章我們講了在Vue3中如何實(shí)現(xiàn)一個高階組件HOC,但是里面涉及到了很多源碼知識,所以這是一篇運(yùn)用源碼的實(shí)戰(zhàn)文章。如果你理解了文章中涉及到的知識,那么就會覺得Vue中實(shí)現(xiàn)HOC還是很簡單的,反之就像是在看天書。

前言

高階組件HOC在React社區(qū)是非常常見的概念,但是在Vue社區(qū)中卻是很少人使用。主要原因有兩個:1、Vue中一般都是使用SFC,實(shí)現(xiàn)HOC比較困難。2、HOC能夠?qū)崿F(xiàn)的東西,在Vue2時代mixins能夠?qū)崿F(xiàn),在Vue3時代Composition API能夠?qū)崿F(xiàn)。如果你不知道HOC,那么你平時絕對沒有場景需要他。但是如果你知道HOC,那么在一些特殊的場景使用他就可以很優(yōu)雅的解決一些問題。

什么是高階組件HOC

HOC使用場景就是加強(qiáng)原組件。

HOC實(shí)際就是一個函數(shù),這個函數(shù)接收的參數(shù)就是一個組件,并且返回一個組件,返回的就是加強(qiáng)后組件。如下圖:

圖片圖片

在Composition API出現(xiàn)之前HOC還有一個常見的使用場景就是提取公共邏輯,但是有了Composition API后這種場景就無需使用HOC了。

高階組件HOC使用場景

很多同學(xué)覺得有了Composition API后,直接無腦使用他就完了,無需費(fèi)時費(fèi)力的去搞什么HOC。那如果是下面這個場景呢?

有一天產(chǎn)品找到你,說要給我們的系統(tǒng)增加會員功能,需要讓系統(tǒng)中的幾十個功能塊增加會員可見功能。如果不是會員這幾十個功能塊都顯示成引導(dǎo)用戶開通會員的UI,并且這些功能塊涉及到幾十個組件,分布在系統(tǒng)的各個頁面中。

如果不知道HOC的同學(xué)一般都會這樣做,將會員相關(guān)的功能抽取成一個名為useVip.ts的hooks。代碼如下:

export function useVip() {
  function getShowVipContent() {
    // 一些業(yè)務(wù)邏輯判斷是否是VIP
    return false;
  }

  return {
    showVipContent: getShowVipContent(),
  };
}

然后再去每個具體的業(yè)務(wù)模塊中去使用showVipContent變量判斷,v-if="showVipContent"顯示原模塊,v-else顯示引導(dǎo)開通會員UI。代碼如下:

<template>
  <Block1
    v-if="showVipContent"
    :name="name1"
    @changeName="(value) => (name1 = value)"
  />
  <OpenVipTip v-else />
</template>

<script setup lang="ts">
import { ref } from "vue";
import Block1 from "./block1.vue";
import OpenVipTip from "./open-vip-tip.vue";
import { useVip } from "./useVip";

const { showVipContent } = useVip();
const name1 = ref("block1");
</script>

我們系統(tǒng)中有幾十個這樣的組件,那么我們就需要這樣去改幾十次。非常麻煩,如果有些模塊是其他同事寫的代碼還很容易改錯?。?!

而且現(xiàn)在流行搞SVIP,也就是光開通VIP還不夠,需要再開通一個SVIP。當(dāng)你后續(xù)接到SVIP需求時,你又需要去改這幾十個模塊。v-if="SVIP"顯示某些內(nèi)容,v-else-if="VIP"顯示提示開通SVIP,v-else顯示提示開通VIP。

上面的這一場景使用hooks去實(shí)現(xiàn),雖然能夠完成,但是因?yàn)槿肭至诉@幾十個模塊的業(yè)務(wù)邏輯。所以容易出錯,也改起來比較麻煩,代碼也不優(yōu)雅。

那么有沒有一種更好的解決方案,讓我們可以不入侵這幾十個模塊的業(yè)務(wù)邏輯的實(shí)現(xiàn)方式呢?

答案是:高階組件HOC。

HOC的一個用途就是對組件進(jìn)行增強(qiáng),并且不會入侵原有組件的業(yè)務(wù)邏輯,在這里就是使用HOC判斷會員相關(guān)的邏輯。如果是會員那么就渲染原本的模塊組件,否則就渲染引導(dǎo)開通VIP的UI

實(shí)現(xiàn)一個簡單的HOC

首先我們要明白Vue的組件經(jīng)過編譯后就是一個對象,對象中的props屬性對應(yīng)的就是我們寫的defineProps。對象中的setup方法,對應(yīng)的就是我們熟知的<script setup>語法糖。

比如我使用console.log(Block1)將上面的import Block1 from "./block1.vue";給打印出來,如下圖:

圖片圖片

這個就是我們引入的Vue組件對象。

還有一個冷知識,大家可能不知道。如果在setup方法中返回一個函數(shù),那么在Vue內(nèi)部就會認(rèn)為這個函數(shù)就是實(shí)際的render函數(shù),并且在setup方法中我們天然的就可以訪問定義的變量。

利用這一點(diǎn)我們就可以在Vue3中實(shí)現(xiàn)一個簡單的高階組件HOC,代碼如下:

import { h } from"vue";
import OpenVipTip from"./open-vip-tip.vue";

exportdefaultfunction WithVip(BaseComponent: any) {
return {
    setup() {
      const showVipContent = getShowVipContent();
      function getShowVipContent() {
        // 一些業(yè)務(wù)邏輯判斷是否是VIP
        returntrue;
      }

      return() => {
        return showVipContent ? h(BaseComponent) : h(OpenVipTip);
      };
    },
  };
}

在上面的代碼中我們將會員相關(guān)的邏輯全部放在了WithVip函數(shù)中,這個函數(shù)接收一個參數(shù)BaseComponent,他是一個Vue組件對象。

在setup方法中我們return了一個箭頭函數(shù),他會被當(dāng)作render函數(shù)處理。

如果showVipContent為true,就表明當(dāng)前用戶開通了VIP,就使用h函數(shù)渲染傳入的組件。

否則就渲染OpenVipTip組件,他是引導(dǎo)用戶開通VIP的組件。

此時我們的父組件就應(yīng)該是下面這樣的:

<template>
  <EnhancedBlock1 />
</template>

<script setup lang="ts">
import Block1 from "./block1.vue";
import WithVip from "./with-vip.tsx";

const EnhancedBlock1 = WithVip(Block1);
</script>

這個代碼相比前面的hooks的實(shí)現(xiàn)就簡單很多了,只需要使用高階組件WithVip對原來的Block1組件包一層,然后將原本使用Block1的地方改為使用EnhancedBlock1。對原本的代碼基本沒有入侵。

上面的例子只是一個簡單的demo,他是不滿足我們實(shí)際的業(yè)務(wù)場景。比如子組件有props、emit、插槽。還有我們在父組件中可能會直接調(diào)用子組件expose暴露的方法。

因?yàn)槲覀兪褂昧薍OC對原本的組件進(jìn)行了一層封裝,那么上面這些場景HOC都是不支持的,我們需要添加一些額外的代碼去支持。

高階組件HOC實(shí)現(xiàn)props和emit

在Vue中屬性分為兩種,一種是使用props和emit聲明接收的屬性。第二種是未聲明的屬性attrs,比如class、style、id等。

在setup函數(shù)中props是作為第一個參數(shù)返回,attrs是第二個參數(shù)中返回。

所以為了能夠支持props和emit,我們的高階組件WithVip將會變成下面這樣:

import { SetupContext, h } from"vue";
import OpenVipTip from"./open-vip-tip.vue";

exportdefaultfunction WithVip(BaseComponent: any) {
return {
    props: BaseComponent.props,  // 新增代碼
    setup(props, { attrs, slots, expose }: SetupContext) {  // 新增代碼
      const showVipContent = getShowVipContent();
      function getShowVipContent() {
        // 一些業(yè)務(wù)邏輯判斷是否是VIP
        returntrue;
      }

      return() => {
        return showVipContent
          ? h(BaseComponent, {
              ...props, // 新增代碼
              ...attrs, // 新增代碼
            })
          : h(OpenVipTip);
      };
    },
  };
}

在setup方法中接收的第一個參數(shù)就是props,沒有在props中定義的屬性就會出現(xiàn)在attrs對象中。

所以我們調(diào)用h函數(shù)時分別將props和attrs透傳給子組件。

同時我們還需要一個地方去定義props,props的值就是直接讀取子組件對象中的BaseComponent.props。所以我們給高階組件聲明一個props屬性:props: BaseComponent.props,。

這樣props就會被透傳給子組件了。

看到這里有的小伙伴可能會問,那emit觸發(fā)事件沒有看見你處理呢?

答案是:我們無需去處理,因?yàn)楦附M件上面的@changeName="(value) => (name1 = value)"經(jīng)過編譯后就會變成屬性::notallow="(value) => (name1 = value)"。而這個屬性由于我們沒有在props中聲明,所以他會作為attrs直接透傳給子組件。

高階組件實(shí)現(xiàn)插槽

我們的正常子組件一般還有插槽,比如下面這樣:

<template>
  <div class="divider">
    <h1>{{ name }}</h1>
    <button @click="handleClick">change name</button>
    <slot />
    這里是block1的一些業(yè)務(wù)代碼
    <slot name="footer" />
  </div>
</template>

<script setup lang="ts">
const emit = defineEmits<{
  changeName: [name: string];
}>();

const props = defineProps<{
  name: string;
}>();

const handleClick = () => {
  emit("changeName", `hello ${props.name}`);
};

defineExpose({
  handleClick,
});
</script>

在上面的例子中,子組件有個默認(rèn)插槽和name為footer的插槽。此時我們來看看高階組件中如何處理插槽呢?

直接看代碼:

import { SetupContext, h } from"vue";
import OpenVipTip from"./open-vip-tip.vue";

exportdefaultfunction WithVip(BaseComponent: any) {
return {
    props: BaseComponent.props,
    setup(props, { attrs, slots, expose }: SetupContext) {
      const showVipContent = getShowVipContent();
      function getShowVipContent() {
        // 一些業(yè)務(wù)邏輯判斷是否是VIP
        returntrue;
      }

      return() => {
        return showVipContent
          ? h(
              BaseComponent,
              {
                ...props,
                ...attrs,
              },
              slots // 新增代碼
            )
          : h(OpenVipTip);
      };
    },
  };
}

插槽的本質(zhì)就是一個對象里面擁有多個方法,這些方法的名稱就是每個具名插槽,每個方法的參數(shù)就是插槽傳遞的變量。這里我們只需要執(zhí)行h函數(shù)時將slots對象傳給h函數(shù),就能實(shí)現(xiàn)插槽的透傳(如果你看不懂這句話,那就等歐陽下篇插槽的文章寫好后再來看這段話你就懂了)。

我們在控制臺中來看看傳入的slots插槽對象,如下圖:

圖片圖片

從上面可以看到插槽對象中有兩個方法,分別是default和footer,對應(yīng)的就是默認(rèn)插槽和footer插槽。

大家熟知h函數(shù)接收的第三個參數(shù)是children數(shù)組,也就是有哪些子元素。但是他其實(shí)還支持直接傳入slots對象,下面這個是他的一種定義:

export function h<P>(
  type: Component<P>,
  props?: (RawProps & P) | null,
  children?: RawChildren | RawSlots,
): VNode

export type RawSlots = {
  [name: string]: unknown
  // ...省略
}

所以我們可以直接把slots對象直接丟給h函數(shù),就可以實(shí)現(xiàn)插槽的透傳。

父組件調(diào)用子組件的方法

有的場景中我們需要在父組件中直接調(diào)用子組件的方法,按照以前的場景,我們只需要在子組件中expose暴露出去方法,然后在父組件中使用ref訪問到子組件,這樣就可以調(diào)用了。

但是使用了HOC后,中間層多了一個高階組件,所以我們不能直接訪問到子組件expose的方法。

怎么做呢?答案很簡單,直接上代碼:

import { SetupContext, h, ref } from"vue";
import OpenVipTip from"./open-vip-tip.vue";

exportdefaultfunction WithVip(BaseComponent: any) {
return {
    props: BaseComponent.props,
    setup(props, { attrs, slots, expose }: SetupContext) {
      const showVipContent = getShowVipContent();
      function getShowVipContent() {
        // 一些業(yè)務(wù)邏輯判斷是否是VIP
        returntrue;
      }

      // 新增代碼start
      const innerRef = ref();
      expose(
        newProxy(
          {},
          {
            get(_target, key) {
              return innerRef.value?.[key];
            },
            has(_target, key) {
              return innerRef.value?.[key];
            },
          }
        )
      );
      // 新增代碼end

      return() => {
        return showVipContent
          ? h(
              BaseComponent,
              {
                ...props,
                ...attrs,
                ref: innerRef,  // 新增代碼
              },
              slots
            )
          : h(OpenVipTip);
      };
    },
  };
}

在高階組件中使用ref訪問到子組件賦值給innerRef變量。然后expose一個Proxy的對象,在get攔截中讓其直接去執(zhí)行子組件中的對應(yīng)的方法。

比如在父組件中使用block1Ref.value.handleClick()去調(diào)用handleClick方法,由于使用了HOC,所以這里讀取的handleClick方法其實(shí)是讀取的是HOC中expose暴露的方法。所以就會走到Proxy的get攔截中,從而可以訪問到真正子組件中expose暴露的handleClick方法。

那么上面的Proxy為什么要使用has攔截呢?

答案是在Vue源碼中父組件在執(zhí)行子組件中暴露的方法之前會執(zhí)行這樣一個判斷:

if (key in target) {
  return target[key];
}

很明顯我們這里的Proxy代理的原始對象里面什么都沒有,執(zhí)行key in target肯定就是false了。所以我們可以使用has去攔截key in target,意思是只要訪問的方法或者屬性是子組件中expose暴露的就返回true。

至此,我們已經(jīng)在HOC中覆蓋了Vue中的所有場景。但是有的同學(xué)覺得h函數(shù)寫著比較麻煩,不好維護(hù),我們還可以將上面的高階組件改為tsx的寫法,with-vip.tsx文件代碼如下:

import { SetupContext, ref } from"vue";
import OpenVipTip from"./open-vip-tip.vue";

exportdefaultfunction WithVip(BaseComponent: any) {
return {
    props: BaseComponent.props,
    setup(props, { attrs, slots, expose }: SetupContext) {
      const showVipContent = getShowVipContent();
      function getShowVipContent() {
        // 一些業(yè)務(wù)邏輯判斷是否是VIP
        returntrue;
      }

      const innerRef = ref();
      expose(
        newProxy(
          {},
          {
            get(_target, key) {
              return innerRef.value?.[key];
            },
            has(_target, key) {
              return innerRef.value?.[key];
            },
          }
        )
      );

      return() => {
        return showVipContent ? (
          <BaseComponent {...props} {...attrs} ref={innerRef}>
            {slots}
          </BaseComponent>
        ) : (
          <OpenVipTip />
        );
      };
    },
  };
}

一般情況下h函數(shù)能夠?qū)崿F(xiàn)的,使用jsx或者tsx都能實(shí)現(xiàn)(除非你需要操作虛擬DOM)。

注意上面的代碼是使用ref={innerRef},而不是我們熟悉的ref="innerRef",這里很容易搞錯!!

compose函數(shù)

此時你可能有個新需求,需要給某些模塊顯示不同的折扣信息,這些模塊可能會和上一個會員需求的模塊有重疊。此時就涉及到多個高階組件之間的組合情況。

同樣我們使用HOC去實(shí)現(xiàn),新增一個WithDiscount高階組件,代碼如下:

import { SetupContext, onMounted, ref } from"vue";

exportdefaultfunction WithDiscount(BaseComponent: any, item: string) {
return {
    props: BaseComponent.props,
    setup(props, { attrs, slots, expose }: SetupContext) {
      const discountInfo = ref("");

      onMounted(async () => {
        const res = await getDiscountInfo(item);
        discountInfo.value = res;
      });

      function getDiscountInfo(item: any): Promise<string> {
        // 根據(jù)傳入的item獲取折扣信息
        returnnewPromise((resolve) => {
          setTimeout(() => {
            resolve("我是折扣信息1");
          }, 1000);
        });
      }

      const innerRef = ref();
      expose(
        newProxy(
          {},
          {
            get(_target, key) {
              return innerRef.value?.[key];
            },
            has(_target, key) {
              return innerRef.value?.[key];
            },
          }
        )
      );

      return() => {
        return (
          <div class="with-discount">
            <BaseComponent {...props} {...attrs} ref={innerRef}>
              {slots}
            </BaseComponent>
            {discountInfo.value ? (
              <div class="discount-info">{discountInfo.value}</div>
            ) : null}
          </div>
        );
      };
    },
  };
}

那么我們的父組件如果需要同時用VIP功能和折扣信息功能需要怎么辦呢?代碼如下:

const EnhancedBlock1 = WithVip(WithDiscount(Block1, "item1"));

如果不是VIP,那么這個模塊的折扣信息也不需要顯示了。

因?yàn)楦唠A組件接收一個組件,然后返回一個加強(qiáng)的組件。利用這個特性,我們可以使用上面的這種代碼將其組合起來。

但是上面這種寫法大家覺得是不是看著很難受,一層套一層。如果這里同時使用5個高階組件,這里就會套5層了,那這個代碼的維護(hù)難度就是地獄難度了。

所以這個時候就需要compose函數(shù)了,這個是React社區(qū)中常見的概念。它的核心思想是將多個函數(shù)從右到左依次組合起來執(zhí)行,前一個函數(shù)的輸出作為下一個函數(shù)的輸入。

我們這里有多個HOC(也就是有多個函數(shù)),我們期望執(zhí)行完第一個HOC得到一個加強(qiáng)的組件,然后以這個加強(qiáng)的組件為參數(shù)去執(zhí)行第二個HOC,最后得到由多個HOC加強(qiáng)的組件。

compose函數(shù)就剛好符合我們的需求,這個是使用compose函數(shù)后的代碼,如下:

const EnhancedBlock1 = compose(WithVip, WithDiscount("item1"))(Block1);

這樣就舒服多了,所有的高階組件都放在第一個括弧里面,并且由右向左去依次執(zhí)行每個高階組件HOC。如果某個高階組件HOC需要除了組件之外的額外參數(shù),像WithDiscount這樣處理就可以了。

很明顯,我們的WithDiscount高階組件的代碼需要修改才能滿足compose函數(shù)的需求,這個是修改后的代碼:

import { SetupContext, onMounted, ref } from"vue";

exportdefaultfunction WithDiscount(item: string) {
return(BaseComponent: any) => {
    return {
      props: BaseComponent.props,
      setup(props, { attrs, slots, expose }: SetupContext) {
        const discountInfo = ref("");

        onMounted(async () => {
          const res = await getDiscountInfo(item);
          discountInfo.value = res;
        });

        function getDiscountInfo(item: any): Promise<string> {
          // 根據(jù)傳入的item獲取折扣信息
          returnnewPromise((resolve) => {
            setTimeout(() => {
              resolve("我是折扣信息1");
            }, 1000);
          });
        }

        const innerRef = ref();
        expose(
          newProxy(
            {},
            {
              get(_target, key) {
                return innerRef.value?.[key];
              },
              has(_target, key) {
                return innerRef.value?.[key];
              },
            }
          )
        );

        return() => {
          return (
            <div class="with-discount">
              <BaseComponent {...props} {...attrs} ref={innerRef}>
                {slots}
              </BaseComponent>
              {discountInfo.value ? (
                <div class="discount-info">{discountInfo.value}</div>
              ) : null}
            </div>
          );
        };
      },
    };
  };
}

注意看,WithDiscount此時只接收一個參數(shù)item,不再接收BaseComponent組件對象了,然后直接return出去一個回調(diào)函數(shù)。

準(zhǔn)確的來說此時的WithDiscount函數(shù)已經(jīng)不是高階組件HOC了,他return出去的回調(diào)函數(shù)才是真正的高階組件HOC。在回調(diào)函數(shù)中去接收BaseComponent組件對象,然后返回一個增強(qiáng)后的Vue組件對象。

至于參數(shù)item,因?yàn)殚]包所以在里層的回調(diào)函數(shù)中還是能夠訪問的。這里比較繞,可能需要多理解一下。

前面的理解完了后,我們可以再上一點(diǎn)強(qiáng)度了。來看看compose函數(shù)是如何實(shí)現(xiàn)的,代碼如下:

function compose(...funcs) {
  return funcs.reduce((acc, cur) => (...args) => acc(cur(...args)));
}

這個函數(shù)雖然只有一行代碼,但是乍一看,怎么看怎么懵逼,歐陽也是?。∥覀冞€是結(jié)合demo來看:

const EnhancedBlock1 = compose(WithA, WithB, WithC, WithD)(View);

假如我們這里有WithA、WithB、 WithC、 WithD四個高階組件,都是用于增強(qiáng)組件View。

compose中使用的是...funcs將調(diào)用compose函數(shù)接收到的四個高階組件都存到了funcs數(shù)組中。

然后使用reduce去遍歷這些高階組件,注意看執(zhí)行reduce時沒有傳入第二個參數(shù)。

所以第一次執(zhí)行reduce時,acc的值為WithA,cur的值為WithB。返回結(jié)果也是一個回調(diào)函數(shù),將這兩個值填充進(jìn)去就是(...args) => WithA(WithB(...args)),我們將第一次的執(zhí)行結(jié)果命名為r1。

我們知道reduce會將上一次的執(zhí)行結(jié)果賦值為acc,所以第二次執(zhí)行reduce時,acc的值為r1,cur的值為WithC。返回結(jié)果也是一個回調(diào)函數(shù),同樣將這兩個值填充進(jìn)行就是(...args) => r1(WithC(...args))。同樣我們將第二次的執(zhí)行結(jié)果命名為r2。

第三次執(zhí)行reduce時,此時的acc的值為r2,cur的值為WithD。返回結(jié)果也是一個回調(diào)函數(shù),同樣將這兩個值填充進(jìn)行就是(...args) => r2(WithD(...args))。同樣我們將第三次的執(zhí)行結(jié)果命名為r3,由于已經(jīng)將數(shù)組遍歷完了,最終reduce的返回值就是r3,他是一個回調(diào)函數(shù)。

由于compose(WithA, WithB, WithC, WithD)的執(zhí)行結(jié)果為r3,那么compose(WithA, WithB, WithC, WithD)(View)就等價于r3(View)。

前面我們知道r3是一個回調(diào)函數(shù):(...args) => r2(WithD(...args)),這個回調(diào)函數(shù)接收的參數(shù)args,就是需要增強(qiáng)的基礎(chǔ)組件View。所以執(zhí)行這個回調(diào)函數(shù)就是先執(zhí)行WithD對組件進(jìn)行增強(qiáng),然后將增強(qiáng)后的組件作為參數(shù)去執(zhí)行r2。

同樣r2也是一個回調(diào)函數(shù):(...args) => r1(WithC(...args)),接收上一次WithD增強(qiáng)后的組件為參數(shù)執(zhí)行WithC對組件再次進(jìn)行增強(qiáng),然后將增強(qiáng)后的組件作為參數(shù)去執(zhí)行r1。

同樣r1也是一個回調(diào)函數(shù):(...args) => WithA(WithB(...args)),將WithC增強(qiáng)后的組件丟給WithB去執(zhí)行,得到增強(qiáng)的組件再丟給WithA去執(zhí)行,最終就拿到了最后增強(qiáng)的組件。

執(zhí)行順序就是從右向左去依次執(zhí)行高階組件對基礎(chǔ)組件進(jìn)行增強(qiáng)。

至此,關(guān)于compose函數(shù)已經(jīng)講完了,這里對于Vue的同學(xué)可能比較難理解,建議多看兩遍。

總結(jié)

這篇文章我們講了在Vue3中如何實(shí)現(xiàn)一個高階組件HOC,但是里面涉及到了很多源碼知識,所以這是一篇運(yùn)用源碼的實(shí)戰(zhàn)文章。如果你理解了文章中涉及到的知識,那么就會覺得Vue中實(shí)現(xiàn)HOC還是很簡單的,反之就像是在看天書。

還有最重要的一點(diǎn)就是Composition API已經(jīng)能夠解決絕大部分的問題,只有少部分的場景才需要使用高階組件HOC,切勿強(qiáng)行使用HOC,那樣可能會有炫技的嫌疑。如果是防御性編程,那么就當(dāng)我沒說。

最后就是我們實(shí)現(xiàn)的每個高階組件HOC都有很多重復(fù)的代碼,而且實(shí)現(xiàn)起來很麻煩,心智負(fù)擔(dān)也很高。那么我們是不是可以抽取一個createHOC函數(shù)去批量生成高階組件呢?這個就留給各位自己去思考了。

還有一個問題,我們這種實(shí)現(xiàn)的高階組件叫做正向?qū)傩源?,弊端是每代理一層就會增加一層組件的嵌套。那么有沒有方法可以解決嵌套的問題呢?

答案是反向繼承,但是這種也有弊端如果業(yè)務(wù)是setup中返回的render函數(shù),那么就沒法重寫了render函數(shù)了。

責(zé)任編輯:武曉燕 來源: 前端歐陽
相關(guān)推薦

2020-07-14 08:43:54

VueHTML函數(shù)

2020-10-28 08:06:09

Vue3框架數(shù)據(jù)

2020-07-08 12:44:00

大數(shù)據(jù)IT互聯(lián)網(wǎng)

2022-12-07 08:16:50

Vue 3技巧數(shù)組

2021-01-12 12:33:20

Pandas技巧代碼

2021-07-14 11:25:12

CSSPosition定位

2022-06-23 13:13:36

GitHub開發(fā)技巧

2020-06-29 08:28:36

v-for 解構(gòu)函數(shù)

2025-04-16 07:06:43

2021-01-15 05:39:13

HashMapHashTableTreeMap

2021-11-02 19:14:58

Spring數(shù)據(jù)

2020-07-07 08:35:53

VueKey組件

2021-09-07 11:20:02

binlogMySQL數(shù)據(jù)庫

2018-06-28 08:40:23

Raid機(jī)械硬盤

2024-01-08 07:11:35

2021-08-04 08:31:10

MySQL數(shù)據(jù)庫日志

2021-08-08 21:53:40

Arthas指令表達(dá)式

2024-11-06 08:32:02

JavaScriptTypeScript數(shù)據(jù)結(jié)構(gòu)

2024-05-27 08:39:17

Vue3變量響應(yīng)式

2021-12-16 08:27:54

Vue3 插件Vue應(yīng)用
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號