vue3常用api盤點及現(xiàn)有vue2組件遷移示例

vue3.png

前言:

vue3項目是在兩年前開始的提针,正式版3.0于2020年9月發(fā)布豆同;
目前vue生態(tài)支持情況還不完善橘蜜,如vuex4還處于rc版本,并存在一定的bug垄分,暫不推薦大家用在標準版項目里宛篇;
不過那些無關(guān)緊要的項目必須可以試試;
再者vue3的官方生態(tài)包為了讓打包后的文件盡可能的小锋喜,打包文件都輸出了ECMASCRIPT新語法些己,這就是網(wǎng)上吹牛逼說的vue3更快、更泻侔恪段标;

一、生命周期

  1. beforeCreate -> setup()
  2. created -> setup()
  3. beforeMount -> onBeforeMount // 在掛載前執(zhí)行某些代碼
  4. mounted -> onMounted // 在掛載后執(zhí)行某些代碼
  5. beforeUpdate -> onBeforeUpdate // 在更新前前執(zhí)行某些代碼
  6. updated -> onUpdated // 在更新后執(zhí)行某些代碼
  7. beforeDestroy -> onBeforeUnmount // 在組件銷毀前執(zhí)行某些代碼
  8. destroyed -> onUnmounted // 在組件銷毀后執(zhí)行某些代碼
  9. errorCaptured -> onErrorCaptured // 錯誤捕獲

二炉奴、常用api

!中文文檔(https://www.vue3js.cn/docs/zh/api/global-api.html#createapp)

  1. ref
  2. reactive
  3. watch
  4. computed
  5. nextTick
  6. props

三逼庞、vite創(chuàng)建vue3項目

文檔地址(https://vitejs.dev/guide/#scaffolding-your-first-vite-project)

  • npm init @vitejs/app my-vue-app --template vue
  • cd .\my-vue-app\
  • npm install
  1. ref演示


    ref.gif
<template>
  <button @click="state++">count is: {{ state }}</button>
</template>

<script setup>
import { ref } from 'vue'

const state = ref(0)
</script>
  • 提示:獲取dom也需要ref
  • 思考1:怎么用ref獲取dom
  1. reactive演示


    reactive.gif
<template>
  <button @click="state.count++">count is: {{ state.count }}</button>
</template>

<script setup>
import { reactive } from 'vue'

const state = reactive({ count: 0 })
</script>
  • 思考2:以上可以看出,如果用reactive聲明n個變量瞻赶,在dom中使用都要加上state.xxx赛糟,豈不是很麻煩,
    現(xiàn)在我要這樣的效果 <div>count is: {{ count }}</div>砸逊,您會怎么做璧南?
  1. watch演示


    watch.gif
<template>
    <div>reactive</div>
  <button @click="state.count ++">count is: {{ state.count }}</button>
    <div>{{ state.text }}</div>
</template>

<script setup>
import { reactive, watch } from 'vue'

const state = reactive({
    count: 0,
    text: 'ready'
})

watch(() => state.count, (n, o) => {
    if (n > 5) state.text = '大哥,別點了师逸,count大于5了';
    else state.text = 'count小于5';
});
</script>
  • 思考3:
    1. 我想同時監(jiān)聽多個變量司倚,該怎么做
    2. 深度監(jiān)聽,初始化執(zhí)行,該怎么配置參數(shù)

4.computed演示


computed.gif
<template>
    <div>computed</div>
  <button @click="state.count ++">count is: {{ state.count }}</button>
    <div>{{ doubleCount }}</div>
</template>

<script setup>
import { reactive, computed } from 'vue'

const state = reactive({
    count: 0
})

const doubleCount = computed(() => (state.count * 2))
</script>
  1. nextTick演示


    nextTick.gif
<template>
    <div>nextTick</div>
  <button @click="countClick">count is: {{ state.count }}</button>
    <div v-if="state.count" id="divEle">{{ state.doubleCount }}</div>
</template>

<script setup>
import { reactive, nextTick } from 'vue'

const state = reactive({
    count: 0,
    doubleCount: 0
})

const countClick = () => {
    state.count ++

    nextTick(() => {
        state.doubleCount = state.count * 2
        const divEle2 = document.getElementById('divEle')
        console.log('divEle2::', divEle2);
    });

    const divEle1 = document.getElementById('divEle')
    console.log('divEle1::', divEle1);
}
</script>
  1. props演示


    props.png
<template>
    <div>defineProps</div>
    <div>{{ msg }}</div>
</template>

<script setup>
import { reactive, defineProps } from 'vue'

defineProps({
    msg: String
})

const state = reactive({
    count: 0,
})

</script>
  1. 以上看著不習(xí)慣动知,setup還可以這樣寫
<template>
    <div>defineProps</div>
    <div>{{ msg }}</div>
</template>

<script>
import { reactive, defineProps } from 'vue'
export default {
    props: ['msg'],
    setup() {
       const state = reactive({
          count: 0,
      })
      
      return { state }
    }
}
</script>

四皿伺、vite打包信息

vite-build.png
  • vite打包是杠杠的大拇指
  • 但是,vite打包雖然小盒粮,單并不支持ie鸵鸥,目前在咱們項目中無法使用

五、Breadcrumb 面包屑遷移

完全遷移(composition api jsx篇)

  1. 遷移前
<template>
    <div class="p-breadcrumb">
        <section class="p-breadcrumb-item" v-for="(item, i) in data" :key="i+'-'+item.id">
            <article
                    :class="[
                        'p-breadcrumb-item-text',
                        (value?value===item.id:i===data.length-1)&&'p-breadcrumb-item-active',
                        (i>0&&i<data.length-1)&&'p-breadcrumb-item-width',
                        (i===data.length-1)&&'p-breadcrumb-item-max-width'
                    ]"
                    v-ptitle:isText:true="item.name"
                    @click="breadcrumbClick(item.id)"
                    @mouseenter="TextEllipsis"
            >{{item.name}}</article>
            <article class="p-breadcrumb-arrow" v-if="i<data.length-1">
                <ArrowRight />
            </article>
        </section>
    </div>
</template>

<script>
import ArrowRight from '../static/iconSvg/arrow_right.svg';
import TextEllipsis from '../static/utils/TextEllipsis';

export default {
    name: 'Breadcrumb',
    components: { ArrowRight },
    props: {
        // 數(shù)據(jù)列表
        data: {
            type: Array,
            default: () => []
        },
        // 當前高亮顯示的id
        value: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            titleShow: false // 是否顯示title
        };
    },
    methods: {
        TextEllipsis,
        /**
         * 點擊某項執(zhí)行的鉤子
         * @param id
         */
        breadcrumbClick(id) {
            if (this.value) this.$emit('input', id);
        }
    }
};
</script>
  1. 遷移后
import { defineComponent } from 'vue';
import TextEllipsis from '../static/utils/TextEllipsis';

import ArrowRight from '../static/iconSvg/arrow_right.svg';

const ArrowRightDom = (
    <article className="p-breadcrumb-arrow">
        <ArrowRight/>
    </article>
);

const Breadcrumb = defineComponent({
    name: 'Breadcrumb',
    props: {
        // 數(shù)據(jù)列表
        data: {
            type: Array,
            default: () => []
        },
        // 當前高亮顯示的id
        modelValue: {
            type: String,
            default: ''
        }
    },
    emits: ['change', 'update:modelValue'],
    setup(props, { emit }) {
        const breadcrumbClick = (id) => {
            if (props.modelValue) emit('update:modelValue', id);
            else emit('change', id);
        };
        return () => {
            const { data, modelValue } = props;
            return (
                <div class="p-breadcrumb">
                    {
                        data.map((item, i) => (
                            <section class="p-breadcrumb-item" key={`${i}-${item.id}`}>
                                <article class={{
                                    'p-breadcrumb-item-text': true,
                                    'p-breadcrumb-item-active': (modelValue ? modelValue === item.id : i === data.length - 1),
                                    'p-breadcrumb-item-width': (i > 0 && i < props.data.length - 1),
                                    'p-breadcrumb-item-max-width': (i === data.length - 1)
                                }}
                                onClick={() => breadcrumbClick(item.id)}
                                onMouseEnter={TextEllipsis}
                                >{item.name}</article>
                                {(i < data.length - 1) && <ArrowRightDom/>}
                            </section>
                        ))
                    }
                </div>
            );
        };
    }
});
  1. 注意
    • class類名的綁定 - 與react中不一樣的是丹皱,vue中支持對象宰翅、數(shù)組
    • props - 必須接收
    • emits - 需申明提交方式
    • 事件 - 事件綁定需要on...開頭

保守遷移(option api)

<template>
    <div class="p-breadcrumb">
        <section class="p-breadcrumb-item" v-for="(item, i) in data" :key="i+'-'+item.id">
            <article
                    :class="[
                        'p-breadcrumb-item-text',
                        (modelValue?modelValue===item.id:i===data.length-1)&&'p-breadcrumb-item-active',
                        (i>0&&i<data.length-1)&&'p-breadcrumb-item-width',
                        (i===data.length-1)&&'p-breadcrumb-item-max-width'
                    ]"
                    @click="breadcrumbClick(item.id)"
                    @mouseenter="TextEllipsis"
            >{{item.name}}</article>
            <article class="p-breadcrumb-arrow" v-if="i<data.length-1">
                <ArrowRight />
            </article>
        </section>
    </div>
</template>

<script>
import ArrowRight from '../static/iconSvg/arrow_right.svg';
import TextEllipsis from '../static/utils/TextEllipsis';

export default {
    name: 'Breadcrumb',
    components: { ArrowRight },
    props: {
        /**
         * 數(shù)據(jù)列表
         */
        data: {
            type: Array,
            default: () => []
        },
        /**
         * 當前高亮顯示的id
         */
        modelValue: {
            type: String,
            default: ''
        }
    },
    emit: ['update:modelValue'],
    data() {
        return {
            titleShow: false // 是否顯示title
        };
    },
    methods: {
        TextEllipsis,
        /**
         * 點擊某項執(zhí)行的鉤子
         * @param id
         */
        breadcrumbClick(id) {
            if (this.modelValue) this.$emit('update:modelValue', id);
        }
    }
};
</script>
  • 問題:
    vue3當中很多廢棄api瓶珊,不能保證所有組件遷移成功(研究中)

六伞芹、v-model與v-show寫法

v-model.png
  • 截圖來之某乎,大家可以下去試下胸遇,在jsx中并沒什么ly
.vue v-show v-model v-model:title v-model:title.func
.jsx v-show v-model v-model={[val, 'title']} v-model={[val, 'title', ['func']]}

七、全局變量

版本 變量 獲取
vue2 Vue.prototype.$xxx = xxx this.$xxx
vue3 app.config.globalProperties.$xxx = xxx getCurrentInstance().ctx.$xxx

八逗威、兩個好玩的組件

  1. Teleport 傳送門

    • 有這樣的場景,我們在做業(yè)務(wù)的時候咐蚯,經(jīng)常會遇到層級(z-index)問題春锋、或者我們項把組件掛在到body下
      示例:
         <Teleport to="body">
             <div>xxx</div>
         </Teleport>
      

    其中to參數(shù)值可以指向任何一個容器(容器建議具有唯一性)

  2. Suspense 用作處理異步占位

    • 最常見的當數(shù)據(jù)沒有回來時我們需要一個占位內(nèi)容危尿,通常是loading或骨架屏
      示例:
            <Suspense>
                <template #default>
                    <div>主內(nèi)容(異步加載內(nèi)容)</div>
                </template>
                <template #fallback>
                    <div>loading</div>
                </template>
            </Suspense>
      

    此處為固定寫法济欢,目前官網(wǎng)文檔還不完善法褥,且Suspense api可能會改變,別問為什么我知道莽囤,網(wǎng)上抄的

九蔚舀、以上思考問題回復(fù)

  1. 思考1:怎么用ref獲取dom
    回復(fù):
       const dom = ref(null);
       <div ref={dom}></div>
    
  2. 思考2:以上可以看出礼患,如果用reactive聲明n個變量是钥,在dom中使用都要加上state.xxx掠归,豈不是很麻煩,
    現(xiàn)在我要這樣的效果 <div>count is: {{ count }}</div>悄泥,您會怎么做虏冻?
    回復(fù):
       const state = reactive({
           params1: '111',
           params2: '222',
           params3: '333'
       })
       return {
           ...toRefs(state)
       }
    
  3. 思考3:
    • 我想同時監(jiān)聽多個變量,該怎么做
      回復(fù):
         watch([() => state.params1,() => state.params2,() => state.params3], (n, o) => {
             console.log(n, o);
         });
         const clickHandler = () => {
             state.params1 = '1111+1'
         }
      
    • 深度監(jiān)聽弹囚,初始化執(zhí)行厨相,該怎么配置參數(shù)
      回復(fù):
       watch([() => state.params1,() => state.params2,() => state.params3], (n, o) => {
             console.log(n, o);
       }, { deep: true, immediate: true });
    

總結(jié)

  • vue3支持大部分在vue2中的option api,就好比在react17中既可以使用class component也可以使用hooks
  • vue3 api變化大鸥鹉,其中所提供的api遠不止本文這些蛮穿,本文只做了一個簡單的入門介紹
  • vue3目前暫不支持ie11-,尤老師本計劃在20年第四季度完成這事的毁渗,現(xiàn)在來看践磅,不知道啥時候能得到尤老師的好消息
  • vue3的生態(tài)是一個浩大的工程,官方正在奮力解決灸异,小伙伴們不要慌

祝各位工作愉快

end~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末府适,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子绎狭,更是在濱河造成了極大的恐慌细溅,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件儡嘶,死亡現(xiàn)場離奇詭異,居然都是意外死亡恍风,警方通過查閱死者的電腦和手機蹦狂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朋贬,“玉大人凯楔,你說我怎么就攤上這事〗跄迹” “怎么了摆屯?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長糠亩。 經(jīng)常有香客問我虐骑,道長,這世上最難降的妖魔是什么赎线? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任廷没,我火速辦了婚禮,結(jié)果婚禮上垂寥,老公的妹妹穿的比我還像新娘颠黎。我一直安慰自己另锋,他們只是感情好,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布狭归。 她就那樣靜靜地躺著夭坪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪过椎。 梳的紋絲不亂的頭發(fā)上室梅,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音潭流,去河邊找鬼竞惋。 笑死,一個胖子當著我的面吹牛灰嫉,可吹牛的內(nèi)容都是我干的拆宛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼讼撒,長吁一口氣:“原來是場噩夢啊……” “哼浑厚!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起根盒,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤钳幅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后炎滞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體敢艰,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年册赛,在試婚紗的時候發(fā)現(xiàn)自己被綠了钠导。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡森瘪,死狀恐怖牡属,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扼睬,我是刑警寧澤逮栅,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站窗宇,受9級特大地震影響措伐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜担映,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一废士、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蝇完,春花似錦官硝、人聲如沸矗蕊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽傻咖。三九已至,卻和暖如春岖研,著一層夾襖步出監(jiān)牢的瞬間卿操,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工孙援, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留害淤,地道東北人。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓拓售,卻偏偏與公主長得像窥摄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子础淤,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容