【问题标题】:Vue.JS emit native DOM eventsVue.JS 发出原生 DOM 事件
【发布时间】:2021-03-29 21:06:37
【问题描述】:

我有一个自定义的复选框组件,它由一个经典的复选框和一个标签组成。您可以单击复选框或标签来切换状态。

我想发出一个原生的onchange event,所以我可以在一个遥远的 div 祖父母上做一个v-on 监听器。我用于实际复选框的输入正确地发出了原生 onchange 事件,但是当点击标签时我无法手动发出冒泡的原生 onchange 事件。我试过this.$emit('change')this.$emit('onchange'),都没有像原生DOM 事件那样冒泡。

这是一个简单的例子:

<!-- Form.vue -->

<div id="form-1" @change="markDirty()">
  <div class="header">
    <CustomButton>Submit</CustomButton>
    <CustomButton>Cancel</CustomButton>
  </div>
  <div class="form-body">
    <div class="form-region">
      <CustomCheckBox :checked.sync='tryChecked'>Try checking me!</CustomCheckBox>
    </div>
  </div>
</div>
<!-- CustomCheckBox.vue -->

<template>
  <div class="custom-checkbox">
    <input type="checkbox" v-on:change="selectCheckbox" />
    <label v-on:click="selectCheckbox">
        <slot></slot>
    </label>
  </div>
</template>

<script>
export default {
    name: 'CustomCheckBox',
    props: {
        checked: {
            type: Boolean,
            required: true
        }
    },
    methods: {
        selectCheckbox() {
            this.$emit('update:checked', !this.checked)
            this.$emit('change')
        }
    }
}
</script>

我希望能够通过onchange 冒泡来判断我的表单中的任何元素何时发生变化,这样我就可以设置一个脏标志。如果我只有原生按钮和复选框,这个例子会很好,因为它们会发出原生 onchange 事件。使用我的CustomCheckBox,当我单击实际的本机复选框时它会冒泡,但标签不会。

这在 Vue 中可行吗?如果没有,使用本机 Javascript 执行此操作的最佳方法是什么?

【问题讨论】:

  • 不清楚你所说的远程 div 祖父母是什么意思,一个例子可以解释它,你可以在祖父母组件上使用 ref 来获取子实例并观察其数据,然后在呈现复选框的组件上你可以使用&lt;checkbox :change="doSomthing"/&gt;,不过如果你需要从远处看东西,那么可以考虑使用 vuex
  • @LawrenceCherone 更新了一个示例。在我的情况下,整个项目有很多很多形式,结构各不相同。 “手动冒泡”或显式使用 refs 是不切实际的。我想要一些模块化的并且适合 web 框架风格的东西。如果原生 HTML 元素发出更改事件,它只会认为组件也应该能够。
  • @Spooky Vue DOM 事件与原生 DOM 事件完全分开,因此它们不会一对一地操作。查看this 文章。详细介绍原生 onChange 的缺点以及如何使用原生 HTML API 属性捕获更改的值。

标签: javascript html vue.js vuejs2 dom-events


【解决方案1】:

Vue 发出的事件不会像原生事件那样冒泡。您需要在父组件中直接处理发出的事件或利用状态,如下所示:How to bubble events on a component subcomponent chain with Vue js 2?

您可以在每个后续父组件中使用v-on 处理程序“冒泡”事件,“手动”传递事件,通过bus 使用状态,如上述源中所述或通过vuex

在这里使用 vanilla js 将不是最佳解决方案,因为您需要直接在祖父组件中设置事件处理程序,这意味着访问在子组件中呈现的 DOM 元素。虽然这是可能的,但它会在组件之间造成相互依赖,因此应尽可能避免。

【讨论】:

  • 手动冒泡是不切实际的,因为在我的项目中存在许多不同的形式,其结构各不相同。我不想为每个表单添加一个v-on:change 指令并重新发送到 5 层以上的 div。
  • 对于全局状态,每个组件管理自己的脏状态。我不想要页面范围的脏状态。如果我在一页中有多个表单,我希望它们能够从其中的组件中单独获取它们的脏状态。
  • 已经存在本机冒泡更改事件的功能,它仅表明自定义组件也应该能够发出 onchange 事件。我敢肯定,我不是唯一一个使用 Vue 制作过自定义输入组件的人。
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 2017-04-01
  • 2016-11-19
  • 2019-09-20
  • 2018-10-21
  • 1970-01-01
  • 2012-01-01
  • 1970-01-01
相关资源
最近更新 更多