在 Composition API 中使用 props 與 emit 操控 modal 在前端工程師的日常中,modal/ 彈出視窗 是常常會遇到的工作情境。畫面大概就是外部元件有一個按鈕,按下去會有一個對話框(內部元件)彈出來,對話框上有個按鈕,點擊後對話框就會關閉。 如果前端框架是 Vue 的話,一般我們會在外部元件定義一個布林值,預設為 false ,按下外部的按鈕後,布林值會變為 true。 開啟:在內部元件 modal 用 props 接收外部元件的布林值,綁上 v-if= props 接收到的布林值。這樣就可以由外部元件控制內部元件的開啟。 關閉:內元件 modal 可以由元件內部的按鈕關閉,按下按鈕後以 emit 傳送一個事件去觸發外部元件反轉布林值,達成元件的關閉。 App.vue(外部元件) <template> <button @click="isOpen = true">showModal</button> <!-- 外部元件中插入內部元件 modal --> <!-- props 口訣:先內後外 :open="isOpen"--> <!-- emit 口訣:先內後外 @close="isOpen = !isOpen"--> <Modal :open="isOpen" @close="isOpen = !isOpen"> <p> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quo molestiae consectetur blanditiis aspernatur velit autem labore amet </p> </Modal> </template> <script> import { ref } from "vue"; import Modal from "./components/ModalView.vue"; // import HelloWorldVue from "./components/HelloWorld.vue"; export default { components: { Modal }, setup() { // 由 isOpen 的 true 或 false 控制 modal 的開關 const isOpen = ref(false); return { isOpen, }; }, }; </script> <style> </style> /components/ModalView.vue(內部元件) <template> <transition name="fade"> <!-- 控制背景 --> <div class="vue-modal" v-if="open"> <transition name="drop-in"> <!-- 彈跳視窗本體 props 為 open,所以 v-if="open" --> <div class="vue-modal-inner" v-if="open"> <div class="vue-modal-content"> <slot /> <!-- @click="close" 觸發 emit 事件,傳送至外層切換 isOpen --> <button type="button" @click="close">close</button> </div> </div> </transition> </div> </transition> </template> <script> import { onMounted, onUnmounted } from "vue"; export default { props: { open: { type: Boolean, requires: true, }, }, // peops 這個參數一定要帶到,才能使用 {emit} setup(props, { emit }) { const close = () => { emit("close"); }; const handleKeyup = (event) => { close(); }; onMounted(() => document.addEventListener("keyup", handleKeyup)); onUnmounted(() => document.removeEventListener("keyup", handleKeyup)); return { close }; }, }; </script> <style scoped> *, ::before, ::after { margin: 0; padding: 0; box-sizing: border-box; } .vue-modal { position: fixed; top: 0; left: 0; width: 100%; height: 100%; overflow-x: hidden; overflow-y: auto; background-color: rgba(0, 0, 0, 0.04); z-index: 1; } .vue-modal-inner { max-width: 500px; margin: 2rem auto; } .vue-modal-content { position: relative; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.3); background-clip: padding-box; border-radius: 0.3rem; padding: 1rem; } .fade-enter-active, .fade-leave-active { transition: opacity 0.5s; } .fade-enter-from, .fade-leave-to { opacity: 0; } .drop-in-enter-active, .drop-in-leave-active { transition: all 0.3s easeout; } .drop-in-enter-from, .drop-in-leave-to { opacity: 0; transform: translateY(-50px); } </style> Vue3 #Vue, modal, props, emit 在 Composition API 中使用 props 與 emit 操控 modal https://popeye-ux.github.io/2023/01/27/modal-props-emit/ 作者 POPEYE 發布於 2023年1月27日 許可協議 在 Composition API 中使用 pinia 操控 modal 上一篇 hover 基本應用 下一篇 Please enable JavaScript to view the comments