Composition Api
解决碎片化导致理解和维护复杂组件变得困难。将同一个逻辑关注点相关代码收集在一起
setup
选项
- 在组件创建之前执行,一旦 props 被解析,就将作为组合式 API 的入口。
避免使用 this
,因为其发生在 data
、computed
或 methods
被解析之前,还没有找到组件实例
setup
是接收 props
和 context
的函数,return
的所有内容都暴露给组件的其余部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted, watch, toRefs, computed } from 'vue'
export default { component: {RepositoriesFilters, RepositoriesSortBy}, props: { user: { type: string, required: true, } }, setup(props) { const { user } = toRefs(props)
let repositories = ref([]) const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(user.value) }
onMounted(getUserRepositories)
watch(user, getUserRepositories)
const searchQuery = ref("") const repositoriesMatchingSearchQuery = computed(() => { return repositories.value.filter( repository => repository.name includes(searchQuery.value) ) })
return { repositories, getUserRepositories, searchQuery, repositoriesMatchingSearchQuery } }, }
|
带 ref
的响应式变量
在 setup
内注册生命周期钩子
- 前缀为
on
, 即 mounted
看起来会像 onMounted
- 这些函数接受一个回调,当钩子被组件调用时,该回调将被执行
watch(ref[getter], cb, options)
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| const counter = ref(0) watch(counter, (newValue, oldValue) => { console.log('The new counter value is: ' + counter.value) })
export default { data() { return { counter: 0 } }, watch: { counter(newValue, oldValue) { console.log('The new counter value is: ' + this.counter) } } }
|
独立的 computed
属性
- 函数输出一个只读的响应式引用,用
.value
访问值1 2 3 4 5 6 7 8
| import { ref, computed } from 'vue'
const counter = ref(0) const twiceTheCounter = computed(() => counter.value * 2)
counter.value++ console.log(counter.value) console.log(twiceTheCounter.value)
|
提取到独立的组合式函数中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import { fetchUserRepositories } from '@/api/repositories' import { ref, onMounted, watch } from 'vue'
export default function useUserRepositories(user) { let repositories = ref([])
const getUserRepositories = async () => { repositories.value = await fetchUserRepositories(user.value) }
onMounted(getUserRepositories) watch(user, getUserRepositories)
return { repositories, getUserRepositories } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { ref, computed } from 'vue'
export default function useRepositoryNameSearch(repositories) { const searchQuery = ref('') const repositoriesMatchingSearchQuery = computed(() => { return repositories.value.filter(repository => { return repository.name.includes(searchQuery.value) }) })
return { searchQuery, repositoriesMatchingSearchQuery }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import useUserRepositories from '@/composables/useUserRepositories' import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch' import { toRefs } from 'vue'
export default { components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList }, props: { user: { type: String, required: true } }, setup (props) { const { user } = toRefs(props)
const { repositories, getUserRepositories } = useUserRepositories(user) const { searchQuery, repositoriesMatchingSearchQuery } = useRepositoryNameSearch(repositories)
return { repositories: repositoriesMatchingSearchQuery, getUserRepositories, searchQuery, } } }
|
TS
1 2 3 4 5
| import { defineComponent } from '@vue/composition-api'
export default defineComponent({ })
|