Hone logo
Hone
Problems

Implementing Event Modifiers in a Vue Component

Event modifiers in Vue.js provide a concise and powerful way to alter the behavior of event listeners. This challenge asks you to build a simplified version of event modifier functionality within a Vue component, focusing on .stop, .prevent, and .self modifiers. This exercise will solidify your understanding of event handling and how Vue extends it for improved developer experience.

Problem Description

You are tasked with creating a Vue component that handles click events on a series of nested elements. The component should support three event modifiers:

  • .stop: Prevents the event from bubbling up to parent elements.
  • .prevent: Prevents the default browser behavior associated with the event (e.g., submitting a form).
  • .self: Only triggers the event handler if the event originated from the element the handler is attached to.

The component should dynamically apply these modifiers based on a configuration object passed as a prop. The configuration object will specify which modifiers to apply to each event handler.

Key Requirements:

  • The component should accept a modifiers prop, which is an object where keys are event names (e.g., "click") and values are arrays of modifiers (e.g., ["stop", "prevent"]).
  • The component should render a series of nested div elements.
  • Each div should have a click event listener attached.
  • The event listener should check if the specified modifiers are present in the modifiers configuration for that event.
  • Based on the modifiers, the event listener should either:
    • Call a provided handler function.
    • Prevent the default browser behavior.
    • Stop event propagation.
    • Do nothing if the .self modifier is present and the event did not originate from the element.

Expected Behavior:

  • Clicking on any of the nested div elements should trigger the event handler if the modifiers are configured correctly.
  • .stop should prevent the click event from reaching parent elements.
  • .prevent should prevent the default browser action (e.g., form submission).
  • .self should only trigger the handler if the click originated from the element itself.

Edge Cases to Consider:

  • Empty modifiers prop.
  • Event names not defined in the modifiers prop.
  • Invalid modifier names in the modifiers prop (should be ignored).
  • Multiple modifiers for the same event (apply all).

Examples

Example 1:

Input:
modifiers = {
  'click': ['stop', 'prevent']
}
handler = (event) => console.log('Handler called with stop and prevent');

Component Structure:
<div>
  <div>
    <div></div>
  </div>
</div>

Output: Clicking on any nested div will log "Handler called with stop and prevent" to the console, and the click event will not propagate to the parent div, and the default browser action will be prevented.

Explanation: The click event handler is called, and both .stop and .prevent modifiers are applied.

Example 2:

Input:
modifiers = {
  'click': ['self']
}
handler = (event) => console.log('Handler called with self');

Component Structure:
<div>
  <div>
    <div></div>
  </div>
</div>

Output: Clicking directly on the innermost div will log "Handler called with self" to the console. Clicking on any other div will do nothing.

Explanation: The .self modifier ensures the handler is only called if the click originates from the element itself.

Example 3:

Input:
modifiers = {
  'click': ['invalidModifier', 'stop']
}
handler = (event) => console.log('Handler called with stop');

Component Structure:
<div>
  <div>
    <div></div>
  </div>
</div>

Output: Clicking on any nested div will log "Handler called with stop" to the console, and the click event will not propagate to the parent div. The "invalidModifier" is ignored.

Explanation: The handler is called, and the .stop modifier is applied. The invalid modifier is gracefully ignored.

Constraints

  • The component should be written in TypeScript.
  • The component should be functional (using setup and ref).
  • The handler function should accept an event object as an argument.
  • The component should render at least three nested div elements.
  • The solution should be well-structured and readable.
  • Performance is not a primary concern for this exercise.

Notes

  • Consider using event.stopPropagation() to implement the .stop modifier.
  • Consider using event.preventDefault() to implement the .prevent modifier.
  • Use event.target to determine if the event originated from the element itself for the .self modifier.
  • Focus on the core logic of applying modifiers; you don't need to implement a full-fledged Vue plugin.
  • Think about how to handle different modifier combinations effectively.
Loading editor...
typescript