是否可以通过在其外部单击来关闭Vue组件?

时间:2019-03-22 19:20:32

标签: javascript vue.js

我正在寻找一种方法来关闭组件,使其在元素的单击位置超出范围。

我尝试了addEventListener。 这将关闭组件,但在关闭后将不会再次打开。

window.addEventListener('click', function(e){

if (document.getElementById('shopcartpreview').contains(e.target)){
console.log("Clicked in Box");


} else{
console.log("Clicked outside Box");
$('#shopcartpreview').hide();
 }
 })

有没有办法做到这一点?

<template>
    <div id="shopcartpreview"  v-if="carthover">
        <div class="cartitem" v-for="item in cartitems">
            <div class="cartitempic"><img class="productImg" width="80px" height="80px" v-bind:src="'assets/products/' + item.image"></div>
            <div class="cartitemdetails">
                <div class="cartitemname">{{item.name}}</div>
                <div class="cartitemqty">1 X </div>
                <div class="cartitemprice">€{{item.unit_price}}</div>
            </div>
            <div class="cartitemdelete">
                <img src="assets/images/icon-bin.png" width="15px" height="15px">
            </div>
        </div>

        <div class="carttotal">
            <div class="carttotaltext">TOTAL:</div>
            <div class="carttotalprice">€2,860.00</div>
        </div>
        <div class="cartcheckouttbn">PROCEED TO CHECKOUT</div>
        <div class="viewcart">VIEW CART</div>



    </div>    
</template>
<script>
    module.exports = {
        data: function () {
                return{ 
                    cartitems: 0,
                    carthover: false,
                }
            },
            created(){
            EventBus.$on('addToCart', (payload) =>{
                this.cartitems = payload
            }),
            EventBus.$on('mouseover', (carthover) =>{
            this.carthover = carthover
            })
        }
    }
</script>

3 个答案:

答案 0 :(得分:1)

Demo Fiddle:https://jsfiddle.net/bq8m4fhe/

创建clickoutside指令... Detect click outside element

module.exports = {
    data: function() {
        return {
            cartitems: 0,
            carthover: false
        };
    },
    directives: {
        clickoutside: {
            bind: function(el, binding, vnode) {
                el.clickOutsideEvent = function(event) {
                    // here I check that click was outside the el and his childrens
                    if (!(el == event.target || el.contains(event.target))) {
                        // and if it did, call method provided in attribute value
                        vnode.context[binding.expression](event);
                    }
                };
                document.body.addEventListener("click", el.clickOutsideEvent);
                document.body.addEventListener("touchstart", el.clickOutsideEvent);
            },
            unbind: function(el) {
                document.body.removeEventListener("click", el.clickOutsideEvent);
                document.body.removeEventListener("touchstart", el.clickOutsideEvent);
            },
            stopProp(event) {
                event.stopPropagation();
            }
        }
    },
    created() {
        EventBus.$on("addToCart", payload => {
            this.cartitems = payload;
        }),
        EventBus.$on("mouseover", carthover => {
            this.carthover = carthover;
        });
    }
};

像这样使用该指令。

<div id="shopcartpreview"  v-if="carthover" v-clickoutside="SHOPPING_CART_HIDE_FUNCTION">

答案 1 :(得分:0)

我在组件的末尾创建了一个div元素,就像这样:

<div v-if="isPopup" class="outside" v-on:click="away()"></div>

在CSS中指定.outside类的位置如下:

.outside {
  width: 100vw;
  height: 100vh;
  position: fixed;
  top: 0px;
  left: 0px;
}

away()是Vue实例中的一种方法,如下所示:

away() {
 this.isPopup = false;
}

容易,效果很好。

答案 2 :(得分:0)

首先,当您打开一个组件(例如,下拉菜单)时,应将窗口对象绑定到一个click事件,该事件用于关闭下拉菜单。在此,停止此事件的传播非常重要。

关于事件传播,bubbling and capturing

然后,当您关闭下拉菜单时,应使用removeEventListener删除事件监听器。

如下所示的下拉菜单

<li class="user-profile nav-item">
  <div class="dropdown" @click="toggleDropdown">
    <img src="@/assets/user.jpg" alt="user-alias">
    <ul class="dropdown-menu" v-if="showDropdown">
      <li class="dropdown-menu-item"><a>Dashbord</a></li>
      <li class="dropdown-menu-item"><a>Profile</a></li>
      <li class="dropdown-menu-item"><a>Settings</a></li>
      <li class="dropdown-menu-item"><a>Logout</a></li>
    </ul>
  </div>
</li>

Vue组件:

export default {
  data () {
    return {
      showDropdown: false,
    }
  },
  methods: {
    toggleDropdown (e) {
      e.stopPropagation() // this will stop propagation of this event to upper level
      this.showDropdown = !this.showDropdown
      if (this.showDropdown) {
        window.addEventListener('click', () => {
          this.showDropdown = false
        })
      } else {
        window.removeEventListener('click', () => {
          this.showDropdown = false
        })
      }
    }
  }
}