简体   繁体   中英

Vue.JS emit native DOM events

I have a custom checkbox component, which is composed by a classic checkbox and a label. You are able to click either the checkbox or the label to toggle the state.

在此处输入图像描述

I want to emit a native onchange event , so I can do a v-on listener on a distant div grandparent. The input I use for the actual checkbox is properly emitting a native onchange event, but I'm unable to manually emit a bubbling native onchange event when the label is clicked. I've tried this.$emit('change') and this.$emit('onchange') , neither which bubble like the native DOM event would.

Here is a simple example:

<!-- 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>

I would like to be able to tell when any element in my form has changed via onchange bubbling, so I can set a dirty flag. This example would be fine if I only had native buttons and checkboxes, as they emit native onchange events. With my CustomCheckBox , it bubbles when I click the actual native checkbox, but the label does not.

Is this possible in Vue? If not, what's the best way to do this with native Javascript?

Events emitted by Vue do not bubble like native events do. You need to handle the emitted event right in the parent component or utilize state, as shown here: How to bubble events on a component subcomponent chain with Vue js 2?

You could either "bubble" the event using v-on handlers in every subsequent parent component, passing the event on "manually", use state via a bus as described in the source mentioned above or via vuex .

Using vanilla js would be a suboptimal solution here as you would need to set the event handler in the grandparent component directly, which would mean accessing a DOM element rendered in a child component. While this is possible, it creates interdependence among the components and should therefore be avoided when possible.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM