Can you explain the distinction between Vue's 'v-on' directive and vue.$on method?

If I have two sibling components set up like this:

<div id="root2">
    <some-component>First</some-component>
    <some-component>Second</some-component>
</div>

... and these components are coded as follows:

Vue.component('some-component', {
    template: '<button @click="doSomething" @somethingwasdone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    methods: {
        doSomething() {
            Event.$emit('somethingWasDone');
        },

        reactToSomething() {
            this.isDisabled = true;
        }
    },
    data() {
        return {
            isDisabled: false,
        }
    },
    created() {
        Event.$on('somethingWasDone', () => this.reactToSomething());
    }
});

If my goal is to disable both buttons when one of them is clicked, I have implemented two event listeners intentionally - one using a 'v-on' directive and the other with the $on method in Vue instance. However, I am experiencing difficulty getting the former to function correctly without understanding the reason behind it.

I suspect that the issue may be related to the scope of the emitted event. Despite using the v-on directive, even the component emitting the event does not respond to it. Any assistance in resolving this matter would be highly valued!

Thank you,

Ryan


Update: Upon reviewing my code, I identified an error where the v-on directive was listening for 'componentclicked' instead of 'somethingwasdone'. After correcting this mistake, I confirmed that both approaches indeed work effectively.

Answer №1

Each Vue component instance, including the root one, is equipped with $on and $emit methods for emitting and receiving events. It's important to consider the scope of the emitted event when working with events.

In the provided example, it appears that you are attempting to emit and catch an event within the same component. In such cases, you should utilize the component instance $emit and $on methods to ensure the event remains within that scope. The syntax for this involves using this.$emit() and this.$on(), where this refers to the component instance.

Vue.component('some-component', {
    template: '<button @click="doSomething" @somethingWasDone="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    methods: {
        doSomething() {
            this.$emit('somethingWasDone');
        },

        reactToSomething() {
            this.isDisabled = true;
        }
    },
    data() {
        return {
            isDisabled: false,
        }
    },
    created() {
        this.$on('somethingWasDone', () => this.reactToSomething());
    }
});

The v-on syntax in the template is used to listen to the same event from the parent component.

<div id="root2">
     <some-component v-on:somethingWasDone="doSomething">First</some-component>
    <some-component v-on:somethingWasDone="doSomething">Second</some-component>
</div>

If you opt to use Vue.$on and Vue.$emit on the root instance, you will be emitting/listening to events at a global level.

Answer №2

From my understanding, event emissions are directed towards the parent component, requiring logic implementation in the parent component.

<div id="root2">
  <some-component
    v-on:somethingWasDone="isDisabled = true"
    :disabled="isDisabled">
   First
  </some-component>

  <some-component
    v-on:somethingWasDone="isDisabled = true"
    :isDisabled="isDisabled">
   Second
  </some-component>
</div>

// ...

data() {
  return {
    isDisabled: false
  }
}

Add the isDisabled variable to the parent and also as a prop in some-component.

Vue.component('some-component', {
    template: '<button @click="doSomething" @componentclicked="this.reactToSomething" :disabled="this.isDisabled"><slot /></button>',
    props: ["isDisabled"],
    methods: {
        doSomething() {
            Event.$emit('somethingWasDone');
        }
    },
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a dynamic input box with an add/remove button in each row using jQuery

Need help with a jQuery-based UI that allows users to dynamically add input boxes. The desired look is as follows: Default appearance: INPUT_BOX [ADD_BUTTON] [REMOVE_BUTTON] Clicking on the [Add_Button] should add another row like this, and so on: ...

Changing color when mouse hovers using Jquery

Currently, I am in the process of converting a flash ad into an html5 ad. I found this demo here, and I would like to replicate the mouse hover effect showcased. When the cursor hovers over the details text in the banner, the entire background changes to ...

What is the most efficient way to loop through an array and send each item to a method, ensuring that all methods are executed synchronously?

I need to make a request method call that retrieves its own body as an array, which is one item within another array. To achieve this, I have to iterate over the parent array and pass each of its items to the request method for a new server request. I tr ...

Ways to identify the current version of webpack installed

Currently in the process of utilizing Webpack to transpile and bundle multiple JS files. I am curious about determining the specific version that I am using. In this scenario, assuming that it is globally installed, how can I identify the version without ...

Utilizing Jest and nest.js for testing with absolute paths

Looking at my jest configuration inside the package.json: "jest": { "moduleFileExtensions": [ "js", "json", "ts" ], "moduleDirectories":["node_modules", "src" ...

Scrape data from websites where the main URL remains constant but the information in the table varies

If you take a look at this link, you'll notice that when the next page is selected, the table on the website gets reloaded with new content without any change in the URL. Even after inspecting the developer tools > Network > XHR, it's difficult t ...

Issue with react-addons-css-transition-group and multiline TextFields in Material-UI TextField

If a TextField with multiline is nested inside a react-addons-css-transition-group, it seems to disrupt the show transition. Any suggestions on how to handle this situation effectively? Check out my code snippet here: https://codesandbox.io/s/material-dem ...

What is the best way to add randomness to the background colors of mapped elements?

I am looking for a way to randomly change the background color of each element However, when I try to implement it in the code below, the background color ends up being transparent: { modules.map((module, index) => ( <div className='carou ...

How can I retrieve the attributes of multiple identical components within a webpage?

I've recently delved into learning Vue and decided to create a small application for adding fractions together. I have developed two main components: Fraction.vue and App.vue. The App.vue component contains multiple instances of the Fraction component ...

JavaScript - The function will not execute any code inside its body

When I try to call my constructor function, it stops at the function definition in the debugger and never reaches the actual function body. Is there a common reason for this issue that I might be missing? Here is an example of the code: myconstructor.js ...

Illuminate a corresponding regular expression within a text input

I currently have a functional code for testing regex, which highlights matching patterns. However, my challenge lies in highlighting the result within the same input as the test string. Below you will see the HTML and JavaScript snippets along with two ima ...

Trigger a callback in KnockoutJS once all bindings have been successfully set up

I am facing a frustrating bug that is detailed here: <select> only shows first char of selected option and I am looking for a solution to remove the display:none from my select boxes in order to resolve this issue. Any ideas? Here's the binding ...

Submitting Data Forms with AJAX on dynamically loaded webpages

Issue with Form Submission in Ajax-Generated Page I am experiencing an issue with form submission on a page generated within AJAX. The page contains two forms, #form1 and #form2. The jQuery code for submitting the form is as shown below: jQuery("#form1" ...

ngSanitize continues to present plain text rather than rendering HTML code

When working with AngularJS scope, I encountered the need to display certain items as HTML. After some research, I realized that integrating ngSanitize was necessary for this functionality. Here is how I implemented it in my app: <script src="Scripts/a ...

Is it advisable to create a component for each codebase when combining multiple codebases into one?

Embarking on a new project where the goal is to merge 7 different codebases into a single cohesive one. Each individual codebase serves a unique purpose, such as Registration, Surveys, Email Blaster, and more. My plan is to utilize Vue for the frontend and ...

cancel the ongoing ajax request during a specific event

There seems to be an issue with the behavior of clicking on the .personalized class. When clicked, it does not display both #loading_personalized and #divPersonalized elements simultaneously. This results in the execution of an AJAX call even when the pr ...

Create a JavaScript script within a CSS file

I'm attempting to create this using only CSS: Codepen and I would like to achieve the same effect but solely with CSS. This is what my CSS looks like: .text{ --a: calc(var(--a);*0.82+(1.5-var(--b);)/10); --b: calc(var(--b);+var(--a);); transfor ...

Can a variable name be created using a function input?

It seems like my title might be a bit confusing, but oh well. I'm currently working on developing a game and I have several arrays named things like ItemsInG5Array, ItemsInB2Array. These names correspond to different nodes on the map. What I'm ai ...

Sequelize associations are not functioning optimally as expected

Trying to display a nested relationship: Cat.hasMany(legs) Leg.belongsTo(cat) Leg.hasOne(paw) paw.hasMany(leg) This is the Cat Model: module.exports = (sequelize, DataTypes) => { const Cat = sequelize.define('Cat', { us ...

Modify KeyboardDatePicker to display the full name of the day and month

Date Selector Hey there, I'm looking to modify the date format from Wed, Apr 7 to Wednesday, April 7. Is there a way to display the full name of the day and month instead of the short abbreviation? ...