讓你30分鐘快速掌握vue3教程
經(jīng)過(guò)了漫長(zhǎng)的迭代,Vue 3.0終于在上2020-09-18發(fā)布了,帶了翻天覆地的變化,使用了Typescript 進(jìn)行了大規(guī)模的重構(gòu),帶來(lái)了Composition API RFC版本,類似React Hook 一樣的寫Vue,可以自定義自己的hook ,讓使用者更加的靈活,接下來(lái)總結(jié)一下vue 3.0 帶來(lái)的部分新特性。
- setup()
- ref()
- reactive()
- isRef()
- toRefs()
- computed()
- watch()
- LifeCycle Hooks(新的生命周期)
- Template refs
- globalProperties
- Suspense
Vue2與Vue3的對(duì)比
- 對(duì)TypeScript支持不友好(所有屬性都放在了this對(duì)象上,難以推倒組件的數(shù)據(jù)類型)
- 大量的API掛載在Vue對(duì)象的原型上,難以實(shí)現(xiàn)TreeShaking。
- 架構(gòu)層面對(duì)跨平臺(tái)dom渲染開發(fā)支持不友好
- CompositionAPI。受ReactHook啟發(fā)
- 更方便的支持了 jsx
- Vue 3 的 Template 支持多個(gè)根標(biāo)簽,Vue 2 不支持
- 對(duì)虛擬DOM進(jìn)行了重寫、對(duì)模板的編譯進(jìn)行了優(yōu)化操作...
一、setup 函數(shù)
setup() 函數(shù)是 vue3 中,專門為組件提供的新屬性。它為我們使用 vue3 的 Composition API 新特性提供了統(tǒng)一的入口, setup 函數(shù)會(huì)在 beforeCreate 之后、created 之前執(zhí)行, vue3也是取消了這兩個(gè)鉤子,統(tǒng)一用setup代替, 該函數(shù)相當(dāng)于一個(gè)生命周期函數(shù),vue中過(guò)去的data,methods,watch等全部都用對(duì)應(yīng)的新增api寫在setup()函數(shù)中
setup(props, context) {
context.attrs
context.slots
context.parent
context.root
context.emit
context.refs
return {
}
}
- props: 用來(lái)接收 props 數(shù)據(jù)
- context 用來(lái)定義上下文, 上下文對(duì)象中包含了一些有用的屬性,這些屬性在 vue 2.x 中需要通過(guò) this 才能訪問(wèn)到, 在 setup() 函數(shù)中無(wú)法訪問(wèn)到 this,是個(gè) undefined
- 返回值: return {}, 返回響應(yīng)式數(shù)據(jù), 模版中需要使用的函數(shù)
二、reactive 函數(shù)
reactive() 函數(shù)接收一個(gè)普通對(duì)象,返回一個(gè)響應(yīng)式的數(shù)據(jù)對(duì)象, 想要使用創(chuàng)建的響應(yīng)式數(shù)據(jù)也很簡(jiǎn)單,創(chuàng)建出來(lái)之后,在setup中return出去,直接在template中調(diào)用即可
<template>
{{name}} // test
<template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
setup(props, context) {
let state = reactive({
name: 'test'
});
return state
}
});
</script>
三、ref() 函數(shù)
ref() 函數(shù)用來(lái)根據(jù)給定的值創(chuàng)建一個(gè)響應(yīng)式的數(shù)據(jù)對(duì)象,ref() 函數(shù)調(diào)用的返回值是一個(gè)對(duì)象,這個(gè)對(duì)象上只包含一個(gè) value 屬性, 只在setup函數(shù)內(nèi)部訪問(wèn)ref函數(shù)需要加.value
<template>
<div class="mine">
{{count}} // 10
</div>
</template>
<script lang="ts">
import { defineComponent, ref } from 'vue';
export default defineComponent({
setup() {
const count = ref<number>(10)
// 在js 中獲取ref 中定義的值, 需要通過(guò)value屬性
console.log(count.value);
return {
count
}
}
});
</script>
在 reactive 對(duì)象中訪問(wèn) ref 創(chuàng)建的響應(yīng)式數(shù)據(jù)
<template>
<div class="mine">
{{count}} -{{t}} // 10 -100
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
setup() {
const count = ref<number>(10)
const obj = reactive({
t: 100,
count
})
// 通過(guò)reactive 來(lái)獲取ref 的值時(shí),不需要使用.value屬性
console.log(obj.count);
return {
...toRefs(obj)
}
}
});
</script>
四、isRef() 函數(shù)
isRef() 用來(lái)判斷某個(gè)值是否為 ref() 創(chuàng)建出來(lái)的對(duì)象
<script lang="ts">
import { defineComponent, isRef, ref } from 'vue';
export default defineComponent({
setup(props, context) {
const name: string = 'vue'
const age = ref<number>(18)
console.log(isRef(age)); // true
console.log(isRef(name)); // false
return {
age,
name
}
}
});
</script>
五、toRefs() 函數(shù)
toRefs() 函數(shù)可以將 reactive() 創(chuàng)建出來(lái)的響應(yīng)式對(duì)象,轉(zhuǎn)換為普通的對(duì)象,只不過(guò),這個(gè)對(duì)象上的每個(gè)屬性節(jié)點(diǎn),都是 ref() 類型的響應(yīng)式數(shù)據(jù)
<template>
<div class="mine">
{{name}} // test
{{age}} // 18
</div>
</template>
<script lang="ts">
import { defineComponent, reactive, ref, toRefs } from 'vue';
export default defineComponent({
setup(props, context) {
let state = reactive({
name: 'test'
});
const age = ref(18)
return {
...toRefs(state),
age
}
}
});
</script>
六、computed()
該函數(shù)用來(lái)創(chuàng)造計(jì)算屬性,和過(guò)去一樣,它返回的值是一個(gè)ref對(duì)象。 里面可以傳方法,或者一個(gè)對(duì)象,對(duì)象中包含set()、get()方法
6.1 創(chuàng)建只讀的計(jì)算屬性
import { computed, defineComponent, ref } from 'vue';
export default defineComponent({
setup(props, context) {
const age = ref(18)
// 根據(jù) age 的值,創(chuàng)建一個(gè)響應(yīng)式的計(jì)算屬性 readOnlyAge,它會(huì)根據(jù)依賴的 ref 自動(dòng)計(jì)算并返回一個(gè)新的 ref
const readOnlyAge = computed(() => age.value++) // 19
return {
age,
readOnlyAge
}
}
});
</script>
6.2 通過(guò)set()、get()方法創(chuàng)建一個(gè)可讀可寫的計(jì)算屬性
<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
export default defineComponent({
setup(props, context) {
const age = ref<number>(18)
const computedAge = computed({
get: () => age.value + 1,
set: value => age.value + value
})
// 為計(jì)算屬性賦值的操作,會(huì)觸發(fā) set 函數(shù), 觸發(fā) set 函數(shù)后,age 的值會(huì)被更新
age.value = 100
return {
age,
computedAge
}
}
});
</script>
七、 watch() 函數(shù)
watch 函數(shù)用來(lái)偵聽特定的數(shù)據(jù)源,并在回調(diào)函數(shù)中執(zhí)行副作用。默認(rèn)情況是懶執(zhí)行的,也就是說(shuō)僅在偵聽的源數(shù)據(jù)變更時(shí)才執(zhí)行回調(diào)。
7.1 監(jiān)聽用reactive聲明的數(shù)據(jù)源
<script lang="ts">
import { computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
name: string,
age: number
}
export default defineComponent({
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 })
watch(
() => state.age,
(age, preAge) => {
console.log(age); // 100
console.log(preAge); // 10
}
)
// 修改age 時(shí)會(huì)觸發(fā)watch 的回調(diào), 打印變更前后的值
state.age = 100
return {
...toRefs(state)
}
}
});
</script>
7.2 監(jiān)聽用ref聲明的數(shù)據(jù)源
<script lang="ts">
import { defineComponent, ref, watch } from 'vue';
interface Person {
name: string,
age: number
}
export default defineComponent({
setup(props, context) {
const age = ref<number>(10);
watch(age, () => console.log(age.value)); // 100
// 修改age 時(shí)會(huì)觸發(fā)watch 的回調(diào), 打印變更后的值
age.value = 100
return {
age
}
}
});
</script>
7.3 同時(shí)監(jiān)聽多個(gè)值
<script lang="ts">
import { computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
name: string,
age: number
}
export default defineComponent({
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 })
watch(
[() => state.age, () => state.name],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge);
console.log(oldName);
console.log(oldAge);
}
)
// 修改age 時(shí)會(huì)觸發(fā)watch 的回調(diào), 打印變更前后的值, 此時(shí)需要注意, 更改其中一個(gè)值, 都會(huì)執(zhí)行watch的回調(diào)
state.age = 100
state.name = 'vue3'
return {
...toRefs(state)
}
}
});
</script>
7.4 stop 停止監(jiān)聽
在 setup() 函數(shù)內(nèi)創(chuàng)建的 watch 監(jiān)視,會(huì)在當(dāng)前組件被銷毀的時(shí)候自動(dòng)停止。如果想要明確地停止某個(gè)監(jiān)視,可以調(diào)用 watch() 函數(shù)的返回值即可,語(yǔ)法如下:
<script lang="ts">
import { set } from 'lodash';
import { computed, defineComponent, reactive, toRefs, watch } from 'vue';
interface Person {
name: string,
age: number
}
export default defineComponent({
setup(props, context) {
const state = reactive<Person>({ name: 'vue', age: 10 })
const stop = watch(
[() => state.age, () => state.name],
([newName, newAge], [oldName, oldAge]) => {
console.log(newName);
console.log(newAge);
console.log(oldName);
console.log(oldAge);
}
)
// 修改age 時(shí)會(huì)觸發(fā)watch 的回調(diào), 打印變更前后的值, 此時(shí)需要注意, 更改其中一個(gè)值, 都會(huì)執(zhí)行watch的回調(diào)
state.age = 100
state.name = 'vue3'
setTimeout(()=> {
stop()
// 此時(shí)修改時(shí), 不會(huì)觸發(fā)watch 回調(diào)
state.age = 1000
state.name = 'vue3-'
}, 1000) // 1秒之后講取消watch的監(jiān)聽
return {
...toRefs(state)
}
}
});
</script>
八、LifeCycle Hooks(新的生命后期)
新版的生命周期函數(shù),可以按需導(dǎo)入到組件中,且只能在 setup() 函數(shù)中使用, 但是也可以在setup 外定義, 在 setup 中使用
<script lang="ts">
import { set } from 'lodash';
import { defineComponent, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onErrorCaptured, onMounted, onUnmounted, onUpdated } from 'vue';
export default defineComponent({
setup(props, context) {
onBeforeMount(()=> {
console.log('beformounted!')
})
onMounted(() => {
console.log('mounted!')
})
onBeforeUpdate(()=> {
console.log('beforupdated!')
})
onUpdated(() => {
console.log('updated!')
})
onBeforeUnmount(()=> {
console.log('beforunmounted!')
})
onUnmounted(() => {
console.log('unmounted!')
})
onErrorCaptured(()=> {
console.log('errorCaptured!')
})
return {}
}
});
</script>
九、Template refs
通過(guò)refs 來(lái)回去真實(shí)dom元素, 這個(gè)和react 的用法一樣,為了獲得對(duì)模板內(nèi)元素或組件實(shí)例的引用,我們可以像往常一樣在setup()中聲明一個(gè)ref并返回它
- 還是跟往常一樣,在 html 中寫入 ref 的名稱
- 在steup 中定義一個(gè) ref
- steup 中返回 ref的實(shí)例
- onMounted 中可以得到 ref的RefImpl的對(duì)象, 通過(guò).value 獲取真實(shí)dom
<template>
<!--第一步:還是跟往常一樣,在 html 中寫入 ref 的名稱-->
<div class="mine" ref="elmRefs">
<span>1111</span>
</div>
</template>
<script lang="ts">
import { set } from 'lodash';
import { defineComponent, onMounted, ref } from 'vue';
export default defineComponent({
setup(props, context) {
// 獲取真實(shí)dom
const elmRefs = ref<null | HTMLElement>(null);
onMounted (() => {
console.log(elmRefs.value); // 得到一個(gè) RefImpl 的對(duì)象, 通過(guò) .value 訪問(wèn)到數(shù)據(jù)
})
return {
elmRefs
}
}
});
</script>
十、vue 的全局配置
通過(guò)vue 實(shí)例上config來(lái)配置,包含Vue應(yīng)用程序全局配置的對(duì)象。您可以在掛載應(yīng)用程序之前修改下面列出的屬性:
const app = Vue.createApp({})
app.config = {...}
為組件渲染功能和觀察程序期間的未捕獲錯(cuò)誤分配處理程序。錯(cuò)誤和應(yīng)用程序?qū)嵗龑⒄{(diào)用處理程序
app.config.errorHandler = (err, vm, info) => {}
可以在應(yīng)用程序內(nèi)的任何組件實(shí)例中訪問(wèn)的全局屬性,組件的屬性將具有優(yōu)先權(quán)。這可以代替Vue 2.xVue.prototype擴(kuò)展:
const app = Vue.createApp({})
app.config.globalProperties.$http = 'xxxxxxxxs'
可以在組件用通過(guò) getCurrentInstance() 來(lái)獲取全局globalProperties 中配置的信息,getCurrentInstance 方法獲取當(dāng)前組件的實(shí)例,然后通過(guò) ctx 屬性獲得當(dāng)前上下文,這樣我們就能在setup中使用router和vuex, 通過(guò)這個(gè)屬性我們就可以操作變量、全局屬性、組件屬性等等
setup( ) {
const { ctx } = getCurrentInstance();
ctx.$http
}
十一、Suspense 組件
在開始介紹 Vue 的 Suspense 組件之前,我們有必要先了解一下 React 的 Suspense 組件,因?yàn)樗麄兊墓δ茴愃啤?/p>
React.lazy 接受一個(gè)函數(shù),這個(gè)函數(shù)需要?jiǎng)討B(tài)調(diào)用 import()。它必須返回一個(gè) Promise,該 Promise 需要 resolve 一個(gè) default export 的 React 組件。
import React, { Suspense } from 'react';
const myComponent = React.lazy(() => import('./Component'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<myComponent />
</Suspense>
</div>
);
}
Vue3 也新增了 React.lazy 類似功能的 defineAsyncComponent 函數(shù),處理動(dòng)態(tài)引入(的組件)。defineAsyncComponent可以接受返回承諾的工廠函數(shù)。當(dāng)您從服務(wù)器檢索到組件定義時(shí),應(yīng)該調(diào)用Promise的解析回調(diào)。您還可以調(diào)用reject(reason)來(lái)指示負(fù)載已經(jīng)失敗
import { defineAsyncComponent } from 'vue'
const AsyncComp = defineAsyncComponent(() =>
import('./components/AsyncComponent.vue')
)
app.component('async-component', AsyncComp)
Vue3 也新增了 Suspense 組件:
<template>
<Suspense>
<template #default>
<my-component />
</template>
<template #fallback>
Loading ...
</template>
</Suspense>
</template>
<script lang='ts'>
import { defineComponent, defineAsyncComponent } from "vue";
const MyComponent = defineAsyncComponent(() => import('./Component'));
export default defineComponent({
components: {
MyComponent
},
setup() {
return {}
}
})
</script>
十二、vue 3.x 完整組件模版結(jié)構(gòu)
一個(gè)完成的vue 3.x 完整組件模版結(jié)構(gòu)包含了:組件名稱、 props、components、setup(hooks、computed、watch、methods 等)
<template>
<div class="mine" ref="elmRefs">
<span>{{name}}</span>
<br>
<span>{{count}}</span>
<div>
<button @click="handleClick">測(cè)試按鈕</button>
</div>
<ul>
<li v-for="item in list" :key="item.id">{{item.name}}</li>
</ul>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, getCurrentInstance, onMounted, PropType, reactive, ref, toRefs } from 'vue';
interface IState {
count: 0,
name: string,
list: Array<object>
}
export default defineComponent({
name: 'demo',
// 父組件傳子組件參數(shù)
props: {
name: {
type: String as PropType<null | ''>,
default: 'vue3.x'
},
list: {
type: Array as PropType<object[]>,
default: () => []
}
},
components: {
/// TODO 組件注冊(cè)
},
emits: ["emits-name"], // 為了提示作用
setup (props, context) {
console.log(props.name)
console.log(props.list)
const state = reactive<IState>({
name: 'vue 3.0 組件',
count: 0,
list: [
{
name: 'vue',
id: 1
},
{
name: 'vuex',
id: 2
}
]
})
const a = computed(() => state.name)
onMounted(() => {
})
function handleClick () {
state.count ++
// 調(diào)用父組件的方法
context.emit('emits-name', state.count)
}
return {
...toRefs(state),
handleClick
}
}
});
</script>
vue 3 的生態(tài)
- 官網(wǎng)
- 源碼
- vite構(gòu)建器
- 腳手架:https://cli.vuejs.org/
- vue-router-next
- vuex4.0
UI 組件庫(kù)
到此這篇關(guān)于讓你30分鐘快速掌握vue3教程的文章就介紹到這了,更多相關(guān)vue3 入門內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue使用自定義事件的表單輸入組件用法詳解【日期組件與貨幣組件】
這篇文章主要介紹了vue使用自定義事件的表單輸入組件用法,結(jié)合實(shí)例形式詳細(xì)分析了vue.js日期組件與貨幣組件相關(guān)操作技巧及注意事項(xiàng),需要的朋友可以參考下2020-06-06
vue組件從開發(fā)到發(fā)布的實(shí)現(xiàn)步驟
這篇文章主要介紹了vue組件從開發(fā)到發(fā)布的實(shí)現(xiàn)步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-11-11
詳解vue-admin和后端(flask)分離結(jié)合的例子
本篇文章主要介紹了詳解vue-admin和后端(flask)分離結(jié)合的例子,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
Django與Vue語(yǔ)法的沖突問(wèn)題完美解決方法
這篇文章主要介紹了Django與Vue語(yǔ)法的沖突問(wèn)題完美解決方法,本文給大家分享了兩種解決方法,需要的朋友參考下吧2017-12-12
vue實(shí)現(xiàn)頁(yè)面刷新動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)頁(yè)面刷新動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Vue3 appear 失效的問(wèn)題及如何使用 appear
appear 是一個(gè)在元素默認(rèn)被顯示的情況下 調(diào)用進(jìn)入動(dòng)畫效果,使得元素在這種初次渲染情況下 執(zhí)行進(jìn)入動(dòng)畫的屬性,最近在學(xué)習(xí)vue3的動(dòng)畫時(shí)遇到appear無(wú)法生效的問(wèn)題,本文給大家詳細(xì)講解,感興趣的朋友一起看看吧2023-10-10
vue-cli3啟動(dòng)服務(wù)如何自動(dòng)打開瀏覽器配置
這篇文章主要介紹了vue-cli3啟動(dòng)服務(wù)如何自動(dòng)打開瀏覽器配置,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue自適應(yīng)布局postcss-px2rem詳解
這篇文章主要介紹了vue自適應(yīng)布局(postcss-px2rem)的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2022-05-05

