组合式 API
为什么需要它
能够将与同一个逻辑关注点相关的代码配置在一起(解决选项式api的痛点)
基础
// src/components/UserRepositories.vue
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: { type: String }
},
setup(props) {
console.log(props) // { user: '' }
return {} // 这里返回的任何内容都可以用于组件的其余部分
}
// 组件的“其余部分”
}
声明响应式变量
基本类型+数组
在 Vue 3.0 中,我们可以通过一个新的 ref 函数使任何响应式变量在任何地方起作用,如下所示:
import { ref } from 'vue'
const counter = ref(0)
console.log(counter) // { value: 0 }
console.log(counter.value) // 0
counter.value++
console.log(counter.value) // 1
其实本质就是将值传递转换成引用传递(拿到指针)
引用类型
reactive:返回对象的响应式副本
const obj = reactive({ count: 0 })
生命周期的变化
这些函数接受一个回调函数,当钩子被组件调用时将会被执行:
// MyBook.vue
export default {
setup() {
// mounted
onMounted(() => {
console.log('Component is mounted!')
})
}
}
状态逻辑复用
根据组合api,我们可以抽离公用的状态逻辑,不再使用mixin
function useMouse() {
const x = ref(0)
const y = ref(0)
const update = e => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
// 在组件中使用该函数
const Component = {
setup() {
const { x, y } = useMouse()
// 与其它函数配合使用
const { z } = useOtherLogic()
return { x, y, z }
},
template: `<div>{{ x }} {{ y }} {{ z }}</div>`
}
内置组件
Teleport
背景
Vue 鼓励我们通过将 UI 和相关行为封装到组件中来构建 UI。我们可以将它们嵌套在另一个内部,以构建一个组成应用程序 UI 的树。
然而,有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
一个常见的场景是创建一个包含全屏模式的组件。在大多数情况下,你希望模态的逻辑存在于组件中,但是模态的定位很快就很难通过 CSS 来解决,或者需要更改组件组合。
Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下呈现 HTML
,而不必求助于全局状态或将其拆分为两个组件。
const app = Vue.createApp({});
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
app.mount('#app')