一篇文章總結(jié)Vue3.2語法糖使用
一. 概述
在Vue2
時(shí)期,組件里定義的各類變量、方法、計(jì)算屬性等是分別存放到data
、methods
、computed
等選項(xiàng)里,這樣編寫的代碼不便于后期的查閱,查找一個(gè)業(yè)務(wù)邏輯需要在各個(gè)選項(xiàng)來回切換。vue3.0
組合式APIsetup
函數(shù)的推出就是為了解決這個(gè)問題,它讓我們的邏輯關(guān)注點(diǎn)更加集中,語法也更加精簡,但是當(dāng)我們?cè)谑褂?code>vue3.0的語法就構(gòu)建組件的時(shí)候,總是需要把外面定義的方法變量必須要return出去才能在<template>
,比較麻煩一些. vue3.2
語法糖的出現(xiàn)以及一些新增的API,讓我們的代碼進(jìn)一步簡化。
什么是語法糖?
語法糖(英語:Syntactic sugar)是由英國計(jì)算機(jī)科學(xué)家彼得·蘭丁發(fā)明的一個(gè)術(shù)語,指計(jì)算機(jī)語言中添加的某種語法,這種語法對(duì)語言的功能沒有影響,但是更方便程序員使用。語法糖讓程序更加簡潔,有更高的可讀性。
Vue3.2語法糖
來看下vue3.0
與vue3.2
的單文件組件(SFC,即.vue 文件)的結(jié)構(gòu)對(duì)比
vue3.0
組件
<template> <div> </div> </template> <script> export default { components: { }, props: { }, setup () { return {} } } </script> <style lang="scss" scoped> </style>
vue3.2
組件
<template> <MyTestVue :title="title" @click="changeTitle" /> </template> <script setup> import MyTestVue from './MyTest.vue'; import { ref } from 'vue'; const title = ref('測(cè)試一下') const changeTitle = () => { title.value = 'Hello,World' } </script> <style lang="scss" scoped> </style>
對(duì)比
vue3.0
與vue3.2
版本的組件模板,最主要的變化是3.2中沒有了setup
函數(shù),而是把它放在了script標(biāo)簽中。我們定義的屬性和方法也不用在return中返回,直接就可以用在模板語法中 ...
這些是直觀的變化,接下來我們學(xué)習(xí)具體的用法。
二.使用介紹
1.組件注冊(cè)
vue3.0
中使用組件,需要使用 components 選項(xiàng)來顯式注冊(cè):
<script> import ComponentA from './ComponentA.js' export default { components: { ComponentA }, setup() { // ... } } </script>
vue3.2
<script setup>
的單文件組件中,導(dǎo)入的組件可以直接在模板中使用,組件會(huì)自動(dòng)注冊(cè),并且無需指定當(dāng)前組件的名字,它會(huì)自動(dòng)以文件名為主,也就是不用再寫name屬性了。
<script setup> import ComponentA from './ComponentA.vue' </script> <template> <ComponentA /> </template>
2.Props 聲明
在vue3.0
中,prop
可以使用props
選項(xiàng)來聲明
<script> export default { props: ['foo'], // 或者用這種方式指類型與默認(rèn)值 // props: { // foo:{ // type: String, // default: '' // }, // }, setup(props) { // setup() 接收 props 作為第一個(gè)參數(shù) console.log(props.foo) } } </script>
vue3.2
組件中,props
可以使用defineProps()
宏來聲明
<script setup> const props = defineProps(['foo']) // 或者 const propsOther = defineProps({ title: String, likes: Number }) console.log(props.foo) </script>
注意事項(xiàng):所有的 props 都遵循著單向綁定原則,props 因父組件的更新而變化,自然地將新的狀態(tài)向下流往子組件,而不會(huì)逆向傳遞,這意味著你不應(yīng)該在子組件中去更改一個(gè) prop。
3.計(jì)算屬性
我們一般使用計(jì)算屬性來描述依賴響應(yīng)式狀態(tài)的復(fù)雜邏輯。說白了就是這個(gè)計(jì)算屬性的值依賴于其他響應(yīng)式屬性的值,依賴的屬性發(fā)生變化,那么這個(gè)計(jì)算屬性的值就會(huì)進(jìn)行重新計(jì)算。
<script setup> import { ref, computed } from 'vue' const firstName = ref('John') const lastName = ref('Doe') const fullName = computed({ // getter get() { return firstName.value + ' ' + lastName.value }, // setter set(newValue) { // 注意:我們這里使用的是解構(gòu)賦值語法 [firstName.value, lastName.value] = newValue.split(' ') } }) </script>
當(dāng)調(diào)用fullName.value = 'John Doe'
時(shí),setter
會(huì)被調(diào)用,而firstName
和 lastName
會(huì)被更新,在vue3.2
中我們可以直接在<template>
標(biāo)簽中使用它,不在需要return返回。
- 不要在計(jì)算函數(shù)中做異步請(qǐng)求或者更改 DOM!
- 一個(gè)計(jì)算屬性僅會(huì)在其響應(yīng)式依賴更新時(shí)才重新計(jì)算,如果他依賴的是個(gè)非響應(yīng)式的依賴,及時(shí)其值發(fā)生變化,計(jì)算屬性也不會(huì)更新。
- 相比于方法而言,計(jì)算屬性值會(huì)基于其響應(yīng)式依賴被緩存,一個(gè)計(jì)算屬性僅會(huì)在其響應(yīng)式依賴更新時(shí)才重新計(jì)算
4. watch
在組合式API中,我們可以使用watch
函數(shù)在每次響應(yīng)式狀態(tài)發(fā)生變化時(shí)觸發(fā)回調(diào)函數(shù),watch
的第一個(gè)參數(shù)可以是不同形式的“數(shù)據(jù)源”:它可以是一個(gè) ref
(包括計(jì)算屬性)、一個(gè)響應(yīng)式對(duì)象、一個(gè) getter
函數(shù)、或多個(gè)數(shù)據(jù)源組成的數(shù)組: watch()
是懶執(zhí)行的:僅當(dāng)數(shù)據(jù)源變化時(shí),才會(huì)執(zhí)行回調(diào),例如:
<script setup> import { ref,watch } from 'vue'; const props = defineProps({ title: String, itemList: { type: Array, default: () => [{ text: 'title', value: 0 }] } }) watch(() => props.itemList.length,(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); }) </script>
這里監(jiān)聽
props.itemList.length
,當(dāng)傳入的itemList
數(shù)量發(fā)生變化時(shí),后面的回調(diào)方法會(huì)被調(diào)用。當(dāng)然wacth()
還有第三個(gè)可選參數(shù):否開啟深監(jiān)聽(deep)
, 如果這里這樣寫:<script setup> import { ref,watch } from 'vue'; ... watch(() => props.itemList,(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); }) </script>當(dāng)傳入的
itemList
數(shù)量發(fā)生改變時(shí),回調(diào)函數(shù)不會(huì)觸發(fā),正確的寫法是加上其第三個(gè)參數(shù)deep:true
<script setup> import { ref,watch } from 'vue'; ... watch(() => props.itemList,(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); },{deep:true}) </script>
watch
也可以同時(shí)監(jiān)聽多個(gè)屬性:
<script setup> import { ref,watch } from 'vue'; const props = defineProps({ title: String, itemList: { type: Array, default: () => [{ text: 'title', value: 0 }] } }) // 同時(shí)監(jiān)聽多個(gè)屬性 watch(() => [props.itemList,props.title],(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); },{deep:true}) </script>
5. watchEffect()
與watch()
的懶執(zhí)行不同的是,watchEffect()
會(huì)立即執(zhí)行一遍回調(diào)函數(shù),如果這時(shí)函數(shù)產(chǎn)生了副作用,Vue
會(huì)自動(dòng)追蹤副作用的依賴關(guān)系,自動(dòng)分析出響應(yīng)源。上面的例子可以重寫為:
<script setup> ... watchEffect(() => { console.log('itemList===',props.itemList.length); console.log('title===',props.title); }) </script>
這個(gè)例子中,回調(diào)會(huì)立即執(zhí)行。在執(zhí)行期間,它會(huì)自動(dòng)追蹤props.itemList.length
作為依賴(和計(jì)算屬性的行為類似)。每當(dāng)傳入的itemList.length
變化時(shí),回調(diào)會(huì)再次執(zhí)行。
如果要清除watchEffect()
的的監(jiān)聽,只需要顯示的調(diào)用watchEffect()
的返回函數(shù)就可以了,例如:
<script setup> ... const stopEffect = watchEffect(() => { console.log('itemList===',props.itemList.length); console.log('title===',props.title); }) stopEffect() </script>
watch 只追蹤明確偵聽的數(shù)據(jù)源。它不會(huì)追蹤任何在回調(diào)中訪問到的東西。另外,僅在數(shù)據(jù)源確實(shí)改變時(shí)才會(huì)觸發(fā)回調(diào)。我們能更加精確地控制回調(diào)函數(shù)的觸發(fā)時(shí)機(jī)。 watchEffect,則會(huì)在副作用發(fā)生期間追蹤依賴。它會(huì)在同步執(zhí)行過程中,自動(dòng)追蹤所有能訪問到的響應(yīng)式屬性。
6.組件的事件調(diào)用
6.1 子組件調(diào)用父組件的方法
vue3.0
中如果我們的子組件觸發(fā)父組件的方法,我們的做法:
子組件 <script> export default { emits: ['inFocus', 'submit'], setup(props, ctx) { ctx.emit('submit',params) } } // 或者將可以將emit解構(gòu)使用 export default { setup(props,{emit}) { emit('submit',params) } } </script> 父組件 <template> <Children @submit="submitHandel"/> </div> </template> <script> export default { name: 'TodoItem', setup(props, { emit }) { const submitHandel = () => { console.log('子組件調(diào)用了父組件的submitHandel方法'); } return { submitHandel, } } }; </script>
vue3.2
語法糖中,子組件要觸發(fā)的事件需要顯式地通過 defineEmits()
宏來聲明
子組件 <script setup> const emit = defineEmits(['inFocus', 'submit']) function buttonClick(parmas) { emit('submit', parmas) } </script> 父組件 <template> <Children @submit="submitHandel"/> </div> </template> <script setup> const submitHandel = () => { console.log('子組件調(diào)用了父組件的submitHandel方法'); } }; </script>
6.2 父組件調(diào)用子組件的方法或是屬性
vue3.0
中如果父組件觸發(fā)子組件的方法或是屬性,直接在return函數(shù)中返回就可以,數(shù)據(jù)都是默認(rèn)隱式暴露給父組件的。
<script> // 子組件 setup(props, { emit }) { const isShow = ref(false) // 父組件調(diào)用這個(gè)方法 const showSubComponent = () => { isShow.value = !isShow.value } return { // return 返回 showSubComponent, } } </script>
父組件中通過ref
獲取到子組件,并對(duì)子組件暴露的方法進(jìn)行訪問
父組件 <template> <div class="todo-list"> <TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /> </div> </template> <script> import { ref } from 'vue'; export default { setup(props, { emit }) { //獲取子組件ref const todoItemVueRef = ref(null) // 調(diào)用子組件的方法 const callItemFuncHandel = () => { todoItemVueRef.value.showSubComponent() } return { todoItemVueRef } } }; </script>
vue3.2
語法中,父組件的調(diào)用方式相同,子組件通過defineExpose()
將方法或是屬性暴露出去
子組件 <script setup> const isShow = ref(false) // 父組件調(diào)用這個(gè)方法 const showSubComponent = () => { isShow.value = !isShow.value } // 通過defineExpose將方法暴露出去 defineExpose({ showSubComponent }) </script> 父組件 <template> <div class="todo-list"> <TodoItemVue :itemList="itemList" @clickItemHandel="clickItemHandel" ref="todoItemVueRef" /> </div> </template> <script setup> import { ref } from 'vue'; //獲取子組件ref const todoItemVueRef = ref(null) // 調(diào)用子組件的方法 const callItemFuncHandel = () => { todoItemVueRef.value.showSubComponent() } </script>
7.Vuex的使用
在vue3.0
與vue3.2
中創(chuàng)建Vuex
沒有區(qū)別,只不過在<template>
模板中使用Vuex的store
有細(xì)微差別。
import { createStore } from 'vuex'; import { ADD_ITEM_LIST, REDUCE_ITEM_LIST, CHANGE_ITEM_LIST_ASYNC } from './constants'; export default createStore({ state: { itemList: [ { text: 'Learn JavaScript', done: true }, { text: 'Learn Vue', done: false }, { text: 'Build something awesome', done: false }, ], }, getters: { doneItemList: (state) => state.itemList.filter((todo) => todo.done), }, mutations: { // 使用ES2015風(fēng)格的計(jì)算屬性命名功能 來使用一個(gè)常量作為函數(shù)名 [ADD_ITEM_LIST](state, item) { console.log('增加數(shù)據(jù)', item); state.itemList.push(item); }, [REDUCE_ITEM_LIST](state) { console.log('減少數(shù)據(jù)'); state.itemList.pop(); }, }, actions: { [CHANGE_ITEM_LIST_ASYNC]({ commit, state }, todoItem) { /// 模擬網(wǎng)絡(luò)請(qǐng)求 setTimeout(() => { commit(ADD_ITEM_LIST, todoItem); console.log('state===', state); }, 1000); }, }, modules: { }, });
在vue3.0
中我們一般在return中對(duì)store.state
進(jìn)行解構(gòu),然后可以直接在<template>
中使用state
中的值
<template> <div class="todo-item"> <ol> <li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"> {{ item.text }} </li> </ol> </div> </template> <script> export default { name: 'TodoItem', setup(props, { emit }) { return { // 對(duì)store.state進(jìn)行解構(gòu) ...store.state, clickItem, count, isShow, showSubComponent, } } }; </script>
vue3.2
中沒有了return,需要我們顯示的獲取要使用的stare
的值
<template> <div class="todo-item"> <ol> <li v-for="(item,index) in itemList" :key="index" class="todos" @click="clickItem(index)"> {{ item.text }} </li> </ol> </div> </template> <script setup> import { useStore } from 'vuex'; const store = useStore() // 獲取后在<template>中使用 const itemList = store.state.itemList </script>
8. <style>中的 v-bind
<style>
中的 v-bind
: 用于在 SFC <style>
標(biāo)簽中啟用組件狀態(tài)驅(qū)動(dòng)的動(dòng)態(tài) CSS 值
<script setup> import { ref, watchEffect } from 'vue'; const color = ref('black') const callChangeColorHandel = () => { if(color.value === 'black') { color.value = 'red' }else { color.value = 'black' } } </script> <style lang="scss" scoped> .todo-list { color: v-bind(color); } </style>
觸發(fā)callChangeColorHandel
函數(shù),在<style>
中的v-bind
指令可以動(dòng)態(tài)綁定的響應(yīng)式狀態(tài)。
三. 總結(jié)
整體來說,setup語法糖的引入簡化了使用Composition API
時(shí)冗長的模板代碼,也就是讓代碼更加簡潔,可讀性也更高。并且官方介紹vue3.2
在界面渲染的速度以及內(nèi)存的使用量上都進(jìn)行了優(yōu)化,本文只是對(duì)setup語法糖的常用方式進(jìn)行了總結(jié),更多vue3.2
新特性可以去官方文檔查看。
一些參考:
到此這篇關(guān)于Vue3.2語法糖使用的文章就介紹到這了,更多相關(guān)Vue3.2語法糖使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue一步到位的實(shí)現(xiàn)動(dòng)態(tài)路由
這篇文章主要介紹了vue一步到位的實(shí)現(xiàn)動(dòng)態(tài)路由,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06vue之保留小數(shù)點(diǎn)兩位小數(shù) 使用filters(過濾器)
這篇文章主要介紹了vue之保留小數(shù)點(diǎn)兩位小數(shù) 使用filters(過濾器),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11vuejs router history 配置到iis的方法
今天小編就為大家分享一篇vuejs router history 配置到iis的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09Vue實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽頁面寬度高度變化
這篇文章主要為大家詳細(xì)介紹了Vue如何實(shí)現(xiàn)實(shí)時(shí)監(jiān)聽頁面寬度高度變化,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03vue路由導(dǎo)航守衛(wèi)和請(qǐng)求攔截以及基于node的token認(rèn)證的方法
這篇文章主要介紹了vue路由導(dǎo)航守衛(wèi)和請(qǐng)求攔截以及基于node的token認(rèn)證的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-04-04解決antd 表單設(shè)置默認(rèn)值initialValue后驗(yàn)證失效的問題
這篇文章主要介紹了解決antd 表單設(shè)置默認(rèn)值initialValue后驗(yàn)證失效的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11Vue項(xiàng)目打包部署的實(shí)戰(zhàn)過程記錄
我們使用nginx部署Vue項(xiàng)目,實(shí)質(zhì)上就是將Vue項(xiàng)目打包后的內(nèi)容同步到nginx指向的文件夾,下面這篇文章主要給大家介紹了關(guān)于Vue項(xiàng)目打包部署的相關(guān)資料,需要的朋友可以參考下2021-09-09