十分鐘,帶你了解 Vue3 的新寫法
本文的目的,是為了讓已經(jīng)有 Vue2 開發(fā)經(jīng)驗(yàn)的?人?,快速掌握 Vue3 的寫法。
因此,?本篇假定你已經(jīng)掌握 Vue 的核心內(nèi)容?,只為你介紹編寫 Vue3 代碼,需要了解的內(nèi)容。
一、Vue3 里?script
?的三種寫法
首先,Vue3 新增了一個(gè)叫做組合式 api 的東西,英文名叫 Composition API。因此 Vue3 的?script
?現(xiàn)在支持三種寫法,
1、最基本的 Vue2 寫法
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script>
export?default?{
??data()?{
????return?{
??????count:?1,
????};
??},
??methods:?{
????onClick()?{
??????this.count?+=?1;
????},
??},
}
</script>
2、setup() 屬性
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script>
import?{?ref?}?from?'vue';
export?default?{
??//?注意這部分
??setup()?{
????let?count?=?ref(1);
????const?onClick?=?()?=>?{
??????count.value?+=?1;
????};
????return?{
??????count,
??????onClick,
????};
??},
??
}
</script>
3、<script setup>
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script?setup>
import?{?ref?}?from?'vue';
const?count?=?ref(1);
const?onClick?=?()?=>?{
??count.value?+=?1;
};
</script>
正如你看到的那樣,無論是代碼行數(shù),還是代碼的精簡度,<script setup>
?的方式是最簡單的形式。
如果你對 Vue 很熟悉,那么,我推薦你使用?<script setup>
?的方式。
這種寫法,讓 Vue3 成了我最喜歡的前端框架。
如果你還是前端新人,那么,我推薦你先學(xué)習(xí)第一種寫法。
因?yàn)榈谝环N寫法的學(xué)習(xí)負(fù)擔(dān)更小,先學(xué)第一種方式,掌握最基本的 Vue 用法,然后再根據(jù)我這篇文章,快速掌握 Vue3 里最需要關(guān)心的內(nèi)容。
第一種寫法,跟過去 Vue2 的寫法是一樣的,所以我們不過多介紹。
第二種寫法,所有的對象和方法都需要?return
?才能使用,太啰嗦。除了舊項(xiàng)目,可以用這種方式體驗(yàn) Vue3 的新特性以外,我個(gè)人不建議了解這種方式。反正我自己暫時(shí)不打算精進(jìn)這部分。
所以,接下來,我們主要介紹的,也就是?<script setup>
?,這種寫法里需要了解的內(nèi)容。
注意:?<script setup>
?本質(zhì)上是第二種寫法的語法糖,掌握了這種寫法,其實(shí)第二種寫法也基本上就會了。(又多了一個(gè)不學(xué)第二種寫法的理由)。
二、如何使用?<script setup>
?編寫組件
學(xué)習(xí) Vue3 并不代表你需要新學(xué)習(xí)一個(gè)技術(shù),Vue3 的底層開發(fā)思想,跟 Vue2 是沒有差別的。
V3 和 V2 的區(qū)別就像是,你用不同的語言或者方言說同一句話。
所以我們需要關(guān)心的,就是 Vue2 里的內(nèi)容,怎么用 Vue3 的方式寫出來。
1、data
——唯一需要注意的地方
整個(gè)?data
?這一部分的內(nèi)容,你只需要記住下面這一點(diǎn)。
以前在?data
?中創(chuàng)建的屬性,現(xiàn)在全都用?ref()
?聲明。
在?template
?中直接用,在?script
?中記得加?.value
?。
在開頭,我就已經(jīng)寫了一個(gè)簡單的例子,我們直接拿過來做對比。
1)寫法對比
?//?Vue2?的寫法
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script>
export?default?{
??data()?{
????return?{
??????count:?1,
????};
??},
??methods:?{
????onClick()?{
??????this.count?+=?1;
????},
??},
}
</script>?//?Vue3?的寫法
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script?setup>
import?{?ref?}?from?'vue';
?//?用這種方式聲明
const?count?=?ref(1);
const?onClick?=?()?=>?{
???//?使用的時(shí)候記得?.value
??count.value?+=?1;
};
</script>
2)注意事項(xiàng)——組合式?api?的心智負(fù)擔(dān)
a、ref 和 reactive
Vue3 里,還提供了一個(gè)叫做?reactive
?的?api
。
但是我的建議是,你不需要關(guān)心它。絕大多數(shù)場景下,ref
?都夠用了。
b、什么時(shí)候用?ref()
?包裹,什么時(shí)候不用。
要不要用ref,就看你的這個(gè)變量的值改變了以后,頁面要不要跟著變。
當(dāng)然,你可以完全不需要關(guān)心這一點(diǎn),跟過去寫?data
?一樣就行。
只不過這樣做,你在使用的時(shí)候,需要一直?.value
。
c、不要解構(gòu)使用
在使用時(shí),不要像下面這樣去寫,會丟失響應(yīng)性。
也就是會出現(xiàn)更新了值,但是頁面沒有更新的情況
//?Vue3?的寫法
<template>
??<div>{{?count?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script?setup>
import?{?ref?}?from?'vue';
const?count?=?ref(1);
const?onClick?=?()?=>?{
??//?不要這樣寫!!
??const?{?value?}?=?count;
??value?+=?1;
};
</script>
注意:?學(xué)習(xí) Vue3 就需要考慮像這樣的內(nèi)容,徒增了學(xué)習(xí)成本。實(shí)際上這些心智負(fù)擔(dān),在學(xué)習(xí)的過程中,是可以完全不需要考慮的。
這也是為什么我推薦新人先學(xué)習(xí) Vue2 的寫法。
2、methods
聲明事件方法,我們只需要在?script
?標(biāo)簽里,創(chuàng)建一個(gè)方法對象即可。
剩下的在 Vue2 里是怎么寫的,Vue3 是同樣的寫法。
//?Vue2?的寫法
<template>
??<div?@click="onClick">
????這是一個(gè)div
??</div>
</template>
<script>
export?default?{
??methods:?{
????onClick()?{
??????console.log('clicked')
????},
??},
}
</script>//?Vue3?的寫法
<template>
??<div?@click="onClick">
????這是一個(gè)div
??</div>
</template>
<script?setup>
//?注意這部分
const?onClick?=?()?=>?{
??console.log('clicked')
}
</script>
3、props
聲明?props
?我們可以用?defineProps()
,具體寫法,我們看代碼。
1)寫法對比
//?Vue2?的寫法
<template>
??<div>{{?foo?}}</div>
</template>
<script>
export?default?{
??props:?{
????foo:?String,
??},
??created()?{
????console.log(this.foo);
??},
}
</script>//?Vue3?的寫法
<template>
??<div>{{?foo?}}</div>
</template>
<script?setup>
//?注意這里
const?props?=?defineProps({
??foo:?String
})
//?在?script?標(biāo)簽里使用
console.log(props.foo)
</script>
2)注意事項(xiàng)——組合式?api?的心智負(fù)擔(dān)
使用 props 時(shí),同樣注意不要使用解構(gòu)的方式。
<script?setup>
const?props?=?defineProps({
??foo:?String
})
?//?不要這樣寫
const?{?foo?}?=?props;
console.log(foo)
</script>
4、emits 事件
與?props
?相同,聲明?emits
?我們可以用?defineEmits()
,具體寫法,我們看代碼。
//?Vue2?的寫法
<template>
??<div?@click="onClick">
????這是一個(gè)div
??</div>
</template>
<script>
export?default?{
??emits:?['click'],?//?注意這里
??methods:?{
????onClick()?{
??????this.$emit('click');?//?注意這里
????},
??},
?
}
</script>//?Vue3?的寫法
<template>
??<div?@click="onClick">
????這是一個(gè)div
??</div>
</template>
<script?setup>
//?注意這里
const?emit?=?defineEmits(['click']);
const?onClick?=?()?=>?{
??emit('click')?//?注意這里
}
</script>
5、computed
直接上寫法對比。
//?Vue2?的寫法
<template>
??<div>
????<span>{{?value?}}</span>
????<span>{{?reversedValue?}}</span>
??</div>
</template>
<script>
export?default?{
??data()?{
????return?{
??????value:?'this?is?a?value',
????};
??},
??computed:?{
????reversedValue()?{
??????return?value
????????.split('').reverse().join('');
????},
??},
}
</script>//?Vue3?的寫法
<template>
??<div>
????<span>{{?value?}}</span>
????<span>{{?reversedValue?}}</span>
??</div>
</template>
<script?setup>
import?{ref,?computed}?from?'vue'
const?value?=?ref('this?is?a?value')
//?注意這里
const?reversedValue?=?computed(()?=>?{
??//?使用?ref?需要?.value
??return?value.value
????.split('').reverse().join('');
})
</script>
6、watch
這一部分,我們需要注意一下了,Vue3 中,watch 有兩種寫法。一種是直接使用?watch
,還有一種是使用?watchEffect
。
兩種寫法的區(qū)別是:
watch
?需要你明確指定依賴的變量,才能做到監(jiān)聽效果。而?
watchEffect
?會根據(jù)你使用的變量,自動的實(shí)現(xiàn)監(jiān)聽效果。
1)直接使用?watch
//?Vue2?的寫法
<template>
??<div>{{?count?}}</div>
??<div>{{?anotherCount?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script>
export?default?{
??data()?{
????return?{??
??????count:?1,
??????anotherCount:?0,
????};
??},
??methods:?{
????onClick()?{
??????this.count?+=?1;
????},
??},
??watch:?{
????count(newValue)?{
??????this.anotherCount?=?newValue?-?1;
????},
??},
}
</script>//?Vue3?的寫法
<template>
??<div>{{?count?}}</div>
??<div>{{?anotherCount?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script?setup>
import?{?ref,?watch?}?from?'vue';
const?count?=?ref(1);
const?onClick?=?()?=>?{
??count.value?+=?1;
};
const?anotherCount?=?ref(0);
//?注意這里
//?需要在這里,
//?明確指定依賴的是?count?這個(gè)變量
watch(count,?(newValue)?=>?{
??anotherCount.value?=?newValue?-?1;
})
</script>
2)使用?watchEffect
//?Vue2?的寫法
<template>
??<div>{{?count?}}</div>
??<div>{{?anotherCount?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script>
export?default?{
??data()?{
????return?{??
??????count:?1,
??????anotherCount:?0,
????};
??},
??methods:?{
????onClick()?{
??????this.count?+=?1;
????},
??},
??watch:?{
????count(newValue)?{
??????this.anotherCount?=?newValue?-?1;
????},
??},
}
</script>//?Vue3?的寫法
<template>
??<div>{{?count?}}</div>
??<div>{{?anotherCount?}}</div>
??<button?@click="onClick">
????增加?1
??</button>
</template>
<script?setup>
import?{?ref,?watchEffect?}?from?'vue';
const?count?=?ref(1);
const?onClick?=?()?=>?{
??count.value?+=?1;
};
const?anotherCount?=?ref(0);
//?注意這里
watchEffect(()?=>?{
??//?會自動根據(jù)?count.value?的變化,
??//?觸發(fā)下面的操作
??anotherCount.value?=?count.value?-?1;
})
</script>
7、生命周期
Vue3 里,除了將兩個(gè)?destroy
?相關(guān)的鉤子,改成了?unmount
,剩下的需要注意的,就是在?<script setup>
?中,不能使用?beforeCreate
?和?created
?兩個(gè)鉤子。
如果你熟悉相關(guān)的生命周期,只需要記得在?setup
?里,用?on
?開頭,加上大寫首字母就行。
//?選項(xiàng)式?api?寫法
<template>
??<div></div>
</template>
<script>
export?default?{
??beforeCreate()?{},
??created()?{},
??
??beforeMount()?{},
??mounted()?{},
??
??beforeUpdate()?{},
??updated()?{},
??
??//?Vue2?里叫?beforeDestroy
??beforeUnmount()?{},
??//?Vue2?里叫?destroyed
??unmounted()?{},
??
??//?其他鉤子不常用,所以不列了。
}
</script>//?組合式?api?寫法
<template>
??<div></div>
</template>
<script?setup>
import?{
??onBeforeMount,
??onMounted,
??onBeforeUpdate,
??onUpdated,
??onBeforeUnmount,
??onUnmounted,
}?from?'vue'
onBeforeMount(()?=>?{})
onMounted(()?=>?{})
onBeforeUpdate(()?=>?{})
onUpdated(()?=>?{})
onBeforeUnmount(()?=>?{})
onUnmounted(()?=>?{})
</script>
三、結(jié)語
好了,對于快速上手 Vue3 來說,以上內(nèi)容基本已經(jīng)足夠了。
這篇文章本身不能做到幫你理解所有 Vue3 的內(nèi)容,但是能幫你快速掌握 Vue3 的寫法。