Custom Events in Vue.js: Naming Conventions and Best Practices
Event Names
Event names does not provide automatic case transformation unlike components and props.
Rather, the name of an emitted event must match the name used to listen to that event exactly. For instance, if we emit a camelCase event name:
this.$emit('myEvent')
listening to its kebab-case version will have no effect.
Also, unlike props and components, events names can never be used as property names or variable names in JavaScript. So there is no reason to use PascalCase or camelCase. In addition, v-on event listeners inside DOM templates will automatically be transformed to lowercase (due to HTML's case-insensitivity)., thus v-on:myEvent will become v-on:myevent.
Customizing Component v-model
On a component v-model use value as the prop and input as the event by default, but some input types such as radio buttons and checkboxes may want to use the value attribute for a totally different purpose. Using the model can help us avoid a conflict in such cases:
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template:
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
})
When we use the v-model on this component we have:
<base-checkbox v-model="lovingVueJs"></base-checkbox>
the value of lovingVueJs would be passed to the checked prop. When
Binding Native Events to Components
There could be times when we wish to listen directly to a native event on the root element of a component. In such cases, we can use the native modifier for v-on:
<base-input v-on:focus.native="onFocus"></base-input>
Though this can be useful sometimes, it is however not a good idea when trying to listen on a very specific element, like an <input>. For instance, the <base-input> component shown above must refactor so that the root element is actually a <label> element:
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on:input="$emit('input', $event.target.value)"
>
</label>
The native listener in the parent would silently break in this case. Though there will be no error however, the onFocus handler wouldn't be called when we expected it to.
Vue however provides a solution to this problem, this solution is achieved using the $listener property containing an object of listeners being used on the component:
{
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
When we use the $listeners property, we can forward all event listeners on the component to a specific child element with v-on="$listeners". We naturally will want to use v-model for elements like <input>, in such cases it is useful to create a new computed property for listeners, as in the case of inputListeners below:
Vue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` merges objects together forming a new object
return Object.assign({},
// All the listeners are added from the parents
this.$listeners,
// We can then add custom listeners or override the
// behavior of some listeners.
{
// This ensures that the component will work with v-model
input: function (event) {
vm.$emit('input', event.target.value)
}
}
)
}
},
template:
<label>
{{ label }}
<input
v-bind="$attrs"
v-bind:value="value"
v-on="inputListeners"
>
</label>
})
.sync Modifier
There are certain cases when we may need "two-way binding" for a prop. However, that can create a maintenance issues. Instead it is recommended that we emit events in the pattern of update:myPropName. For instance, given a hypothetical component with a title prop, we could communicate the intent of assigning a new value with:
this.$emit('update:title', newTitle)
And the parent can then listen to that event and update a local data property, when it wants to. For instance:
<text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
Previous:
Props in Vue.js: Types, Validation, and Best Practices.
Next:
Dynamic and Async Components in Vue.js.
It will be nice if you may share this link in any developer community or anywhere else, from where other developers may find this content. Thanks.
https://w3resource.com/vue/vue-custom-events.php
- Weekly Trends and Language Statistics
- Weekly Trends and Language Statistics