在上一篇實(shí)戰(zhàn)演練中,已經(jīng)將項(xiàng)目搭建好,并介紹了 Router、Vuex 的基本用法
接下來會(huì)以一個(gè) Todo List 項(xiàng)目來介紹實(shí)戰(zhàn)中如何使用 Composition API
一、輸入框與列表(按鍵別名 + computed 類型聲明 )
首先是輸入框,由于需要支持回車鍵提交,所以需要監(jiān)聽 keydown 事件
如果是傳統(tǒng)的按鍵處理,需要在事件對(duì)象中根據(jù) keyCode 來判斷按鍵
Vue 提供了一些常用的按鍵修飾符,不用在事件處理函數(shù)中再做判斷
比如這里就使用了 enter 修飾符,直接監(jiān)聽 enter 鍵的 keydown 事件
列表部分,需要判斷當(dāng)前列表是否為空,如果為空則展示空狀態(tài)
這里使用了 v-if 和 v-else 來做條件判斷,而其判斷條件 showList 是一個(gè)計(jì)算屬性 computed
在 TypeScript 的項(xiàng)目中,如果像 JS 項(xiàng)目一樣添加計(jì)算屬性,無法進(jìn)行類型推斷
需要加上類型聲明:
// 在 setup() 中通過 computed() 注冊(cè)的計(jì)算屬性不需要聲明類型
二、添加、刪除條目(在 setup 中使用 vuex)
創(chuàng)建的條目需要保存到 store 中,首先需要定義條目類型
然后在 state 中新增 todoList 字段,用于保存列表
這里還添加了一個(gè) todoListMap 字段,是 todoList 的字典項(xiàng),后面查找條目的時(shí)候會(huì)用到
同時(shí)在 mutations 中新增添加和刪除方法
Store 已經(jīng)調(diào)整好了,接下來只要在組件中調(diào)用即可
可以像之前介紹的那樣,使用 mapState 和 mapMutations 來導(dǎo)出對(duì)應(yīng)的字段和方法
不過如果想在 setup 中使用 vuex,就需要用到 vuex 4 提供的 useStore 方法
import { useStore } from 'vuex';
export default {
//...
setup() {
const store = useStore();
console.log('store--->', store);
return { ...store.state }
}
}
從截圖可以看到,useStore() 的返回值其實(shí)就是 $store
接下來的事情就簡單了,手動(dòng)導(dǎo)出需要用到的 state 和 mutations、actions 即可
這種方式導(dǎo)出 state 還行,但對(duì)于 mutation 和 action,需要一個(gè)一個(gè)手動(dòng)創(chuàng)建函數(shù)并導(dǎo)出,就比較笨重
沒關(guān)系,我們還有 mapMutations 和 mapActions 可以使用
但需要注意,不要在 setup 使用 mapState!
因?yàn)?mapState 導(dǎo)出 state 是一個(gè)函數(shù)(computed),這個(gè)函數(shù)內(nèi)部使用了 this.$store
而 setup 中 this 是一個(gè)空值,所以在 setup 中使用 mapState 會(huì)報(bào)錯(cuò)
如果確實(shí)希望以 mapState 的形式在 setup 中導(dǎo)出 state,可以看一下 vuex-composition-helpers
import { useState, useActions } from 'vuex-composition-helpers';
export default {
props: {
articleId: String
},
setup(props) {
const { fetch } = useActions(['fetch']);
const { article, comments } = useState(['article', 'comments']);
fetch(props.articleId); // dispatch the "fetch" action
return {
// both are computed compositions for to the store
article,
comments
}
}
}
三、查看條目詳情(在 setup 中使用 router)
在條目詳情頁,可以在 url 上攜帶條目 id,然后通過 id 在 store 中找到對(duì)應(yīng)的數(shù)據(jù)
這就需要調(diào)整路由配置文件 src/router/index.ts,配置 vue-router 中的動(dòng)態(tài)路由
路由配置好了,接下來需要在列表上添加“查看詳情”按鈕的處理函數(shù)
如果這個(gè)函數(shù)寫在 methods 里面,可以直接通過 this.$router.push() 來跳轉(zhuǎn)頁面
但是在 setup 中,就需要用到 vue-router 提供的 useRouter
import { useRouter } from 'vue-router';
export default {
// ...
setup() {
const router = useRouter();
const viewItem = (id: string) => {
router.push(`/about/${id}`);
};
return { viewItem };
}
}
然后在詳情頁,通過 useRoute(注意不是 userRouter )獲取 params
四、完全使用 Composition API 開發(fā)組件
以上都是在 setup 中使用 Composition API,整個(gè)組件本身依然是使用 Options API 開發(fā)
想象一下,如果整個(gè)組件的 <script> 部分就是一個(gè) setup 函數(shù),會(huì)發(fā)生什么呢?
給 <script> 標(biāo)簽加上 setup 修飾符試試!
<script lang="ts" setup>
// ...
</script>
然后把整個(gè) <script> 當(dāng)做 setup 函數(shù),改寫上面的詳情頁
這樣就能完全使用 Composition API 來開發(fā)組件了
和 setup 的區(qū)別在于,setup 最終需要 return 一個(gè)對(duì)象,而現(xiàn)在需要使用 export 來導(dǎo)出變量
如果需要使用 setup 函數(shù)的參數(shù) ( props 和 context ),可以這么寫:
<script lang="ts" setup="props, { emit }">
等效于
setup(props, { emit }) {
// ...
}
最后再貼一份 script-setup 的組件示例:
<script lang="ts" setup="props, { emit }">
import {
defineComponent,
computed,
onMounted,
ref,
toRefs,
} from 'vue';
const { modelValue, disabled } = toRefs(props);
/* data */
export const currentValue = ref('');
export const isComposing = ref(false);
/* methods */
export function handleInput() {
if (isComposing.value) return;
emit('update:modelValue', currentValue.value);
}
/* lifecycle */
onMounted(() => {
currentValue.value = modelValue.value;
});
/* computed */
export const inputDisabled = computed(() => disabled.value);
export default defineComponent({
name: 'test-input',
props: {
modelValue: [String, Number],
disabled: Boolean,
},
emits: {
'update:modelValue': null,
},
});
</script>
在這份代碼中,我還是按照組件選項(xiàng)的方式,將變量分類放到一起
其實(shí)更合理的方式是按功能分類,這樣更利于抽取邏輯
五、小結(jié)
Vuex 和 vue-router 都提供了可以在 setup 中獲取實(shí)例的方法
這也側(cè)面體現(xiàn)了 Vue 3 的 setup 是一個(gè)獨(dú)立的鉤子函數(shù)
它不會(huì)依賴于 Vue 組件實(shí)例,如果需要用到函數(shù)外部的變量,都需要從外部獲取
同時(shí)也提醒我們?cè)陂_發(fā) Vue 3 的插件的時(shí)候,一定要提供相應(yīng)的函數(shù)讓開發(fā)者能在 setup 中使用
聯(lián)系客服