<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在Vue2
時期,元件裡定義的各類變數、方法、計算屬性等是分別存放到data
、methods
、computed
等選項裡,這樣編寫的程式碼不便於後期的查閱,查詢一個業務邏輯需要在各個選項來回切換。vue3.0
組合式APIsetup
函數的推出就是為了解決這個問題,它讓我們的邏輯關注點更加集中,語法也更加精簡,但是當我們在使用vue3.0
的語法就構建元件的時候,總是需要把外面定義的方法變數必須要return出去才能在<template>
,比較麻煩一些. vue3.2
語法糖的出現以及一些新增的API,讓我們的程式碼進一步簡化。
語法糖(英語:Syntactic sugar)是由英國電腦科學家彼得·蘭丁發明的一個術語,指計算機語言中新增的某種語法,這種語法對語言的功能沒有影響,但是更方便程式設計師使用。語法糖讓程式更加簡潔,有更高的可讀性。
來看下vue3.0
與vue3.2
的單檔案元件(SFC,即.vue 檔案)的結構對比
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('測試一下') const changeTitle = () => { title.value = 'Hello,World' } </script> <style lang="scss" scoped> </style>
對比vue3.0
與vue3.2
版本的元件模板,最主要的變化是3.2中沒有了setup
函數,而是把它放在了script標籤中。
我們定義的屬性和方法也不用在return中返回,直接就可以用在模板語法中 ...
這些是直觀的變化,接下來我們學習具體的用法。
vue3.0
中使用元件,需要使用 components 選項來顯式註冊:
<script> import ComponentA from './ComponentA.js' export default { components: { ComponentA }, setup() { // ... } } </script>
vue3.2
<script setup>
的單檔案元件中,匯入的元件可以直接在模板中使用,元件會自動註冊,並且無需指定當前元件的名字,它會自動以檔名為主,也就是不用再寫name屬性了。
<script setup> import ComponentA from './ComponentA.vue' </script> <template> <ComponentA /> </template>
在vue3.0
中,prop
可以使用props
選項來宣告
<script> export default { props: ['foo'], // 或者用這種方式指型別與預設值 // props: { // foo:{ // type: String, // default: '' // }, // }, setup(props) { // setup() 接收 props 作為第一個引數 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>
注意事項:所有的 props 都遵循著單向繫結原則,props 因父元件的更新而變化,自然地將新的狀態向下流往子元件,而不會逆向傳遞,這意味著你不應該在子元件中去更改一個 prop。
我們一般使用計算屬性來描述依賴響應式狀態的複雜邏輯。說白了就是這個計算屬性的值依賴於其他響應式屬性的值,依賴的屬性發生變化,那麼這個計算屬性的值就會進行重新計算。
<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) { // 注意:我們這裡使用的是解構賦值語法 [firstName.value, lastName.value] = newValue.split(' ') } }) </script>
當呼叫fullName.value = 'John Doe'
時,setter
會被呼叫,而firstName
和 lastName
會被更新,在vue3.2
中我們可以直接在<template>
標籤中使用它,不在需要return返回。
- 不要在計算函數中做非同步請求或者更改 DOM!
- 一個計算屬性僅會在其響應式依賴更新時才重新計算,如果他依賴的是個非響應式的依賴,及時其值發生變化,計算屬性也不會更新。
- 相比於方法而言,計算屬性值會基於其響應式依賴被快取,一個計算屬性僅會在其響應式依賴更新時才重新計算
在組合式API中,我們可以使用watch
函數在每次響應式狀態發生變化時觸發回撥函數,watch
的第一個引數可以是不同形式的“資料來源”:它可以是一個 ref
(包括計算屬性)、一個響應式物件、一個 getter
函數、或多個資料來源組成的陣列: watch()
是懶執行的:僅當資料來源變化時,才會執行回撥,例如:
<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>
這裡監聽
props.itemList.length
,當傳入的itemList
數量發生變化時,後面的回撥方法會被呼叫。當然wacth()
還有第三個可選引數:否開啟深監聽(deep)
, 如果這裡這樣寫:<script setup> import { ref,watch } from 'vue'; ... watch(() => props.itemList,(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); }) </script>當傳入的
itemList
數量發生改變時,回撥函數不會觸發,正確的寫法是加上其第三個引數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
也可以同時監聽多個屬性:
<script setup> import { ref,watch } from 'vue'; const props = defineProps({ title: String, itemList: { type: Array, default: () => [{ text: 'title', value: 0 }] } }) // 同時監聽多個屬性 watch(() => [props.itemList,props.title],(newValue,oldValue) => { console.log('newValue===',newValue); console.log('oldValue===',oldValue); },{deep:true}) </script>
與watch()
的懶執行不同的是,watchEffect()
會立即執行一遍回撥函數,如果這時函數產生了副作用,Vue
會自動追蹤副作用的依賴關係,自動分析出響應源。上面的例子可以重寫為:
<script setup> ... watchEffect(() => { console.log('itemList===',props.itemList.length); console.log('title===',props.title); }) </script>
這個例子中,回撥會立即執行。在執行期間,它會自動追蹤props.itemList.length
作為依賴(和計算屬性的行為類似)。每當傳入的itemList.length
變化時,回撥會再次執行。
如果要清除watchEffect()
的的監聽,只需要顯示的呼叫watchEffect()
的返回函數就可以了,例如:
<script setup> ... const stopEffect = watchEffect(() => { console.log('itemList===',props.itemList.length); console.log('title===',props.title); }) stopEffect() </script>
watch 只追蹤明確偵聽的資料來源。它不會追蹤任何在回撥中存取到的東西。另外,僅在資料來源確實改變時才會觸發回撥。我們能更加精確地控制回撥函數的觸發時機。 watchEffect,則會在副作用發生期間追蹤依賴。它會在同步執行過程中,自動追蹤所有能存取到的響應式屬性。
vue3.0
中如果我們的子元件觸發父元件的方法,我們的做法:
子元件 <script> export default { emits: ['inFocus', 'submit'], setup(props, ctx) { ctx.emit('submit',params) } } // 或者將可以將emit解構使用 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('子元件呼叫了父元件的submitHandel方法'); } return { submitHandel, } } }; </script>
vue3.2
語法糖中,子元件要觸發的事件需要顯式地通過 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('子元件呼叫了父元件的submitHandel方法'); } }; </script>
vue3.0
中如果父元件觸發子元件的方法或是屬性,直接在return函數中返回就可以,資料都是預設隱式暴露給父元件的。
<script> // 子元件 setup(props, { emit }) { const isShow = ref(false) // 父元件呼叫這個方法 const showSubComponent = () => { isShow.value = !isShow.value } return { // return 返回 showSubComponent, } } </script>
父元件中通過ref
獲取到子元件,並對子元件暴露的方法進行存取
父元件 <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) // 呼叫子元件的方法 const callItemFuncHandel = () => { todoItemVueRef.value.showSubComponent() } return { todoItemVueRef } } }; </script>
vue3.2
語法中,父元件的呼叫方式相同,子元件通過defineExpose()
將方法或是屬性暴露出去
子元件 <script setup> const isShow = ref(false) // 父元件呼叫這個方法 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) // 呼叫子元件的方法 const callItemFuncHandel = () => { todoItemVueRef.value.showSubComponent() } </script>
在vue3.0
與vue3.2
中建立Vuex
沒有區別,只不過在<template>
模板中使用Vuex的store
有細微差別。
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風格的計算屬性命名功能 來使用一個常數作為函數名 [ADD_ITEM_LIST](state, item) { console.log('增加資料', item); state.itemList.push(item); }, [REDUCE_ITEM_LIST](state) { console.log('減少資料'); state.itemList.pop(); }, }, actions: { [CHANGE_ITEM_LIST_ASYNC]({ commit, state }, todoItem) { /// 模擬網路請求 setTimeout(() => { commit(ADD_ITEM_LIST, todoItem); console.log('state===', state); }, 1000); }, }, modules: { }, });
在vue3.0
中我們一般在return中對store.state
進行解構,然後可以直接在<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 { // 對store.state進行解構 ...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>
<style>
中的 v-bind
: 用於在 SFC <style>
標籤中啟用元件狀態驅動的動態 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>
觸發callChangeColorHandel
函數,在<style>
中的v-bind
指令可以動態繫結的響應式狀態。
整體來說,setup語法糖的引入簡化了使用Composition API
時冗長的模板程式碼,也就是讓程式碼更加簡潔,可讀性也更高。並且官方介紹vue3.2
在介面渲染的速度以及記憶體的使用量上都進行了優化,本文只是對setup語法糖的常用方式進行了總結,更多vue3.2
新特性可以去官方檔案檢視。
一些參考:
到此這篇關於Vue3.2語法糖使用的文章就介紹到這了,更多相關Vue3.2語法糖使用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45