如何在外部点击时关闭自定义弹出窗口?

时间:2017-09-30 04:19:55

标签: javascript jquery html css vuejs2

我正在开发Cordova应用程序。为此,我使用Vue.js和jQuery进行绑定和脚本,我正在自己开发UI。我可以为大多数UI做页面过渡和动画,如单选按钮和复选框等。但我无法开发自定义弹出框。我试过以下代码。

Vue.directive('popover', {
    bind: function(el, bindings, vnode) {
        $(el).click(function() {
            var pageEl = $(this).closest('.ui-page');
            pageEl.find('.drawer').toggleClass('active');

            $(el).closest('.ui-page').click(function(e) {
//                $('.drawer', this).removeClass('active');
            });
        });
    }
})

var pageInstace = new Vue({
    el: '#popover-page',
    data: {
        options: [1, 2, 3, 4, 5]
    }
})
html,
body {
    position: relative;
    width: 100%;
    height: 100%;
}

body {
    font-family: 'Open Sans';
    font-size: 16px;
    margin: 0;
    overflow: hidden;
}

* {
    box-sizing: border-box;
}

*, *:active, *:hover, *:focus {
	outline: 0;
}

button {
    padding: 0;
}

img {
    max-width: 100%;
}

.ui-page,
.header,
.scroll-content {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
    overflow: hidden;
}

.ui-page {
    height: 100%;
    background-color: #fff;
}

.page-content {
    position: relative;
    height: 100%;
    overflow-y: auto;
    z-index: 1;
}

.header {
    height: 54px;
    box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12), 0 1px 8px 0 rgba(0, 0, 0, 0.2);
    background-color: #607D8B;
    color: #fff;
    display: flex;
    align-items: center;
    padding-left: 16px;
    padding-right: 16px;
    z-index: 1;
}

.scroll-content {
    bottom: 0;
    overflow: auto;
}

.scroll-content.has-header {
    top: 54px;
}

.header button {
    color: #fff;
    height: 100%;
}

.header .header-title {
    margin: 0 22px;
    font-size: 18px;
    font-weight: 600;
    width: 100%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

.header .buttons {
    position: relative;
    display: flex;
}

.header .buttons button {
    padding: 4px 8px;
}

.header .buttons button:last-child {
    padding: 4px 0 4px 8px;
}

.btn {
    position: relative;
    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
    border: none;
    padding: 8px 16px;
    font-size: 16px;
    border-radius: 4px;
    font-family: unset;
    overflow: hidden;
}

.btn-clear {
    background-color: transparent;
    border: none;
}

.item {
    position: relative;
    display: flex;
    overflow: hidden;
    border-bottom: 1px solid #bdbdbd;
}

.drawer {
    position: absolute;
    background-color: #fff;
    z-index: 4;
    top: 60px;
    right: 4px;
    border-radius: 2px;
    box-shadow: 0px 2px 8px 2px rgba(0, 0, 0, 0.4);
    transform: scale(0, 0);
    transform-origin: top right;
    transition: transform ease 0.3s;
    min-width: 180px;
}

.drawer.active {
    transform: scale(1, 1);
}

.drawer .drawer-content {
    position: relative;
    padding: 4px 0;
}

.drawer .drawer-content:after {
    content: '';
    position: absolute;
    border: 8px solid transparent;
    border-bottom-color: #fff;
    top: -14px;
    right: 22px;
}

.drawer .item {
    padding: 12px 16px;
    font-size: 14px;
}

.drawer .item:last-child {
    border-bottom: none;
}
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>

<div class="ui-page" id="popover-page">
    <div class="page-content">
        <div class="header">
            <div class="header-title">
                Page Title
            </div>
            <button class="btn-clear" v-popover>Popover</button>
        </div>
        <div class="drawer">
            <div class="drawer-content">
                <div class="item" v-for="option in options">{{ option }}</div>
            </div>
        </div>
        <div class="scroll-content has-header">
            <div class="page-content">
                <p>Some Content</p>
            </div>
        </div>
    </div>
</div>

这适用于在按钮点击时切换弹出窗口。我试了这么多。但是当我点击popover外面时,我无法隐藏弹出窗口。

如何在点击一边时隐藏popover?

2 个答案:

答案 0 :(得分:1)

请试试这个。我添加了jQuery

$('body').click(function(e) {
  if (!$(e.target).closest('.drawer').length){
    $(".drawer").removeClass("active");
  }
});

&#13;
&#13;
$('body').click(function(e) {
    if (!$(e.target).closest('.drawer').length){
        $(".drawer").removeClass("active");
    }
});

Vue.directive('popover', {
    bind: function(el, bindings, vnode) {
        $(el).click(function(e) {
            e.stopPropagation();
            var pageEl = $(this).closest('.ui-page');
            pageEl.find('.drawer').toggleClass('active');

            $(el).closest('.ui-page').click(function(e) {                  
//                $('.drawer', this).removeClass('active');
            });
        });
    }
})

var pageInstace = new Vue({
    el: '#popover-page',
    data: {
        options: [1, 2, 3, 4, 5]
    }
})
&#13;
html,
body {
    position: relative;
    width: 100%;
    height: 100%;
}

body {
    font-family: 'Open Sans';
    font-size: 16px;
    margin: 0;
    overflow: hidden;
}

* {
    box-sizing: border-box;
}

*, *:active, *:hover, *:focus {
	outline: 0;
}

button {
    padding: 0;
}

img {
    max-width: 100%;
}

.ui-page,
.header,
.scroll-content {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
    overflow: hidden;
}

.ui-page {
    height: 100%;
    background-color: #fff;
}

.page-content {
    position: relative;
    height: 100%;
    overflow-y: auto;
    z-index: 1;
}

.header {
    height: 54px;
    box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12), 0 1px 8px 0 rgba(0, 0, 0, 0.2);
    background-color: #607D8B;
    color: #fff;
    display: flex;
    align-items: center;
    padding-left: 16px;
    padding-right: 16px;
    z-index: 1;
}

.scroll-content {
    bottom: 0;
    overflow: auto;
}

.scroll-content.has-header {
    top: 54px;
}

.header button {
    color: #fff;
    height: 100%;
}

.header .header-title {
    margin: 0 22px;
    font-size: 18px;
    font-weight: 600;
    width: 100%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

.header .buttons {
    position: relative;
    display: flex;
}

.header .buttons button {
    padding: 4px 8px;
}

.header .buttons button:last-child {
    padding: 4px 0 4px 8px;
}

.btn {
    position: relative;
    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
    border: none;
    padding: 8px 16px;
    font-size: 16px;
    border-radius: 4px;
    font-family: unset;
    overflow: hidden;
}

.btn-clear {
    background-color: transparent;
    border: none;
}

.item {
    position: relative;
    display: flex;
    overflow: hidden;
    border-bottom: 1px solid #bdbdbd;
}

.drawer {
    position: absolute;
    background-color: #fff;
    z-index: 4;
    top: 60px;
    right: 4px;
    border-radius: 2px;
    box-shadow: 0px 2px 8px 2px rgba(0, 0, 0, 0.4);
    transform: scale(0, 0);
    transform-origin: top right;
    transition: transform ease 0.3s;
    min-width: 180px;
}

.drawer.active {
    transform: scale(1, 1);
}

.drawer .drawer-content {
    position: relative;
    padding: 4px 0;
}

.drawer .drawer-content:after {
    content: '';
    position: absolute;
    border: 8px solid transparent;
    border-bottom-color: #fff;
    top: -14px;
    right: 22px;
}

.drawer .item {
    padding: 12px 16px;
    font-size: 14px;
}

.drawer .item:last-child {
    border-bottom: none;
}
&#13;
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>

<div class="ui-page" id="popover-page">
    <div class="page-content">
        <div class="header">
            <div class="header-title">
                Page Title
            </div>
            <button class="btn-clear" v-popover>Popover</button>
        </div>
        <div class="drawer">
            <div class="drawer-content">
                <div class="item" v-for="option in options">{{ option }}</div>
            </div>
        </div>
        <div class="scroll-content has-header">
            <div class="page-content">
                <p>Some Content</p>
            </div>
        </div>
    </div>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

&#13;
&#13;
Vue.directive('popover', {
    bind: function(el, bindings, vnode) {
        
        $(el).click(function() { 
            $(el).closest('.ui-page').find('.drawer').toggleClass('active');           
        });
        $('body').on('click', $(el).closest('.ui-page'), function(e) {
            var $drawer = $(el).closest('.ui-page').find('.drawer');
            var $target = $(e.target);

            if ($target.closest($(el)).length <= 0 
              && $drawer.hasClass('active') 
              && $target.closest('.drawer').length <= 0) {
                $drawer.removeClass('active');
            }
        });
    }
})

var pageInstace = new Vue({
    el: '#popover-page',
    data: {
        options: [1, 2, 3, 4, 5]
    }
})
&#13;
html,
body {
    position: relative;
    width: 100%;
    height: 100%;
}

body {
    font-family: 'Open Sans';
    font-size: 16px;
    margin: 0;
    overflow: hidden;
}

* {
    box-sizing: border-box;
}

*, *:active, *:hover, *:focus {
	outline: 0;
}

button {
    padding: 0;
}

img {
    max-width: 100%;
}

.ui-page,
.header,
.scroll-content {
    position: absolute;
    width: 100%;
    top: 0;
    left: 0;
    overflow: hidden;
}

.ui-page {
    height: 100%;
    background-color: #fff;
}

.page-content {
    position: relative;
    height: 100%;
    overflow-y: auto;
    z-index: 1;
}

.header {
    height: 54px;
    box-shadow: 0 3px 4px 0 rgba(0, 0, 0, 0.14), 0 3px 3px -2px rgba(0, 0, 0, 0.12), 0 1px 8px 0 rgba(0, 0, 0, 0.2);
    background-color: #607D8B;
    color: #fff;
    display: flex;
    align-items: center;
    padding-left: 16px;
    padding-right: 16px;
    z-index: 1;
}

.scroll-content {
    bottom: 0;
    overflow: auto;
}

.scroll-content.has-header {
    top: 54px;
}

.header button {
    color: #fff;
    height: 100%;
}

.header .header-title {
    margin: 0 22px;
    font-size: 18px;
    font-weight: 600;
    width: 100%;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
}

.header .buttons {
    position: relative;
    display: flex;
}

.header .buttons button {
    padding: 4px 8px;
}

.header .buttons button:last-child {
    padding: 4px 0 4px 8px;
}

.btn {
    position: relative;
    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.26);
    border: none;
    padding: 8px 16px;
    font-size: 16px;
    border-radius: 4px;
    font-family: unset;
    overflow: hidden;
}

.btn-clear {
    background-color: transparent;
    border: none;
}

.item {
    position: relative;
    display: flex;
    overflow: hidden;
    border-bottom: 1px solid #bdbdbd;
}

.drawer {
    position: absolute;
    background-color: #fff;
    z-index: 4;
    top: 60px;
    right: 4px;
    border-radius: 2px;
    box-shadow: 0px 2px 8px 2px rgba(0, 0, 0, 0.4);
    transform: scale(0, 0);
    transform-origin: top right;
    transition: transform ease 0.3s;
    min-width: 180px;
}

.drawer.active {
    transform: scale(1, 1);
}

.drawer .drawer-content {
    position: relative;
    padding: 4px 0;
}

.drawer .drawer-content:after {
    content: '';
    position: absolute;
    border: 8px solid transparent;
    border-bottom-color: #fff;
    top: -14px;
    right: 22px;
}

.drawer .item {
    padding: 12px 16px;
    font-size: 14px;
}

.drawer .item:last-child {
    border-bottom: none;
}
&#13;
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>

<div class="ui-page" id="popover-page">
    <div class="page-content">
        <div class="header">
            <div class="header-title">
                Page Title
            </div>
            <button class="btn-clear" v-popover>Popover</button>
        </div>
        <div class="drawer">
            <div class="drawer-content">
                <div class="item" v-for="option in options">{{ option }}</div>
            </div>
        </div>
        <div class="scroll-content has-header">
            <div class="page-content">
                <p>Some Content</p>
            </div>
        </div>
    </div>
</div>
&#13;
&#13;
&#13;