Vue v-on:click在组件上不起作用

2020/10/18 05:21 · javascript ·  · 0评论

我正在尝试在组件内部使用on click指令,但它似乎不起作用。当我单击该组件时,应该在控制台中单击“测试”,什么也没有发生。我在控制台中看不到任何错误,所以我不知道我在做什么错。

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>vuetest</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

应用程序

<template>
  <div id="app">
    <test v-on:click="testFunction"></test>
  </div>
</template>

<script>
import Test from './components/Test'

export default {
  name: 'app',
  methods: {
    testFunction: function (event) {
      console.log('test clicked')
    }
  },
  components: {
    Test
  }
}
</script>

Test.vue(组件)

<template>
  <div>
    click here
  </div>
</template>

<script>
export default {
  name: 'test',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

如果要在组件的根元素上侦听本地事件,则必须使用.native修饰符用于v-on,如下所示:

<template>
  <div id="app">
    <test v-on:click.native="testFunction"></test>
  </div>
</template>

或简而言之,如评论中所建议,您也可以执行以下操作:

<template>
  <div id="app">
    <test @click.native="testFunction"></test>
  </div>
</template>

我认为该$emit功能可以更好地满足您的要求。它使您的组件与Vue实例保持隔离,以便可以在许多情况下重用。

// Child component
<template>
  <div id="app">
    <test @click="$emit('test-click')"></test>
  </div>
</template>

在HTML中使用

// Parent component
<test @test-click="testFunction">

这是@Neps的答案,但有详细信息。


注意如果您不想修改组件或无法访问组件,则@Saurabh的答案更合适。


为什么@click不能正常工作?

组件很复杂。一个组件可以是一个小的按钮包装盒,另一个组件可以是一个内部包含一堆逻辑的整个表。Vue不知道绑定v-model或使用时的确切期望,v-on因此所有这些都应由组件的创建者处理。

如何处理点击事件

根据Vue docs$emit将事件传递给父对象。来自文档的示例:

主文件

<blog-post
  @enlarge-text="onEnlargeText"
/>

零件

<button @click="$emit('enlarge-text')">
  Enlarge text
</button>

@v-on 简写

组件处理本机click事件并发出父级事件@enlarge-text="..."

enlarge-text可以替换为click以使其看起来像我们正在处理本地点击事件:

<blog-post
  @click="onEnlargeText"
></blog-post>
<button @click="$emit('click')">
  Enlarge text
</button>

但这还不是全部。$emit允许通过事件传递特定值。如果是native click,则值为MouseEvent(与Vue无关的JS事件)。

Vue将该事件存储在$event变量中。因此,最好$event与事件一起发出以创建本机事件用法的印象:

<button v-on:click="$emit('click', $event)">
  Enlarge text
</button>

有点冗长,但这是我的方法:

@click="$emit('click', $event)"

更新: @sparkyspider添加的示例

<div-container @click="doSomething"></div-container>

div-container组件中...

<template>
  <div @click="$emit('click', $event);">The inner div</div>
</template>

正如Chris Fritz(Vue.js核心团队Emeriti)在VueCONF US 2019提到的那样

如果我们让Kia输入.native,然后基本输入的根元素突然从输入更改为标签,则此组件损坏了,这并不明显,实际上,除非您进行了很好的测试,否则您可能不会立即抓住它。通过避免使用目前我认为反模式将在Vue 3中删除.native修饰符您可以明确定义父级可能关心添加到哪些元素侦听器...

与Vue 2

使用$listeners

因此,如果您正在使用Vue 2,则解决此问题的更好选择是使用完全透明的包装器逻辑。为此,Vue提供了一个$listeners属性,其中包含在组件上使用的侦听器的对象。例如:

{
  focus: function (event) { /* ... */ }
  input: function (value) { /* ... */ },
}

然后我们只需要像这样添加v-on="$listeners"test组件:

Test.vue(子组件)

<template>
  <div v-on="$listeners">
    click here
  </div>
</template>

现在,该<test>组件是一个完全透明的包装器,这意味着它可以像普通<div>元素一样完全使用:所有侦听器都可以工作,而无需使用.native修饰符。

演示:

Vue.component('test', {
  template: `
    <div class="child" v-on="$listeners">
      Click here
    </div>`
})

new Vue({
  el: "#myApp",
  data: {},
  methods: {
    testFunction: function(event) {
      console.log('test clicked')
    }
  }
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <test @click="testFunction"></test>
</div>

使用$emit方法:

我们也可以$emit为此使用方法,这有助于我们侦听父组件中的子组件事件。为此,我们首先需要从子组件发出一个自定义事件,例如:

Test.vue(子组件)

<test @click="$emit('my-event')"></test>

重要提示:始终使用kebab-case作为事件名称。有关更多信息和演示,请查看以下答案:VueJS将计算值从component传递给parent

现在,我们只需要在父组件中监听此发出的自定义事件,例如:

应用程序

<test @my-event="testFunction"></test>

因此,基本上将代替v-on:click或速记,@click我们将仅使用v-on:my-event@my-event

演示:

Vue.component('test', {
  template: `
    <div class="child" @click="$emit('my-event')">
      Click here
    </div>`
})

new Vue({
  el: "#myApp",
  data: {},
  methods: {
    testFunction: function(event) {
      console.log('test clicked')
    }
  }
})
div.child{border:5px dotted orange; padding:20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <test @my-event="testFunction"></test>
</div>

与Vue 3

使用v-bind="$attrs"

Vue 3将在许多方面使我们的生活变得更加轻松。其中一个示例是,它将帮助我们仅通过使用很少的配置来创建一个更简单的透明包装器v-bind="$attrs"通过在子组件上使用它,不仅我们的侦听器将直接在父组件上工作,而且其他任何属性也将像正常情况<div>一样工作

因此,关于这个问题,我们将不需要更新Vue 3中的任何内容,并且您的代码仍然可以正常工作,就像<div>这里的root元素一样,它将自动侦听所有子事件。

演示#1:

const { createApp } = Vue;

const Test = {
  template: `
    <div class="child">
      Click here
    </div>`
};

const App = {
  components: { Test },
  setup() {
    const testFunction = event => {
      console.log("test clicked");
    };
    return { testFunction };
  }
};

createApp(App).mount("#myApp");
div.child{border:5px dotted orange; padding:20px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
  <test v-on:click="testFunction"></test>
</div>

但是对于带有嵌套元素的复杂组件,我们需要将属性和事件应用于main<input />而不是parent标签,我们可以简单地使用v-bind="$attrs"

演示2:

const { createApp } = Vue;

const BaseInput = {
  props: ['label', 'value'],
  template: `
    <label>
      {{ label }}
      <input v-bind="$attrs">
    </label>`
};

const App = {
  components: { BaseInput },
  setup() {
    const search = event => {
      console.clear();
      console.log("Searching...", event.target.value);
    };
    return { search };
  }
};

createApp(App).mount("#myApp");
input{padding:8px;}
<script src="//unpkg.com/vue@next"></script>
<div id="myApp">
  <base-input 
    label="Search: "
    placeholder="Search"
    @keyup="search">
  </base-input><br/>
</div>

无法从父元素直接访问组件的本地事件。相反,您应该尝试v-on:click.native="testFunction",或者也可以从Testcomponent发出事件v-on:click="$emit('click')"

文档中

由于JavaScript的限制,Vue无法检测到对数组的以下更改:

  1. 直接使用索引设置项目时,例如vm.items [indexOfItem] = newValue
  2. 修改数组的长度时,例如vm.items.length = newLength

就我而言,我从Angular迁移到VUE时偶然发现了这个问题。修复非常容易,但是却很难找到:

setValue(index) {
    Vue.set(this.arr, index, !this.arr[index]);
    this.$forceUpdate(); // Needed to force view rerendering
}
本文地址:http://javascript.askforanswer.com/vue-v-onclickzaizujianshangbuqizuoyong.html
文章标签: ,   ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!