Three components of the two API: event
Wherein prop mentioned unidirectional downlink data in a bound, the parent component subassembly to pass values prop realized that if the parent component subassembly to pass required value or other communication request, by vue
the event monitor system (trigger event, monitor the implementation of the callback function, and can accept mass participation in the callback function).
Vue
Built a complete set of event triggers logic:
v-on / @
: The original HTML elements listens native events, custom events or sub-assemblies.native
: Native event-triggered components of the root element$on
: Event Listener component itself triggered$emit
: trigger event$off
: Uninstall event listener component itself$once
: A single monitor, event listeners only once, after which no longer valid$listeners
: Includes v-on register on the component label all custom listener objects, key event name, value to the event listener function.
v-on / @
Click to view: v-on event and event modifier, and DOM / JQUERY events within
So to achieve the face component to parent component communication, we can in the parent component v-on
binding open an event listener on the child component tag, then use the internal sub-components $emit
of the trigger event.
<div id="app">
<p>this is event example for v-on/@<p>
<!-- 绑定监听事件some-event -->
<com-child @com-btn-click="handleChildClick"></com-child>
</div>
const comChild = Vue.extend({
template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发父级监听事件</button>`,
methods: {
handleClick() {
this.$emit('com-btn-click',666)
}
}
})
const vm = new Vue({
el: "#app",
components: {
comChild,
},
methods: {
handleChildClick(val) {
alert('我是由子组件触发的:' + val);
}
}
})
The event name always uses kebab-case form
different from the assembly and prop, event name does not appear as a JavaScript variable or attribute names, so any automatic case conversion does not exist. That event triggered the need to name exactly matches the name used to listen to this event.
And because v-on is bound to the html element, but HTML is not case sensitive. The general name of the event and are based on more than one word, it is proposed that the name of the event all use kebab-case
a hyphen form.
Event parameter passing
subassembly $emit
while the trigger event, a value can be passed, in v-on
the received binding event listener.
// $emit第一个参数是监听器事件名,第二个是要传递的参数
this.$emit('some-event',666)
// 监听事件处理函数第一个参数即为接收的值
handleChildEvent(val) {
alert('我是由子组件触发的:' + val)
}
$on / $once
$on
Open to listen for events and $emit
listen to events are triggered in the same component instance.
<div id="app">
<p>this is event example for $on<p>
<com-child></com-child>
</div>
const comChild = Vue.extend({
template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发监听事件</button>`,
data: () => {
return {
count: 0,
}
},
methods: {
handleClick() {
this.count++
this.$emit('comBtnClick',this.count)
}
},
mounted() {
this.$on('comBtnClick', (val) => {
alert('我是由$on注册的监听子组件按钮点击事件'+val)
if (val === 3) {
console.log('卸载事件监听')
this.$off('comBtnClick')
}
})
this.$once('comBtnClick', (val) => {
alert('我是由$once注册监听子组件按钮点击事件,只会触发一次'+val)
})
}
})
const vm = new Vue({
el: "#app",
components: {
comChild,
},
})
For internal components under conditions trigger other events, such as to monitor the implementation of time with $once
, or monitor the implementation and under certain conditions no longer listening use $on配合$off
.
But if it is continuous monitoring, as long as the event is triggered on the implementation of an action, can be written in the listener callback methods in the method, the method is performed when the event direct handling.
const comChild = Vue.extend({
template: `<button @click="handleClick">我是子组件内定义的按钮,点击触发监听事件</button>`,
methods: {
handleClick() {
// this.$emit('comBtnClick',888)
this.comBtnClick(val)
},
comBtnClick(val) {
alert('我是按钮点击触发执行'+val)
}
},
})
Using the above $on / $emit
, if the internal components perform only an object can not be achieved and the value of the communication component subassembly parent mass. At this point we need to with the $refs
property implementation.
ref
With a single characteristicHTML
over the elements may acquire the nativeDOM
node object, the label used in the assembly, the object can obtain the component instance.
Under the above modified example, using the $on / $emit / $refs
object instance to the parent component subassembly assembly
<div id="app">
<p>this is event example for $on / $emit / $refs<p>
<com-child ref="comChild"></com-child>
</div>
const comChild = Vue.extend({
template: `<div>
<button @click="handleBtnClick">我是子组件内定义的按钮,点击触发监听事件</button>
</div>`,
methods: {
handleBtnClick() {
this.$emit('comBtnClick',999)
},
},
})
const vm = new Vue({
el: "#app",
components: {
comChild,
},
mounted() {
this.$refs.comChild.$on('outerSelfEvent', val => {
console.log('组件按钮点击了')
})
this.$refs.comChild.$once('outerSelfEvent', val => {
console.log('组件按钮点击了,我只监听执行一次')
})
}
})
$off
Remove custom event listeners.
- If no parameters, then remove all the event listeners;
- If only event, then remove all the event listeners;
- If both events and callbacks, only remove this listener callback (callback function can not be used at this time of writing the anonymous function when registering events).
<div id="app">
<p>this is event example for $off<p>
<com-child ref="comChild"></com-child>
</div>
const comChild = Vue.extend({
template: `<div>
<button @click="handleBtnClick1">点击触发触发组件内部监听事件elert</button>
<button @click="handleBtnClick2">点击触发触发组件内部监听事件console</button>
<button @click="handleUninstallAllListener">点击卸载组件内所有事件监听$off()</button>
<button @click="handleUninstallTheEvent">点击卸载组件内指定事件监听器$off(event)</button>
<button @click="handleUninstallTheEventCallback">点击卸载组件内指定监听器$off(event,cb)</button>
</div>`,
methods: {
handleBtnClick1() {
this.$emit('handleAlert')
},
handleBtnClick2() {
this.$emit('handleConsole')
},
handleUninstallAllListener() {
console.log('卸载所有监听器')
this.$off()
},
handleUninstallTheEvent() {
console.log('卸载指定事件handleAlert的所有监听器')
this.$off('handleAlert')
},
handleUninstallTheEventCallback() {
console.log('卸载指定事件handleConsole中的handleConsole2监听器')
this.$off('handleConsole', this.handleConsole2)
},
handleConsole2() {
console.log('监听器Console2')
}
},
mounted() {
this.$on('handleAlert',function () {
alert('监听器alert1')
})
this.$on('handleAlert',function () {
alert('监听器alert2')
})
this.$on('handleConsole',function () {
console.log('监听器Console1')
})
this.$on('handleConsole',this.handleConsole2 )
}
})
const vm = new Vue({
el: "#app",
components: {
comChild,
},
})
$listeners
Contains all registered by v-on event listeners parent scope in the component tag.
But does not include:
- Containing .native decorator native event listener
- Components use $ on registered listeners
The following example, we bind on the child component tag a native event, two v-on
custom events the way, a $on
custom event method.
But the final $listeners
print out only one of two v-on
events bound manner.
<div id="app">
<p>this is event example for $listeners<p>
<com-child
ref="comChild"
@click.native="handleNativeClick"
@child-btn-click-console="handelChildBtnClickConsole" @child-btn-click-alert="handelChildBtnClickAlert"
></com-child>
</div>
const comChild = Vue.extend({
template: `<div>
<button @click="handleBtnClick" >点击触发触发组件内部监听事件elert</button>
</div>`,
methods: {
handleBtnClick() {
this.$emit('child-btn-click-alert')
this.$emit('child-btn-click-console')
this.$emit('handleConsole')
},
},
mounted() {
this.$on('handleConsole',function () {
console.log('$on绑定监听器')
})
// 打印出$listeners
console.log('$listeners:', this.$listeners)
}
})
const vm = new Vue({
el: "#app",
components: {
comChild,
},
methods: {
handelChildBtnClickAlert() {
alert('v-on绑定$emit触发alert')
},
handelChildBtnClickConsole() {
console.log("v-on绑定$emit触发console")
},
handleNativeClick() {
alert('native click')
}
}
})
$listeners:
child-btn-click-alert: ƒ invoker()
child-btn-click-console: ƒ invoker()