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

vue-class-setup?編寫?class?風(fēng)格組合式API

 更新時間:2022年09月23日 09:05:57   作者:狼族小狽  
這篇文章主要為大家介紹了vue-class-setup?編寫?class?風(fēng)格組合式API,支持Vue2和Vue3,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

前言

我司基于vue-class-component開發(fā)的項目有上百個,其中部署的 SSR 服務(wù)也接近100個,如此龐大體量的項目一開始的時候還幻想著看看是否要升級Vue3,結(jié)果調(diào)研一番下來,才發(fā)現(xiàn)vue-class-component對Vue3的支持,最后一個版本發(fā)布都過去兩年了,遲遲還沒有發(fā)布正式版本。目前基本上處于無人維護的狀態(tài),而且升級存在著大量的破壞性更新,對于未來是否還要繼續(xù)使用Vue3現(xiàn)在還是持保留意見,但是不妨礙我們先把組件庫做成Vue2和Vue3通用,于是就有了本文。

在過去的三年里,vue-class-component最大的問題是就是無法正確的校驗組件的傳參,事件類型,這給我?guī)砹司薮蟮年幱?,在?jīng)過一番調(diào)研后,驚喜的發(fā)現(xiàn)使用defineComponent定義的組件,在Vue2.7和3.x都可以正確的識別類型,所以先計劃內(nèi)部的組件庫先做到同時支持Vue2和Vue3,如果后面還要繼續(xù)采用Vue3就變得容易得多。

于是,回到了開頭,調(diào)研了一番vue-class-component在Vue3的支持,目前最新的版本是8.0.0-rc.1,結(jié)果大失所望,目前基本上處于無人維護的狀態(tài),社區(qū)內(nèi)又沒有一個能滿足我需求的,同時支持Vue2和Vue3的。

誕生想法

鑒于vue-class-component組件目前無法做到正確的組件類型檢驗,當(dāng)我驚喜的發(fā)現(xiàn)組合式API寫出來的代碼可以被正確的識別類型時,誕生了一個使用 class 風(fēng)格來編寫組合式API的想法,于是花費一個月的實踐,踩遍了所有的坑,終于誕生了vue-class-setup,一個使用 class 風(fēng)格來編寫代碼的庫,它gzip壓縮后,1kb大小。

快速開始

npm install vue-class-setup
<script lang="ts">
import { defineComponent } from 'vue';
import { Setup, Context } from 'vue-class-setup';
// Setup 和 Context 必須一起工作
@Setup
class App extends Context {
    private _value = 0;
    public get text() {
        return String(this._value);
    }
    public set text(text: string) {
        this._value = Number(text);
    }
    public onClick() {
        this._value++;
    }
}
export default defineComponent({
    // 注入類實例的邏輯
    ...App.inject(),
});
</script>
<template>
    <div>
        <p>{{ text }}</p>
        <button @click="onClick()"></button>
    </div>
</template>

嘗試多很多種方案,最終采用了上面的形式為最佳實踐,它無法做到export default直接導(dǎo)出一個類,必須使用defineComponent 來包裝一層,因為它只是一個組合類(API),并非是一個組件。

最佳實踐

<script lang="ts">
import { defineComponent } from 'vue';
import { Setup, Define } from 'vue-class-setup';
// 傳入組件的 Props 和 Emit,來讓組合類獲取正確的 `Props` 和 `Emit` 類型
@Setup
class App extends Define<Props, Emit> {
    // ? 你可以直接這里定義Props的默認值,不需要像 vue-property-decorator 那樣使用一個 Prop 裝飾器來定義
    public readonly dest = '--';
    // 自動轉(zhuǎn)換成 Vue 的 'computed'
    public get text() {
        return String(this.value);
    }
    public click(evt: MouseEvent) {
        // 發(fā)射事件,可以正確的識別類型
        this.$emit('click', evt);
    }
}
/**
 * 這里提供了另外一種在 setup 函數(shù)中使用的例子,默認推薦使用 `defineComponent`
 * 如果有多個類實例,也可以在 setup 中實例化類
 * <script lang="ts" setup>
 *      const app = new App();
 * <\/script>
 * <template>
 *      <div>{{ app.text }}</div>
 * </template>
 */
export default defineComponent({
    ...App.inject(),
});
</script>
<script lang="ts" setup>
// 如果在 setup 中定義類型,需要導(dǎo)出一下
export interface Props {
    value: number;
    dest?: string;
}
export interface Emit {
    (event: 'click', evt: MouseEvent): void;
}
// 這里不再需要使用變量來接收,可以利用 Vue 的編譯宏來為組件生成正確的 Props 和 Emit
// ? const props = defineProps<Props>();
// ? const emit = defineEmits<Emit>();
defineProps<Props>(); //  ?
defineEmits<Emit>(); //  ?
// 這種默認值的定義,也不再推薦,而是直接在類上聲明
// ? withDefaults(defineProps<Props>(), { dest: '--' });
// ? @Setup
// ? class App extends Define<Props, Emit> {
// ?     public readonly dest = '--'
// ? }
// Setup 裝飾器,會在類實例化時,自動 使用 reactive 包裝類,
// 如果你在 setup 手動實例化,則不需要再執(zhí)行一次 reactive 
// const app = reactive(new App()); // ?
// const app = new App();           // ?
</script>
<template>
    <button class="btn" @click="click($event)">
        <span class="text">{{ text }}</span>
        <span class="props-dest">{{ dest }}</span>
        <span class="props-value">{{ $props.value }}</span>
    </button>
</template>

多個類實例

在一些復(fù)雜的業(yè)務(wù)時,有時需要多個實例

<script lang="ts">
import { onBeforeMount, onMounted } from 'vue';
import { Setup, Context, PassOnTo } from 'vue-class-setup';
@Setup
class Base extends Context {
    public value = 0;
    public get text() {
        return String(this.value);
    }
    @PassOnTo(onBeforeMount)
    public init() {
        this.value++;
    }
}
@Setup
class Left extends Base {
    public left = 0;
    public get text() {
        return String(`value:${this.value}`);
    }
    public init() {
        super.init();
        this.value++;
    }
    @PassOnTo(onMounted)
    public initLeft() {
        this.left++;
    }
}
@Setup
class Right extends Base {
    public right = 0;
    public init() {
        super.init();
        this.value++;
    }
    @PassOnTo(onMounted)
    public initLeft() {
        this.right++;
    }
}
</script>
<script setup lang="ts">
const left = new Left();
const right = new Right();
</script>
<template>
    <p class="left">{{ left.text }}</p>
    <p class="right">{{ right.text }}</p>
</template>

PassOnTo

在類實例準(zhǔn)備就緒后,PassOnTo 裝飾器,會將對應(yīng)的函數(shù),傳遞給回調(diào),這樣我們就可以順利的和 onMounted 等鉤子一起配合使用了

import { onMounted } from 'vue';
@Setup
class App extends Define {
    @PassOnTo(onMounted)
    public onMounted() {}
}

Watch

在使用 vue-property-decoratorWatch 裝飾器時,他會接收一個字符串類型,它不能正確的識別類實例是否存在這個字段,但是現(xiàn)在 vue-class-setup 能檢查你的類型是否正確,如果傳入一個類實例不存在的字段,類型將會報錯

<script lang="ts">
import { Setup, Watch, Context } from 'vue-class-setup';
@Setup
class App extends Context {
    public value = 0;
    public immediateValue = 0;
    public onClick() {
        this.value++;
    }
    @Watch('value')
    public watchValue(value: number, oldValue: number) {
        if (value > 100) {
            this.value = 100;
        }
    }
    @Watch('value', { immediate: true })
    public watchImmediateValue(value: number, oldValue: number | undefined) {
        if (typeof oldValue === 'undefined') {
            this.immediateValue = 10;
        } else {
            this.immediateValue++;
        }
    }
}
</script>
<script setup lang="ts">
const app = new App();
</script>
<template>
    <p class="value">{{ app.value }}</p>
    <p class="immediate-value">{{ app.immediateValue }}</p>
    <button @click="app.onClick()">Add</button>
</template>

defineExpose

在一些場景,我們希望可以暴露組件的一些方法和屬性,那么就需要使用 defineExpose 編譯宏來定義導(dǎo)出了,所以提供了一個.use的類靜態(tài)方法幫你獲取當(dāng)前注入的類實例

<script lang="ts">
import { defineComponent } from 'vue';
import { Setup, Context } from 'vue-class-setup';
@Setup
class App extends Context {
    private _value = 0;
    public get text() {
        return String(this._value);
    }
    public set text(text: string) {
        this._value = Number(text);
    }
    public addValue() {
        this._value++;
    }
}
export default defineComponent({
    ...App.inject(),
});
</script>
<script lang="ts" setup>
const app = App.use();
defineExpose({
    addValue: app.addValue,
});
</script>
<template>
    <div>
        <p class="text">{{ text }}</p>
        <p class="text-eq">{{ app.text === text }}</p>
        <button @click="addValue"></button>
    </div>
</template>

為什么使用 class ?

其實不太想討論這個問題,喜歡的自然會喜歡,不喜歡的自然會不喜歡,世上本無路,走的人多了,就有了路。

最后

不管是 選項 API 還是 組合式API,代碼都是人寫出來的,別人都說 Vue 無法勝任大型項目,但是在我司的實踐中經(jīng)受住了實踐,基本上沒有產(chǎn)生那種數(shù)千行的組件代碼。

如果喜歡使用 class 風(fēng)格來編寫代碼的,不妨來關(guān)注一下

如果你的業(yè)務(wù)復(fù)雜,需要使用 SSR 和微服務(wù)架構(gòu),不妨也關(guān)注一下

以上就是vue-class-setup 編寫 class 風(fēng)格組合式API的詳細內(nèi)容,更多關(guān)于vue-class-setup 編寫組合式API的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue長按事件touch示例詳解

    vue長按事件touch示例詳解

    這篇文章主要介紹了vue長按事件touch,文末給大家補充介紹了Vue長按觸摸事件的實現(xiàn)代碼,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • vue項目使用cdn加速減少webpack打包體積

    vue項目使用cdn加速減少webpack打包體積

    通過壓縮代碼的手段可減小網(wǎng)絡(luò)傳輸?shù)拇笮?但實際上最影響用戶體驗的還是網(wǎng)頁首次打開時的加載等待,其根本原因是網(wǎng)絡(luò)傳輸過程耗時較大,這篇文章主要給大家介紹了關(guān)于vue項目使用cdn加速減少webpack打包體積的相關(guān)資料,需要的朋友可以參考下
    2022-08-08
  • VUE利用vuex模擬實現(xiàn)新聞點贊功能實例

    VUE利用vuex模擬實現(xiàn)新聞點贊功能實例

    本篇文章主要介紹了VUE利用vuex模擬實現(xiàn)新聞點贊功能實例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Vue中的MVVM模式使用及說明

    Vue中的MVVM模式使用及說明

    這篇文章主要介紹了Vue中的MVVM模式使用及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • vue學(xué)習(xí)之Vue-Router用法實例分析

    vue學(xué)習(xí)之Vue-Router用法實例分析

    這篇文章主要介紹了vue學(xué)習(xí)之Vue-Router用法,結(jié)合實例形式分析了Vue-Router路由原理與常見操作技巧,需要的朋友可以參考下
    2020-01-01
  • vue2.0使用swiper組件實現(xiàn)輪播效果

    vue2.0使用swiper組件實現(xiàn)輪播效果

    這篇文章主要為大家詳細介紹了vue2.0使用swiper組件實現(xiàn)輪播效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • vue如何通過src引用assets中的圖片

    vue如何通過src引用assets中的圖片

    這篇文章主要介紹了vue如何通過src引用assets中的圖片,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 淺析vue-router實現(xiàn)原理及兩種模式

    淺析vue-router實現(xiàn)原理及兩種模式

    這篇文章主要介紹了vue-router實現(xiàn)原理及兩種模式分析,給大家介紹了vue-router hash模式與history模式不同模式下處理邏輯,需要的朋友可以參考下
    2020-02-02
  • vue3使用elementPlus進行table合并處理的示例詳解

    vue3使用elementPlus進行table合并處理的示例詳解

    虛擬數(shù)據(jù)中公司下有多個客戶,公司一樣的客戶,公司列需要合并,客戶如果一樣也需要合并進行展示,所以本文給大家介紹了vue3使用elementPlus進行table合并處理的實例,文中通過代碼示例介紹的非常詳細,需要的朋友可以參考下
    2024-02-02
  • vue項目如何通過url鏈接引入其他系統(tǒng)頁面

    vue項目如何通過url鏈接引入其他系統(tǒng)頁面

    這篇文章主要介紹了vue項目如何通過url鏈接引入其他系統(tǒng)頁面問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03

最新評論

亳州市| 宁明县| 邵武市| 玉溪市| 读书| 阜宁县| 云浮市| 嘉荫县| 靖边县| 新营市| 莒南县| 台中县| 株洲县| 洛扎县| 武陟县| 双流县| 龙海市| 保山市| 绥滨县| 德化县| 浠水县| 开封县| 沅江市| 福泉市| 毕节市| 商洛市| 介休市| 酒泉市| 司法| 阿尔山市| 上思县| 平利县| 梁河县| 深水埗区| 子长县| 渭源县| 保康县| 柳州市| 山阴县| 深水埗区| 巫溪县|