前言:
vue3項目是在兩年前開始的提针,正式版3.0于2020年9月發(fā)布豆同;
目前vue生態(tài)支持情況還不完善橘蜜,如vuex4還處于rc版本,并存在一定的bug垄分,暫不推薦大家用在標準版項目里宛篇;
不過那些無關(guān)緊要的項目必須可以試試;
再者vue3的官方生態(tài)包為了讓打包后的文件盡可能的小锋喜,打包文件都輸出了ECMASCRIPT新語法些己,這就是網(wǎng)上吹牛逼說的vue3更快、更泻侔恪段标;
一、生命周期
- beforeCreate -> setup()
- created -> setup()
- beforeMount -> onBeforeMount // 在掛載前執(zhí)行某些代碼
- mounted -> onMounted // 在掛載后執(zhí)行某些代碼
- beforeUpdate -> onBeforeUpdate // 在更新前前執(zhí)行某些代碼
- updated -> onUpdated // 在更新后執(zhí)行某些代碼
- beforeDestroy -> onBeforeUnmount // 在組件銷毀前執(zhí)行某些代碼
- destroyed -> onUnmounted // 在組件銷毀后執(zhí)行某些代碼
- errorCaptured -> onErrorCaptured // 錯誤捕獲
二炉奴、常用api
!中文文檔(https://www.vue3js.cn/docs/zh/api/global-api.html#createapp)
- ref
- reactive
- watch
- computed
- nextTick
- 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
-
ref演示
<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
-
reactive演示
<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>砸逊,您會怎么做璧南?
-
watch演示
<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:
- 我想同時監(jiān)聽多個變量司倚,該怎么做
- 深度監(jiān)聽,初始化執(zhí)行,該怎么配置參數(shù)
4.computed演示
<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>
-
nextTick演示
<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>
-
props演示
<template>
<div>defineProps</div>
<div>{{ msg }}</div>
</template>
<script setup>
import { reactive, defineProps } from 'vue'
defineProps({
msg: String
})
const state = reactive({
count: 0,
})
</script>
- 以上看著不習(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打包是杠杠的大拇指
- 但是,vite打包雖然小盒粮,單并不支持ie鸵鸥,目前在咱們項目中無法使用
五、Breadcrumb 面包屑遷移
完全遷移(composition api jsx篇)
- 遷移前
<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>
- 遷移后
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>
);
};
}
});
- 注意
- 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寫法
- 截圖來之某乎,大家可以下去試下胸遇,在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 |
八逗威、兩個好玩的組件
-
Teleport 傳送門
- 有這樣的場景,我們在做業(yè)務(wù)的時候咐蚯,經(jīng)常會遇到層級(z-index)問題春锋、或者我們項把組件掛在到body下
示例:<Teleport to="body"> <div>xxx</div> </Teleport>
其中to參數(shù)值可以指向任何一個容器(容器建議具有唯一性)
- 有這樣的場景,我們在做業(yè)務(wù)的時候咐蚯,經(jīng)常會遇到層級(z-index)問題春锋、或者我們項把組件掛在到body下
-
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)上抄的
- 最常見的當數(shù)據(jù)沒有回來時我們需要一個占位內(nèi)容危尿,通常是loading或骨架屏
九蔚舀、以上思考問題回復(fù)
- 思考1:怎么用ref獲取dom
回復(fù):const dom = ref(null); <div ref={dom}></div>
- 思考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:
- 我想同時監(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ān)聽多個變量,該怎么做
總結(jié)
- vue3支持大部分在vue2中的option api,就好比在react17中既可以使用class component也可以使用hooks
- vue3 api變化大鸥鹉,其中所提供的api遠不止本文這些蛮穿,本文只做了一個簡單的入門介紹
- vue3目前暫不支持ie11-,尤老師本計劃在20年第四季度完成這事的毁渗,現(xiàn)在來看践磅,不知道啥時候能得到尤老師的好消息
- vue3的生態(tài)是一個浩大的工程,官方正在奮力解決灸异,小伙伴們不要慌
祝各位工作愉快
end~