使用 defineComponent 包裹组件
Teleport - 瞬间移动 第一部分
vue3 新添加了一个默认的组件就叫 Teleport,我们可以拿过来直接使用,它上面有一个 to 的属性,它接受一个css query selector 作为参数,这就是代表要把这个组件渲染到哪个 dom 元素中\
JavaScript复制代码
<template> <teleport to="#modal"> <div id="center"> <h1>this is a modal</h1> </div> </teleport> </template> <style> #center { width: 200px; height: 200px; border: 2px solid black; background: white; position: fixed; left: 50%; top: 50%; margin-left: -100px; margin-top: -100px; } </style> 复制代码
Teleport - 瞬间移动 第二部分
Modal 组件\
JavaScript复制代码
<template> <teleport to="#modal"> <div id="center" v-if="isOpen"> <h2><slot>this is a modal</slot></h2> <button @click="buttonClick">Close</button> </div> </teleport> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ props: { isOpen: Boolean, }, emits: { 'close-modal': null }, setup(props, context) { const buttonClick = () => { context.emit('close-modal') } return { buttonClick } } }) </script> <style> #center { width: 200px; height: 200px; border: 2px solid black; background: white; position: fixed; left: 50%; top: 50%; margin-left: -100px; margin-top: -100px; } </style> 复制代码
在 App 组件中使用\
JavaScript复制代码
const modalIsOpen = ref(false) const openModal = () => { modalIsOpen.value = true } const onModalClose = () => { modalIsOpen.value = false } <button @click="openModal">Open Modal</button><br/> <modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal> 复制代码
Suspense - 异步请求好帮手第一部分
定义一个异步组件,在 setup 返回一个 Promise,AsyncShow.vue
<template> <h1>{{result}}</h1> </template> <script lang="ts"> import { defineComponent } from 'vue' export default defineComponent({ setup() { return new Promise((resolve) => { setTimeout(() => { return resolve({ result: 42 }) }, 3000) }) } }) </script> 复制代码
在 App 中使用
<Suspense> <template #default> <async-show /> </template> <template #fallback> <h1>Loading !...</h1> </template> </Suspense> 复制代码
Suspense - 异步请求好帮手第二部分
使用 async await 改造一下异步请求, 新建一个 DogShow.vue 组件
<template> <img :src="result && result.message"> </template> <script lang="ts"> import axios from 'axios' import { defineComponent } from 'vue' export default defineComponent({ async setup() { const rawData = await axios.get('https://dog.ceo/api/breeds/image') return { result: rawData.data } } }) </script> 复制代码
Suspense 中可以添加多个异步组件
<Suspense> <template #default> <async-show /> <dog-show /> </template> <template #fallback> <h1>Loading !...</h1> </template> </Suspense> 复制代码
全局 API 修改
Vue2 的全局配置
import Vue from 'vue' import App from './App.vue' Vue.config.ignoredElements = [/^app-/] Vue.use(/* ... */) Vue.mixin(/* ... */) Vue.component(/* ... */) Vue.directive(/* ... */) Vue.prototype.customProperty = () => {} new Vue({ render: h => h(App) }).$mount('#app') 复制代码
Vue2 这样写在一定程度上修改了 Vue 对象的全局状态。
- 第一,在单元测试中,全局配置非常容易污染全局环境,用户需要在每次 case 之间,保存和恢复配置。有一些 api (vue use vue mixin)甚至没有方法恢复配置,这就让一些插件的测试非常的困难。
- 第二,在不同的 APP 中,如果想共享一份有不同配置的 vue 对象,也变得非常困难。
Vue3 的修改\
JavaScript复制代码
import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) // 这个时候 app 就是一个 App 的实例,现在再设置任何的配置是在不同的 app 实例上面的,不会像vue2 一样发生任何的冲突。 app.config.isCustomElement = tag => tag.startsWith('app-') app.use(/* ... */) app.mixin(/* ... */) app.component(/* ... */) app.directive(/* ... */) app.config.globalProperties.customProperty = () => {} // 当配置结束以后,我们再把 App 使用 mount 方法挂载到固定的 DOM 的节点上。 app.mount(App, '#app')