Custom events
This page assumes that you have read Component Basics. If you don’t know much about components yet, I recommend you read it first.
##Directory
## Event names
#Unlike components and props, event names do not have any automatic case conversion. Instead, the name of the triggered event needs to exactly match the name used to listen for this event. For example, if an event with a camelCase name is triggered:this.$emit('myEvent')
, then listening to the kebab-case version of this name will have no effect:
<!-- 没有效果 --> <my-component v-on:my-event="doSomething"></my-component>
Unlike components and props, events The name will not be used as a JavaScript variable or property name, so there is no reason to use camelCase or PascalCase. And the
v-on event listener will be automatically converted to all lowercase in the DOM template (because HTML is case-insensitive), so v-on:myEvent
will become Into v-on:myevent
——Making myEvent
impossible to be monitored. Therefore, we recommend that you
kebab-case event names.
Custom component’s v-model
2.2.0 Added
v-model
on a component. By default, the prop named value
and the named input will be used.
event, but input controls such as radio buttons, check boxes, etc. may use the value
attribute for different purposes
. The model option can be used to avoid such conflicts:
Now when using 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)"
>
`
})
on this component:
here The value of <base-checkbox v-model="lovingVue"></base-checkbox>
will be passed into this prop named checked
. At the same time, when <base-checkbox>
triggers a change
event with a new value, the properties of this lovingVue
will be updated.
checkedthis prop in the component's
props
option.
Bind native events to components
You may have many This time I want to listen to a native event directly on the root element of a component. At this time, you can use the.native
modifier of This can be useful sometimes, but it's not a good idea when you're trying to listen to a very specific element like At this time , the parent's In order to solve this problem, Vue provides a With this element: all the same attributes and listeners work. .sync update:myPropName prop, we can express the intention to assign a new value to it using: Then the parent component can listen to that event and Update a local data attribute as needed. For example: The .sync be used with expressions (for example This will pass each attribute (such as title) in the doc object as an independent prop, and then add v-on listeners for updates. Use v-on
: <base-input v-on:focus.native="onFocus"></base-input>
<input>
. For example, the above <base-input>
component may be refactored as follows, so 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>
.native
listener will fail silently. It will not generate any errors, but the onFocus
handler will not be called as you expect. $listeners
property, which is an object that contains all the listeners that act on this component. For example: {
focus: function (event) { /* ... */ }
input: function (value) { /* ... */ },
}
$listeners
attribute, you can use v-on="$listeners"
to point all event listeners to this component. a specific child element. For components like <input>
that you want to also work with v-model
, create a listener like the following inputListeners
Computed properties of It is used exactly like a normal
In some cases, we may need to perform "two-way binding" on a prop. Unfortunately, true two-way binding creates maintenance problems because child components can modify their parent components with no obvious source of change in either parent or child components. Modifier
2.3.0 NewThis is why we recommend using the
titleVue.component('base-input', {
inheritAttrs: false,
props: ['label', 'value'],
computed: {
inputListeners: function () {
var vm = this
// `Object.assign` 将所有的对象合并为一个新对象
return Object.assign({},
// 我们从父级添加所有的监听器
this.$listeners,
// 然后我们添加自定义监听器,
// 或覆写一些监听器的行为
{
// 这里确保组件配合 `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>
`
})
For convenience, we provide an abbreviation for this mode, which is this.$emit('update:title', newTitle)
.sync
Modifier: <text-document
v-bind:title="doc.title"
v-on:update:title="doc.title = $event"
></text-document>
Note the characters with modifier
v-bind cannot
v-bind:title.sync="doc.title '!'
" it is invalid). Instead, you can only provide the name of the property you want to bind, something like v-model
. When we use an object to set multiple props at the same time, we can also use this
.sync modifier with
v-bind<text-document v-bind:title.sync="doc.title"></text-document>
v-bind.sync
on a literal object, for example v-bind.sync=”{ title: doc.title }”
, will not work properly because there are many edge cases to consider when parsing a complex expression like this.