Teleport 提供了一種乾淨的方法,容許咱們控制在 DOM 中哪一個父節點下渲染了 HTML,而沒必要求助於全局狀態或將其拆分爲兩個組件。css
效果:html
目錄:vue
index.html:react
<!DOCTYPE html> <html lang=""> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="<%= BASE_URL %>favicon.ico"> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <noscript> <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong> </noscript> <div id="app"></div> <div id="m-dialog"></div> <!-- built files will be auto injected --> </body> </html>
Dialog.vue:app
<template> <div :class="[`m-mask ${visible ? 'active' : ''}`]"> <div class="m-dialog"> <div class="m-header"> <span class="m-header-title">{{title}}</span> <span class="m-header-close" @click="handleClose">X</span> </div> <div class="m-content"> <slot name="content"></slot> </div> <div class="m-footer"> <button class="m-btn" @click="handleOk">肯定</button> <button class="m-btn" @click="handleClose">取消</button> </div> </div> </div> </template> <script> export default { props: { visible: { type: Boolean }, title: { type: String } }, emits: ['onClose', 'onOk'], setup(props, context) { const handleClose = () => { context.emit('onClose') } const handleOk = () => { context.emit('onOk') } return { handleClose, handleOk } } } </script> <style> </style>
Home.vue:ide
<template> <Teleport to="#m-dialog"> <Dialog :visible="visible" title="標題" @onClose="handleCloseDialog" @onOk="handleOk"> <template #content> <div class="m-info"> <span class="m-msg">你好!</span> </div> </template> </Dialog> </Teleport> <button @click="handleShowDialog">按鈕</button> </template> <script> import { reactive, toRefs } from "vue"; import Dialog from "../components/Dialog"; export default { components: { Dialog, }, setup() { const state = reactive({ visible: false, }); const handleShowDialog = () => { state.visible = true } const handleCloseDialog = () => { state.visible = false } const handleOk = () => { console.log('ok') handleCloseDialog() } const { visible } = toRefs(state) return { visible, handleShowDialog, handleCloseDialog, handleOk } }, }; </script> <style> </style>
index.css:flex
.m-mask{position: absolute;display: none; top: 0;left: 0;right: 0;bottom: 0;background: rgba(0 , 0, 0, 0.1);} .m-mask.active{display: flex;} .m-dialog{display: flex;flex-direction: column; margin: auto;min-width: 400px;min-height: 100px;background: #fff;border-radius: 5px;box-shadow: 10px 10px 5px #888;} .m-header{display: flex;line-height: 40px;border-bottom: 1px solid #ddd;} .m-header-title{flex:1;padding: 0 0 0 5px;} .m-header-close{width: 40px;text-align: center;cursor: pointer;} .m-info{display: flex;height: 100px;} .m-msg{margin: auto;} .m-content{flex:1;} .m-footer{ line-height: 40px;border-top: 1px solid #ddd; text-align: right;} .m-btn{margin: 0 5px;}