Vue3技术8
- Fragment
- Teleport
- 弹窗案例
- 目录结构
- App.vue
- Child.vue
- Son.vue
- Dialog.vue
- 总结
- Suspense
- 普通写法
- App.vue
- Child.vue
- 使用suspense之后
- App.vue
- Child.vue
- 不再自己调整网络低速
- Child.vue
- App.vue
- 总结
- 补充setup的一个知识点
- Suspense总结
- Vue3中其他的改变
- 全局API的转移
- 其他改变
Fragment
- 在Vue2中:组件必须有一个根标签
- 在Vue3中:组件可以没有根标签,内部会将多个标签包含在一个Fragment虚拟元素中
- 好处:减少标签层级,减少内存占用
Teleport
弹窗案例
目录结构
App.vue
<template><div class="app"><h1>我是App组件</h1><Child></Child></div>
</template><script>
import Child from "@/components/Child";export default {name: 'App',components: {Child},
}
</script><style scoped>
.app{background-color: gray;padding: 10px;
}
</style>
Child.vue
<template><div class="child"><h1>我是Child组件</h1><Son></Son></div>
</template><script>
import Son from "@/components/Son";
export default {name: "Child",components: {Son}
}
</script><style scoped>
.child{background-color: orange;padding: 10px;
}
</style>
Son.vue
<template><div class="son"><h1>我是Son组件</h1><Dialog></Dialog></div>
</template><script>
import Dialog from "@/components/Dialog";
export default {name: "Son",components: {Dialog},
}
</script><style scoped>
.son{background-color: pink;padding: 10px;
}
</style>
Dialog.vue
<template><div><button @click="isShow=true">点我弹个窗</button><teleport to="body"><div class="mask" v-if="isShow"><div class="dialog"><h3>我是一个弹窗</h3><h4>一些内容</h4><h4>一些内容</h4><h4>一些内容</h4><button @click="isShow=false">关闭弹窗</button></div></div></teleport></div>
</template><script>
import {ref} from "vue";export default {name: "Dialog",setup(){let isShow=ref(false)return{isShow}},
}
</script><style scoped>
.mask{position: absolute;top: 0;bottom: 0;left: 0;right: 0;background-color: rgba(0,0,0,0.5);
}
.dialog{width: 300px;height: 300px;background-color: skyblue;text-align: center;position: absolute;left: 50%;top: 50%;transform: translate(-50%,-50%);
}
</style>
总结
- 什么是Teleport?——Teleport是一种能将我们的
组件html结构
移动到指定位置的技术
<teleport to="移动位置"><div v-if="isShow" class="mask"><div class="dialog"><h3>我是一个弹窗</h3><button @click="isShow=false">关闭弹窗</button></div></div>
</teleport>
Suspense
普通写法
App组件和Child组件是一起加载出来的
App.vue
<template><div class="app"><h1>我是App组件</h1><Child></Child></div>
</template><script>
import Child from "@/components/Child"; //静态引入export default {name: 'App',components: {Child},
}
</script><style scoped>
.app{background-color: gray;padding: 10px;
}
</style>
Child.vue
<template><div class="child"><h1>我是Child组件</h1></div>
</template><script>
export default {name: "Child",
}
</script><style scoped>
.child{background-color: orange;padding: 10px;
}
</style>
使用suspense之后
App.vue
<template><div class="app"><h1>我是App组件</h1><suspense><template v-slot:default><Child></Child></template><template v-slot:fallback><h3>稍等,加载中...</h3></template></suspense></div>
</template><script>
// import Child from "@/components/Child"; //静态引入
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child')) //异步引入
export default {name: 'App',components: {Child},
}
</script><style scoped>
.app{background-color: gray;padding: 10px;
}
</style>
Child.vue
<template><div class="child"><h1>我是Child组件</h1></div>
</template><script>
export default {name: "Child",
}
</script><style scoped>
.child{background-color: orange;padding: 10px;
}
</style>
不再自己调整网络低速
Child.vue
<template><div class="child"><h1>我是Child组件</h1><div>{{sum}}</div></div>
</template><script>
import {ref} from "vue";export default {name: "Child",async setup(){let sum=ref(0)const p= new Promise((resolve, reject) => {setTimeout(() => {resolve({sum})},3000)})return await p}
}
</script><style scoped>
.child{background-color: orange;padding: 10px;
}
</style>
App.vue
<template><div class="app"><h1>我是App组件</h1><suspense><template v-slot:default><Child></Child></template><template v-slot:fallback><h3>稍等,加载中...</h3></template></suspense></div>
</template><script>
// import Child from "@/components/Child"; //静态引入
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child')) //异步引入
export default {name: 'App',components: {Child},
}
</script><style scoped>
.app{background-color: gray;padding: 10px;
}
</style>
总结
补充setup的一个知识点
- setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性。(后期也可以返回一个Promise实例,但需要Suspense和异步组件的配合)
Suspense总结
- 等待异步组件时渲染一些额外内容,让应用有更好的用户体验
- 使用步骤
(1)异步引入组件
import {defineAsyncComponent} from 'vue'
const Child=defineAsyncComponent(()=>import('@/components/Child')) //异步引入
(2)使用Suspense包裹组件,并配置好default与fallback
<template><div class="app"><h1>我是App组件</h1><suspense><template v-slot:default><Child/></template><template v-slot:fallback><h3>稍等,加载中...</h3></template></suspense></div>
</template>
Vue3中其他的改变
全局API的转移
- Vue 2.x 有许多全局 API 和配置。
例如:注册全局组件、注册全局指令等
//注册全局组件Vue.component('MyButton', {data: () => ({count: 0}),template: '<button @click="count++">Clicked {{ count }} times.</button>'})//注册全局指令Vue.directive('focus', {inserted: el => el.focus()}
-
Vue3中对这些API做了调整
将全局的API,即:Vue.xxx调整到应用实例(app)2.x 全局 API( Vue
)3.x 实例 API ( app
)Vue.config.xxxx app.config.xxxx Vue.config.productionTip 移除 Vue.component app.component Vue.directive app.directive Vue.mixin app.mixin Vue.use app.use Vue.prototype app.config.globalProperties
其他改变
- data选项应始终被声明为一个函数。
- 过度类名的更改:
-
Vue2.x写法
.v-enter, .v-leave-to {opacity: 0; } .v-leave, .v-enter-to {opacity: 1; }
-
Vue3.x写法
.v-enter-from, .v-leave-to {opacity: 0; }.v-leave-from, .v-enter-to {opacity: 1; }
移除
keyCode作为 v-on 的修饰符,同时也不再支持config.keyCodes
移除
修饰符
-
父组件中绑定事件
<my-componentv-on:close="handleComponentEvent"v-on:click="handleNativeClickEvent" />
-
子组件中声明自定义事件
<script>export default {emits: ['close']} </script>
移除
过滤器(filter)
过滤器虽然这看起来很方便,但它需要一个自定义语法,打破大括号内表达式是 “只是 JavaScript” 的假设,这不仅有学习成本,而且有实现成本!建议用方法调用或计算属性去替换过滤器。
- …