开发者问题收集

这个 TypeError 是否与错误的 this.$emit 有关?

2017-06-08
241

我正在构建一个组件,该组件应该从父级获取对象数组,显示它们并允许删除某些对象(=子级向父级发送一个新数组)。

上一个答案 对于理解子级 -> 父级通信非常有用,但我现在陷入了一个我无法理解的错误:

Vue.component('search-box', {
  template: '#search-box-template',
  props: ['who'],
  methods: {
    deleteID: function(p) {
      var user = _.filter(this.who, function(w) {
        return w.id === p.id
      })
      this.$emit('delete-id', user)
    }
  }
})
var vm = new Vue({
  el: '#root',
  data: {
    who: [{
      "name": "john",
      "id": 1
    }, {
      "name": "mary",
      "id": 2
    }]
  }
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


<div id="root">
  Hello in parent
  <search-box v-bind:who="who" v-on:delete-id="who"></search-box>
  who is: {{who}}
</div>

<template id="search-box-template">
    <div>
        <ul>
            <li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
        </ul>
    </div>
</template>

运行此代码正确列出了用户,但当我尝试删除一个用户时,我在控制台中得到了

vue.js:1739 Uncaught TypeError: fns[i].apply is not a function
    at VueComponent.invoker (vue.js:1739)
    at VueComponent.Vue.$emit (vue.js:2210)
    at VueComponent.deleteID (search.html:31)
    at Proxy.boundFn (vue.js:170)
    at click (eval at makeFunction (vue.js:9323), <anonymous>:2:164)
    at HTMLButtonElement.invoker (vue.js:1743)
invoker @   vue.js:1739
Vue.$emit   @   vue.js:2210
deleteID    @   search.html:31
boundFn @   vue.js:170
click   @   VM9358:2
invoker @   vue.js:1743

这个错误是什么意思? $emit 正确吗?

2个回答

有两个问题:

  1. 您的 _.filter 返回一个数组,因此您不会发出用户,而是发出包含用户的数组。该过滤器也完全没有必要,因为 p 已经是您要过滤的用户对象。但该代码不是导致错误的原因。
  2. v-on:delete-id="who" 您将一个对象 ( who ) 传递给事件侦听器,但它需要一个函数。这就是引发错误的原因。

您的代码的工作版本如下所示:

Vue.component('search-box', {
  template: '#search-box-template',
  props: ['who'],
  methods: {
    deleteID: function(p) {
      this.$emit('delete-id', p)
    }
  }
})

var vm = new Vue({
  el: '#root',
  data: {
    who: [{
      "name": "john",
      "id": 1
    }, {
      "name": "mary",
      "id": 2
    }]
  },
  methods: {
    handleDelete(person) {
      const index = this.who.indexOf(person)
      this.who.splice(index, 1)
    }
  }
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


<div id="root">
  Hello in parent
  <search-box v-bind:who="who" v-on:delete-id="handleDelete"></search-box>
  who is: {{who}}
</div>

<template id="search-box-template">
    <div>
        <ul>
            <li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
        </ul>
    </div>
</template>
Linus Borg
2017-06-08

根据 Linus 的出色回答,以下是我更正后的代码,当删除用户时,它会发出一个数组。

Vue.component('search-box', {
  template: '#search-box-template',
  props: ['who'],
  methods: {
    deleteID: function(p) {
                var user = _.filter(this.who, function (w) {
                return w.id != p.id
            })
      this.$emit('delete-id', user)
    }
  }
})

var vm = new Vue({
  el: '#root',
  data: {
    who: [{
      "name": "john",
      "id": 1
    }, {
      "name": "mary",
      "id": 2
    }]
  },
  methods: {
    handleDelete(users) {
      this.who = users
    }
  }
})
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.3/vue.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>


<div id="root">
  Hello in parent
  <search-box v-bind:who="who" v-on:delete-id="handleDelete"></search-box>
  who is: {{who}}
</div>

<template id="search-box-template">
    <div>
        <ul>
            <li v-for="p in who">person: {{p.name}}, id: {{p.id}} <button v-on:click="deleteID(p)">delete</button></li>
        </ul>
    </div>
</template>
WoJ
2017-06-08