Vue.js — Почему @click срабатывает только один раз?

Всем привет! Люди подскажите пожалуйста. Делаю модальные окна через vue. Значит есть такой html код:

$html ='<div id="app-top">';
         $html .= '<a href="#" @click="zoomModal = true" >Вход</a>';    
                $html .='<modal title="Авторизация" :show.sync="zoomModal" effect="zoom" width="400">
                            <div slot="modal-body" class="modal-body">';
                                $html .= LoginFormWidget::widget([]);
                            $html .='</div>
                        </modal>';            
$html .='</div>';


LoginFormWidget - это виджет формы авторизации, там просто вставляется форма Activeform (yii2)

и соответственно сам js:

// modal component
    Vue.component('modal', {
        template: `              
            <div role="dialog" v-bind:class="{ 'modal':true, 'fade':effect === 'fade', 'zoom':effect === 'zoom' }">
                <div v-bind:class="{'modal-dialog':true,'modal-lg':large,'modal-sm':small}" role="document" v-bind:style="{width: optionalWidth}">
                    <div class="modal-content">
                        <slot name="modal-header">
                            <div class="modal-header">
                                <button type="button" class="close" @click="close"><span>&times;</span></button>
                                <h4 class="modal-title">
                                    <slot name="title">
                                        {{title}}
                                    </slot>
                                </h4>
                            </div>
                        </slot>
                        <slot name="modal-body">
                            <div class="modal-body"></div>
                        </slot>
                        <slot name="modal-footer">
                            <div class="modal-footer">
                                <button type="button" class="btn btn-default" @click="close">{{ cancelText }}</button>
                                <button type="button" class="btn btn-primary" @click="callback">{{ okText }}</button>
                            </div>
                        </slot>
                    </div>
                </div>
            </div>
        `,
        /*data: function data() {
            return {
                zoomModal: false              
            };
          },*/ 
        props: {
            effect: {
                type: String,
                required: true
            },
            large: {
                type: Boolean,                
                default: false
            },
            small: {
                type: Boolean,                
                default: false
            },              
            title: {
                type: String,
                default: ''
            },
            show: {
                required: true,
                type: Boolean,                
                twoWay: false
            },
            cancelText: {
                type: String,
                default: 'Закрыть'
            },
            okText: {
                type: String,
	            default: 'Save changes'
            },
            callback: {
                type: Function,
                default: function _default() {}
            },  
            width: {
                default: null
            },  
            backdrop: {
                type: Boolean,                
                default: true
            },     
        },
        computed: {
            optionalWidth: function optionalWidth() {
                if (this.width === null) {
                    return null;
                } else if (jQuery.isNumeric(this.width)) {
                    return this.width + 'px';
                }
                return this.width;
            }
        },
        watch: {
            show: function show(val) {                
                var _this = this;
                var el = this.$el;                
                var body = document.body;  
                              
                if(val) {
                    jQuery(el).find('.modal-content').focus();                    
                    jQuery(el).show();  
                    setTimeout(function(){
                        return jQuery(el).addClass("in");
                    },100); 
                    
                    jQuery(body).addClass("modal-open");
                    
                    if (this.backdrop) {
                        jQuery(el).on('click', function (e) {
                            if (e.target === el) {                                
                                _this.show = false;
                            }
                        });
                    }                    
                } else {
                    jQuery(body).removeClass("modal-open");
                    jQuery(el).removeClass('in').on('transitionend', function () {
                        jQuery(el).off('click transitionend');                        
                        jQuery(el).hide();
                    });      
                    console.log(this);                  
                }    
            
            }
	      
        }, 
        methods: {
            close: function close() {                
                this.show = false; 
            }            
        }  
    });

    new Vue({
        el: '#app-top',
        data: {            
            signupShowModal: false,
            zoomModal: false            
        },                
        methods: {            
            getLoginForm() {    
                //var self = this;                   
                //this.zoomModal = true;
            },
            getSignupForm() {                  
                var self = this;
                self.signupShowModal = true;        
            },            
            sendFrom() {                
                this.zoomModal = false;    
            }                             
             
        }        
    });


Всё отлично работает. При клике на ссылку "Вход" открывается модальное окно. Далее если нажать на кнопку "Закрыть" к которой присвоен метод (@click="close"), то модальное окно закрывается, но потом при повторном клике снова на Вход - модальное окно не открывается. То есть клик срабатывает только один раз.

Я решил в форме LoginFormWidget добавить ссылку и присвоить её метод @click="sendFrom" . В самом методе я прописал закрытие формы:

sendFrom() {                
                this.zoomModal = false;    
            }


Тоесть при закрытии модального окна нажимать не на метод Close, а на метод sendFrom. В таком случае модальное окно закрывается и снова открывается. Но почему при закрытии через метод Close - окно потом не открывается?!?!
  • Вопрос задан
  • 1351 просмотр
Решения вопроса 2
0xD34F
@0xD34F Куратор тега Vue.js
почему при закрытии через метод Close - окно потом не открывается?!?!

Открывается. Если использовать vue версии 1. Во второй, да - облом. У вас какая? - почему-то мне кажется, что вы об этом даже не задумывались. Ну, то есть - раз не работает как надо, значит вторая, но если вторая то... Какого хрена? - вы пытаетесь менять параметр компонента:

this.show = false;

указываете вырезанный twoWay:

show: {
  required: true,
  type: Boolean,                
  twoWay: false
}

Почему не происходит повторное открытие - потому что вы внутри компонента меняете значение параметра, но снаружи оно не изменяется. То есть, с точки зрения родительского компонента, модальное окно так и осталось открытым. И когда вы повторно пытаетесь его открыть, свойство, отвечающее за состояние окна, не меняет своего значения, vue не видит никаких изменений, и, соответственно, ничего не делает.

В общем - разберитесь с используемой версией vue. И документацию почитайте - корень вашей проблемы в том, что вы пытаетесь использовать инструмент непредусмотренным способом.

UPD. В первую очередь вам следует переписать работу с параметром show - вместо присваивания значения напрямую, генерировать событие, на которое надо будет подписаться в родительском компоненте, и уже там изменять значение переменной, отвечающей за видимость окна (zoomModal, кажется). С чем конкретно стоит ознакомиться для понимания проблемы - раз, два.
Ответ написан
rifer
@rifer Автор вопроса
Если кому интересно, то решение было такое:

в методе close вместо

this.show = false;

написать:

this.$emit('update:show', false)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Мне кажется что идет конфликт с jquery и vue P.S лень анализировать код

Если хочешь и bootsrap и vue используй вот это
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы