Writing in the front
Because of the vue. js is very interested in, and the usual work of the technology stack vue. js, these months spent some time to study the vue. js source code, and do a summary and output. Original address of the article: github.com/answershuto… . In the process of learning, I added Chinese annotations for Vue github.com/answershuto… , hope can be helpful to other want to learn Vue source partners. There may be some misunderstanding, welcome to point out, learn together, make progress together.
Vue event apis
As we all know, vue.js provides us with four event apis: $ON, $once, $off, and $emit.
Initialization event
Initializing events Creates a _events object on the VM to hold events. The contents of _events are as follows:
{
eventName: [func1, func2, func3]
}Copy the code
Store event names and corresponding execution methods.
/* Initialize the event */
export function initEvents (vm: Component) {
/* Create a _events object on the VM to hold events. * /
vm._events = Object.create(null)
/* The bool flag indicates the presence or absence of hooks, rather than the need to hash the presence or absence of hooks, which can reduce unnecessary overhead and optimize performance. * /
vm._hasHookEvent = false
// init parent attached events
/* Initializes the parent attach event */
const listeners = vm.$options._parentListeners
if (listeners) {
updateComponentListeners(vm, listeners)
}
}Copy the code
$on
The $ON method is used to listen for a custom event on the VM instance that can be fired by $emit.
Vue.prototype.$on = function (event: string | Array<string>, fn: Function) :Component {
const vm: Component = this
/* If it is an array, recurse $on to bind method */ for each member
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$on(event[i], fn)
}
} else {
(vm._events[event] || (vm._events[event] = [])).push(fn)
// optimize hook:event cost by using a boolean flag marked at registration
// instead of a hash lookup
/* Bool is a flag bit to indicate the presence of a hook, rather than the need to hash the table to find the presence of a hook. * /
if (hookRE.test(event)) {
vm._hasHookEvent = true}}return vm
}Copy the code
$once
$once listens for an event that can only be triggered once and automatically removes the event after it is triggered.
Vue.prototype.$once = function (event: string, fn: Function) :Component {
const vm: Component = this
function on () {
/* Destroy the event on the first execution */
vm.$off(event, on)
/* The registration method */
fn.apply(vm, arguments)
}
on.fn = fn
vm.$on(event, on)
return vm
}Copy the code
$off
$off is used to remove custom events
Vue.prototype.$off = function (event? : string | Array
, fn? : Function
) :Component {
const vm: Component = this
// all
/* If no parameter is passed, log out all events */
if (!arguments.length) {
vm._events = Object.create(null)
return vm
}
// array of events
/* Recursively cancel the event if the event is an array */
if (Array.isArray(event)) {
for (let i = 0, l = event.length; i < l; i++) {
this.$off(event[i], fn)
}
return vm
}
// specific event
const cbs = vm._events[event]
/*Github:https://github.com/answershuto*/
/* If the event does not exist, return */
if(! cbs) {return vm
}
/* If only the event argument is passed, log out all methods */
if (arguments.length === 1) {
vm._events[event] = null
return vm
}
// specific handler
/* traverse for the corresponding method and delete */
let cb
let i = cbs.length
while (i--) {
cb = cbs[i]
if (cb === fn || cb.fn === fn) {
cbs.splice(i, 1)
break}}return vm
}Copy the code
$emit
$emit is used to trigger the specified custom event.
Vue.prototype.$emit = function (event: string) :Component {
const vm: Component = this
if(process.env.NODE_ENV ! = ='production') {
const lowerCaseEvent = event.toLowerCase()
if(lowerCaseEvent ! == event && vm._events[lowerCaseEvent]) { tip(`Event "${lowerCaseEvent}" is emitted in component ` +
`${formatComponentName(vm)} but the handler is registered for "${event}". ` +
`Note that HTML attributes are case-insensitive and you cannot use ` +
`v-on to listen to camelCase events when using in-DOM templates. ` +
`You should probably use "${hyphenate(event)}" instead of "${event}". `)}}let cbs = vm._events[event]
if (cbs) {
/* Convert an array-like object to an array */
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments.1)
/* Execute */
for (let i = 0, l = cbs.length; i < l; i++) {
cbs[i].apply(vm, args)
}
}
return vm
}Copy the code
about
Author: Ran Mo
Email: [email protected] or [email protected]
Github: github.com/answershuto
Blog: answershuto. Making. IO /
Zhihu homepage: www.zhihu.com/people/cao-…
Zhihu column: zhuanlan.zhihu.com/ranmo
The Denver nuggets: juejin. Cn/user / 289926…
OsChina:my.oschina.net/u/3161824/b…
Please indicate the source of reprint, thank you.
Welcome to follow my public number