vuejs2 - VueJs 2自定义指令在外部单击时关闭不起作用

标签 vuejs2

我正在开发一个 vuejs 组件,如果您在单击组合框后单击组合框外部,它应该会关闭。

我的问题是自定义指令不起作用,程序编译但在浏览器中出现此错误:

[Vue warn]: Error in directive click-outside bind hook: "TypeError: Cannot set property 'event' of undefined"

这是我的组件的代码:

<template>
  <div class="form-group" v-click-outside="hide">
  <label v-if="label" for="combobox" class="control-label" v-tack>{{ label }}:</label>
    <input id="combobox"
    class="form-control combo-box-control"
    v-on:keyup="filter(searchText,options)"
    v-model="searchText"
    :placeholder="placeholder"
    v-on:click="showAllOptions()" :disabled="isDisabled">
        <template v-if="showAutocomplete">
        <div class="combobox-list">
            <p class="combobox-options" :key="item.id" v-for="item in listFiltered" v-on:click="optionSelected(item)">{{item.text}}</p>
        </div>
        </template>
  </div>
</template>
<script>
export default {
  data () {
    return {
      listFiltered: [],
      searchText: '',
      showAutocomplete: false
    }
  },
  props: {
    name: { type: String, required: true },
    options: Array,
    label: String,
    isDisabled: { type: Boolean, default: false },
    selectedOption: Object,
    placeholder: String
  },
  methods: {
    filter (word, array) {
      if (word === undefined) {
        this.showAutocomplete = false
        this.listFiltered = []
        return
      }
      this.showAutocomplete = true
      this.listFiltered = array.filter(function (item) {
        return item.text.toLowerCase().includes(word.toLowerCase())
      })
    },
    optionSelected (item) {
      this.searchText = item.text
      this.showAutocomplete = false
      if (item !== undefined) {
        this.$emit('change', { name: this.name, item: item })
      }
    },
    showAllOptions () {
      this.listFiltered = this.options
      this.showAutocomplete = !this.showAutocomplete
    },
    hide () {
      this.showAutocomplete = false
    }
  }
}
</script>
<style>
.form-group{
    position:relative;
}
.form-group input{
    width:100%;
}

input.combo-box-control:active{
  border-style: solid;
  border-width: 1px 1px 0 1px;
  border-radius: 5px 5px 0px 0px;
  border-color: #96c8da;
}

.form-control.combo-box-control:focus{
  border-color: #96c8da;
}

.combobox-list{
    position:relative;
    height:154px;
    width:100%;
    background-color:white;
    overflow-y:auto;
    text-align:justify;
    z-index: 5;
    border-style: solid;
    border-color: #96c8da;
    border-width: 0 1px 1px 1px;
    border-radius: 0px 0px 5px 5px;
    top: -3px;
}

.combobox-options{
    padding:6px 0;
    margin:0;
}
.combobox-options:hover{
    background-color:#d9d9d9;
}
</style>

和 main.js:

Vue.directive('click-outside', {
  bind: function (el, binding, vnode) {
    this.event = function (event) {
      if (!(el === event.target || el.contains(event.target))) {
        vnode.context[binding.expression](event)
      }
    }
    document.body.addEventListener('click', this.event)
  },
  unbind: function (el) {
    document.body.removeEventListener('click', this.event)
  }
})

问题出在 this.event = function (event) { 行,因为错误显示 Cannot set property 'event' of undefined,所以这是未定义的。 不确定如何在指令中定义它。

我正在使用此示例使其与我的自定义组件一起工作:https://jsfiddle.net/Linusborg/yzm8t8jq/ 我错过了什么吗? 更新:原来示例中的代码来自 vuejs 1.x,尽管我在 vuejs 2.1 中找到了一个类似的示例 https://jsfiddle.net/y0rpfecd/ , 仍然得到同样的错误。

最佳答案

您可能已经找到了答案。希望有人觉得它有用。

我最近在我的副项目中测试了 click-outside 指令。 只需在指令代码中将 this.event 替换为 window.event 即可。而且效果很好!!

指令.js

import Vue from 'vue';

Vue.directive('click-outside', {
    bind: function (el, binding, vnode) {
        window.event = function (event) {
            if (!(el == event.target || el.contains(event.target))) {
                vnode.context[binding.expression](event);
            }
        };
        document.body.addEventListener('click', window.event)
    },
    unbind: function (el) {
        document.body.removeEventListener('click', window.event)
    },
});

要在组件中使用:只需导入指令。

<template>
  <div class="form-group" v-click-outside="hide">
  <label v-if="label" for="combobox" class="control-label" v-tack>{{ label }}:</label>
    <input id="combobox"
    class="form-control combo-box-control"
    v-on:keyup="filter(searchText,options)"
    v-model="searchText"
    :placeholder="placeholder"
    v-on:click="showAllOptions()" :disabled="isDisabled">
        <template v-if="showAutocomplete">
        <div class="combobox-list">
            <p class="combobox-options" :key="item.id" v-for="item in listFiltered" v-on:click="optionSelected(item)">{{item.text}}</p>
        </div>
        </template>
  </div>
</template>
<script>
import clickOutside from '../directive';
export default {
  data () {
    return {
      listFiltered: [],
      searchText: '',
      showAutocomplete: false
    }
  },
  props: {
    name: { type: String, required: true },
    options: Array,
    label: String,
    isDisabled: { type: Boolean, default: false },
    selectedOption: Object,
    placeholder: String
  },
  methods: {
    filter (word, array) {
      if (word === undefined) {
        this.showAutocomplete = false
        this.listFiltered = []
        return
      }
      this.showAutocomplete = true
      this.listFiltered = array.filter(function (item) {
        return item.text.toLowerCase().includes(word.toLowerCase())
      })
    },
    optionSelected (item) {
      this.searchText = item.text
      this.showAutocomplete = false
      if (item !== undefined) {
        this.$emit('change', { name: this.name, item: item })
      }
    },
    showAllOptions () {
      this.listFiltered = this.options
      this.showAutocomplete = !this.showAutocomplete
    },
    hide () {
      this.showAutocomplete = false
    }
  }
}
</script>
<style>
.form-group{
    position:relative;
}
.form-group input{
    width:100%;
}

input.combo-box-control:active{
  border-style: solid;
  border-width: 1px 1px 0 1px;
  border-radius: 5px 5px 0px 0px;
  border-color: #96c8da;
}

.form-control.combo-box-control:focus{
  border-color: #96c8da;
}

.combobox-list{
    position:relative;
    height:154px;
    width:100%;
    background-color:white;
    overflow-y:auto;
    text-align:justify;
    z-index: 5;
    border-style: solid;
    border-color: #96c8da;
    border-width: 0 1px 1px 1px;
    border-radius: 0px 0px 5px 5px;
    top: -3px;
}

.combobox-options{
    padding:6px 0;
    margin:0;
}
.combobox-options:hover{
    background-color:#d9d9d9;
}
</style>

关于vuejs2 - VueJs 2自定义指令在外部单击时关闭不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53013471/

相关文章:

javascript - VueJS 路由器 : $route is not defined

javascript - vue dev工具中的警告

vue.js - VueX Getter 从数组中过滤唯一 id

javascript - 将来自 background.js 的数据存储到 vuex 存储中

node.js - 构建 vue cli 后如何运行生产站点

vue.js - Atom 的 VueJS 设置

javascript - 为什么 v-for 只能工作一瞬间?

Vue.js 不显示像 {{ post.title }} 这样的括号

javascript - 使用 vue init 创建的应用程序抛出错误

javascript - vuejs 将多个输入值分配给 json 对象值