Как создать диалог подтверждения в Vue.js

Введение Диалог подтверждения - это шаблон пользовательского интерфейса, в котором пользователю будет предоставлен выбор: продолжить действие или отменить его. Он обычно используется с деструктивными или необратимыми действиями, чтобы убедиться, что пользователь действительно захочет продолжить. В этой статье мы реализуем многоразовый модульный диалог подтверждения на Vue.js. Создание многоразового всплывающего компонента Давайте начнем с создания многоразового базового компонента для любого типа всплывающих компонентов. Таким образом, нам не нужно г

Вступление

Диалог подтверждения - это шаблон пользовательского интерфейса, в котором пользователю будет предоставлен выбор: продолжить действие или отменить его. Он обычно используется с деструктивными или необратимыми действиями, чтобы убедиться, что пользователь действительно захочет продолжить.

В этой статье мы реализуем многоразовый модульный диалог подтверждения на Vue.js.

Создание многоразового всплывающего компонента

Начнем с создания многоразового базового компонента для любых всплывающих компонентов. Таким образом, нам не нужно повторно реализовывать механику всплывающих окон несколько раз. Позже это можно будет повторно использовать для создания чего угодно, от окна предупреждения до всплывающего окна информационного бюллетеня.

Начнем с шаблона:

 <!-- components/PopupModal.vue --> 
 
 <template> 
 <transition name="fade"> 
 <div class="popup-modal" v-if="isVisible"> 
 <div class="window"> 
 <slot></slot> 
 </div> 
 </div> 
 </transition> 
 </template> 

Обратите внимание, что мы добавили в шаблон <slot></slot> Этот тег позволяет нам вставлять любое содержимое в элемент PopupModal <slot></slot> . Чтобы узнать больше о том, как работают слоты, см. Руководство Vue по слотам .

Мы также добавили в шаблон тег <transition name="fade"> Мы будем использовать это в следующем разделе, чтобы анимировать эффект постепенного появления / исчезновения в диалоге.

Затем мы добавим функции событий data() , open() и close()

 <!-- components/PopupModal.vue --> 
 
 <script> 
 export default { 
 name: 'PopupModal', 
 
 data: () => ({ 
 isVisible: false, 
 }), 
 
 methods: { 
 open() { 
 this.isVisible = true 
 }, 
 
 close() { 
 this.isVisible = false 
 }, 
 }, 
 } 
 </script> 

И, наконец, добавим к нему немного стиля:

 <!-- components/PopupModal.vue --> 
 
 <style scoped> 
 /* css class for the transition */ 
 .fade-enter-active, 
 .fade-leave-active { 
 transition: opacity 0.3s; 
 } 
 .fade-enter, 
 .fade-leave-to { 
 opacity: 0; 
 } 
 
 .popup-modal { 
 background-color: rgba(0, 0, 0, 0.5); 
 position: fixed; 
 top: 0; 
 bottom: 0; 
 left: 0; 
 right: 0; 
 padding: 0.5rem; 
 display: flex; 
 align-items: center; 
 z-index: 1; 
 } 
 
 .window { 
 background: #fff; 
 border-radius: 5px; 
 box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); 
 max-width: 480px; 
 margin-left: auto; 
 margin-right: auto; 
 padding: 1rem; 
 } 
 </style> 

Подтверждение диалогового окна анимации

В теге шаблона вы увидите тег <transition name="fade"> . Это используется для анимации простых состояний входа / выхода. Все, что находится внутри этого тега, будет анимировано, если оно было добавлено или удалено из тега.

Мы используем условное v-if="isVisible" чтобы скрыть и показать всплывающее окно. Вы можете узнать больше об этом в руководстве Vue по переходам .

Чтобы указать, как контент перемещается, мы назвали нашу анимацию fade . Чтобы реализовать этот переход в CSS, мы добавим классы с префиксом name fade , соответствующие нашему атрибуту name тега <transition>

Все, что он делает, это анимирует непрозрачность при закрытии и открытии всплывающего окна:

 .fade-enter-active, 
 .fade-leave-active { 
 transition: opacity 0.3s; 
 } 
 .fade-enter, 
 .fade-leave-to { 
 opacity: 0; 
 } 

Наследование компонента Popup

Чтобы создать наш диалог подтверждения, мы унаследуем PopupModal по составу и настроим модальное окно многократного использования, чтобы оно стало диалоговым окном подтверждения.

Создадим новый файл components/ConfirmDialogue.vue и определим внутри него шаблон:

 <!-- components/ConfirmDialogue.vue --> 
 
 <template> 
 <popup-modal ref="popup"> 
 <h2 style="margin-top: 0">{{ title }}</h2> 
 <p>{{ message }}</p> 
 <div class="btns"> 
 <button class="cancel-btn" @click="_cancel">{{ cancelButton }}</button> 
 <span class="ok-btn" @click="_confirm">{{ okButton }}</span> 
 </div> 
 </popup-modal> 
 </template> 

Поскольку мы определили <slot></slot> в popup-modal компоненте, все, что мы помещаем между его тегами компонента (< popup-modal></popup-modal> ), будет отображаться между его тегами <slot> .

Мы также добавили ref="popup" к тегу popup-modal Установив этот атрибут, мы теперь можем получить доступ к popup-modal с помощью this.$refs.popup . Мы будем использовать эту ссылку для вызова open() и close() во всплывающем модальном окне.

Затем давайте реализуем методы из родительского компонента:

 <!-- components/ConfirmDialogue.vue --> 
 
 <script> 
 import PopupModal from './PopupModal.vue' 
 
 export default { 
 name: 'ConfirmDialogue', 
 
 components: { PopupModal }, 
 
 data: () => ({ 
 // Parameters that change depending on the type of dialogue 
 title: undefined, 
 message: undefined, // Main text content 
 okButton: undefined, // Text for confirm button; leave it empty because we don't know what we're using it for 
 cancelButton: 'Go Back', // text for cancel button 
 
 // Private variables 
 resolvePromise: undefined, 
 rejectPromise: undefined, 
 }), 
 
 methods: { 
 show(opts = {}) { 
 this.title = opts.title 
 this.message = opts.message 
 this.okButton = opts.okButton 
 if (opts.cancelButton) { 
 this.cancelButton = opts.cancelButton 
 } 
 // Once we set our config, we tell the popup modal to open 
 this.$refs.popup.open() 
 // Return promise so the caller can get results 
 return new Promise((resolve, reject) => { 
 this.resolvePromise = resolve 
 this.rejectPromise = reject 
 }) 
 }, 
 
 _confirm() { 
 this.$refs.popup.close() 
 this.resolvePromise(true) 
 }, 
 
 _cancel() { 
 this.$refs.popup.close() 
 this.resolvePromise(false) 
 // Or you can throw an error 
 // this.rejectPromise(new Error('User cancelled the dialogue')) 
 }, 
 }, 
 } 
 </script> 

Наконец, давайте добавим к нему немного стиля, чтобы он выглядел немного лучше:

 <!-- components/ConfirmDialogue.vue --> 
 
 <style scoped> 
 .btns { 
 display: flex; 
 flex-direction: row; 
 justify-content: space-between; 
 } 
 
 .ok-btn { 
 color: red; 
 text-decoration: underline; 
 line-height: 2.5rem; 
 cursor: pointer; 
 } 
 
 .cancel-btn { 
 padding: 0.5em 1em; 
 background-color: #d5eae7; 
 color: #35907f; 
 border: 2px solid #0ec5a4; 
 border-radius: 5px; 
 font-weight: bold; 
 font-size: 16px; 
 text-transform: uppercase; 
 cursor: pointer; 
 } 
 </style> 

Использование диалога подтверждения

Чтобы использовать диалог подтверждения, вам нужно включить только components/ConfirmDialogue.vue . Например, давайте создадим страницу с кнопкой «Удалить», которая проверяет, действительно ли вы хотите удалить другую страницу:

 <template> 
 <div> 
 <h1>Delete Page</h1> 
 <button class="delete-btn" @click="doDelete">Delete Page</button> 
 <confirm-dialogue ref="confirmDialogue"></confirm-dialogue> 
 </div> 
 </template> 
 
 <script> 
 import ConfirmDialogue from '../components/ConfirmDialogue.vue' 
 
 export default { 
 components: { ConfirmDialogue }, 
 methods: { 
 async doDelete() { 
 const ok = await this.$refs.confirmDialogue.show({ 
 title: 'Delete Page', 
 message: 'Are you sure you want to delete this page? It cannot be undone.', 
 okButton: 'Delete Forever', 
 }) 
 // If you throw an error, the method will terminate here unless you surround it wil try/catch 
 if (ok) { 
 alert('You have successfully delete this page.') 
 } else { 
 alert('You chose not to delete this page. Doing nothing now.') 
 } 
 }, 
 }, 
 } 
 </script> 
 
 <style scoped> 
 .delete-btn { 
 padding: 0.5em 1em; 
 background-color: #eccfc9; 
 color: #c5391a; 
 border: 2px solid #ea3f1b; 
 border-radius: 5px; 
 font-weight: bold; 
 font-size: 16px; 
 text-transform: uppercase; 
 cursor: pointer; 
 } 
 </style> 

Поскольку мы используем await в нашем методе, чтобы получить результат диалога подтверждения, нам нужно добавить async в определение нашего метода.

В качестве альтернативы вы можете предпочесть подход в стиле обещания:

 this.$refs.confirmDialogue.show({ 
 title: 'Delete Page', 
 message: 'Are you sure you want to delete this page? It cannot be undone.', 
 okButton: 'Delete Forever', 
 }).then((result) => { 
 if (ok) { 
 alert('You have successfully delete this page.') 
 } else { 
 alert('You chose not to delete this page. Doing nothing now.') 
 } 
 }) 

Чтобы понять, почему мы предложили выдавать ошибку, если пользователь отменяет диалог подтверждения, посмотрите, насколько плавным является следующий код:

 await this.$refs.confirmDialogue.show({ 
 title: 'Delete Page', 
 message: 'Are you sure you want to delete this page? It cannot be undone.', 
 okButton: 'Delete Forever', 
 }) 
 alert('Deleting this page.') 

Поскольку для отмены не требуется никаких действий, нет необходимости обрабатывать это состояние вообще. И если вы решите обработать запрос на отмену, просто оберните этот код с помощью try/catch .

Заключение

В этой статье мы определили многоразовый компонент модального всплывающего окна в Vue.js и унаследовали его для реализации диалогового окна подтверждения. Затем мы добавили к нему анимацию в эстетических целях и запустили несколько примеров того, как использовать компонент, чтобы запрашивать у пользователей ввод.

comments powered by Disqus