邏輯分離和複用
阿新 • • 發佈:2020-12-19
Vue 2.x 程式碼寫法
<template> <div class="search"> <form> <input v-model="searchValue" type="text" /> <button @click="search"></button> </form> </div> <ul class="result"> <li class="result__item" v-for="item in filterData" :key="item.id"> {{ item.name }} </li> </ul> <span v-if="loading">Loading</span> </template> <script> export default { data() { searchValue: '', loading: true, searchResult: [] }, computed: { filterData() { return searchResult.filter(i => i.id > 3) } }, methods: { async search() { this.loading = true const { data } = await fetch('/search', body: this.searchValue.trim()) this.searchResult = data.toJSON() this.loading = false } }, mounted() { this.search() } } </script>
使用 Composition API 下工作的程式碼
明顯變化:
- 元件從原本的選項配置變成了函式定義
- 元件也不需要使用 this 去指定當前元件執行的上下文
<template> <div class="search"> <form> <input v-model="state.searchValue" type="text" /> <button @click="search"></button> </form> <ul class="result"> <li class="result__item" v-for="item in filterData" :key="item.id"> {{ item.name }} </li> </ul> <span v-if="state.loading">Loading</span> </div> </template> <script> import { reactive, computed, onMounted, toRef } from '@vue/composition-api' export default { setup() { // 初始化資料 const state = reactive({ searchValue: '', loading: true, searchResult: [] }) const filterData = computed(() => state.searchResult.filter(i => i.id > 3)) async function search() { state.loading = true const { data } = await fetch('/search', body: this.searchValue.trim()) state.searchResult = data.toJSON() state.loading = false } onMounted(() => { search() }) return { ...toRef(state), filterData, search } } } </script>
邏輯分離和複用
<script> import { reactive, computed, onMounted, toRef, ref } from '@vue/composition-api' // 方法提取 function useSearch() { const searchValue = ref('') const searchResult = ref([]) const loading = ref(true) async function search() { loading.value = true const { data } = await fetch('/search', body: searchValue.trim()) searchResult.value = data.toJSON() loading.value = false } onMounted(() => search()) return { searchValue, searchResult, loading, search } } // 提取計算屬性 function useFilterSearchResult(searchResult) { const filterData = computed(() => searchResult.value.filter(I=》 i.id > 3)) return { filterData } } export default { setup(props, context) { const search = useSearch() return { ...search, ...useFilterSearchResult(search.searchResult) } } } </script>
缺點 (資料無響應情況)
當state作為一個返回值或引數的時候,它實際是作為一個值傳遞到了另外一個方法中,所以getter、setter將會丟失,資料無法響應。引用傳遞及值傳遞
function useMounsePosition(){
const pos = reactive({
x: 0,
y: 0
})
onMount(() => {})
return pos
}
# 資料響應丟失清空
export default {
setup() {
// 這裡只取了 useMousePosition 返回值的引用值
// 而值裡面的 getter / setter 丟失
const { x, y } = useMousePosition()
// 響應丟失
return { x, y }
// 響應丟失
return { ...useMousePosition() }
// 可以工作
return {
pos: useMousePosition()
}
}
}
解決方案一 使用 toRefs
function useMounsePosition(){
const pos = reactive({
x: 0,
y: 0
})
onMount(() => {})
return toRefs(pos)
}
export default {
setup() {
// 正確
const { x, y } = useMousePosition()
return { x, y }
// 正確
return { ...useMousePosition() }
}
}
解決方案二 使用 ref去初始資料
unction useMounsePosition(){
const x = ref(0)
const y = ref(0)
onMount(() => {
document.body.addeventListener("mousemove", (e) => {
x.value = e.x
y.value = e.y
})
})
return { x, y }
}
export default {
setup() {
// 正確
const { x, y } = useMousePosition()
return { x, y }
// 正確
return { ...useMousePosition() }
}
}