Quando pesquisei esse princípio antes, só escrevi duas frases em muitos artigos:
A associação de eventos nativos é vinculada a elementos reais por meio de addEventListener.
A vinculação de evento de componente é obtida por meio da chave personalizada $ on do Vue.
Como isso aconteceu? Não disse?
Vamos dar uma olhada nisso agora.
// 原生事件绑定
<div @click="fn()"></div>
// 组件绑定
<my-component @click.native="fn" @click="fn1"></my- component>
Princípio:
Compilação de eventos:
let compiler = require('vue-template-compiler'); //vue-loader
let r1 = compiler.compile('<div @click="fn()"></div>');
let r2 = compiler.compile('<my-component @click.native="fn" @click="fn1"></my- component>'); console.log(r1);
// {on:{click}} console.log(r2);
// {nativeOn:{click},on:{click}}
Os dois compilados não são iguais
// 前者
with (this){
return _c('div',{
on:{
"click":function($event){
return fn()}}})}
// 后者
with (this){
return _c('my-component',{
on:{
"click":fn1},nativeOn:{
"click":function($event){
return fn($event)}}})}
1.1 Vinculação de dom nativo
- O Vue chamará createElm ao criar um dom real e invokeCreateHooks será chamado por padrão
- Percorrerá o código de processamento de atributo relativo na plataforma atual, incluindo o método updateDOMListeners, e o método add será passado internamente
Código fonte:
function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
return }
const on = vnode.data.on || {
} const oldOn = oldVnode.data.on || {
}
target = vnode.elm
normalizeEvents(on)
updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context)
target = undefined
}
function add (
name: string,
handler: Function,
capture: boolean,
passive: boolean
) {
target.addEventListener( // 给当前的dom添加事件
name,
handler,
supportsPassive
? {
capture, passive }
: capture
)
}
1.2 Eventos de ligação em componentes
export function updateComponentListeners (
vm: Component,
listeners: Object,
oldListeners: ?Object
) {
target = vm updateListeners(
listeners, oldListeners || {
},
add,
remove,
createOnceHandler, vm)
target = undefined
}
function add (event, fn) {
target.$on(event, fn)
}
Os eventos de ligação de componentes são implementados por meio do método $ on customizado em vue
1.3 Como $ on funciona?
vm.$on( event, callback )
efeito:
Ouça eventos personalizados na instância atual. O evento pode ser acionado por vm. $ Emit. A função de retorno de chamada receberá todos os parâmetros extras da função de gatilho de evento de entrada.
princípio:
$ on adota o padrão clássico de design publicar-assinante. Primeiro, defina um centro de eventos, inscreva-se em eventos por meio de $ on, armazene os eventos no centro de eventos e, a seguir, acione os eventos de inscrição armazenados no centro de eventos por meio de $ emit.
Vue.prototype.$on = function (event, fn) {
const vm: Component = this
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)
}
return vm
}
Olhando para o código, a lógica é muito simples. A função $ on recebe dois parâmetros. O primeiro é o nome do evento inscrito, que pode ser múltiplo. Se houver vários, uma matriz de nomes de eventos é passada. A outra é a função de retorno de chamada. Primeiro, determine se o evento de entrada é um array. Se for, atravesse o array e chame recursivamente o método $ on para cada evento no array para inscrevê-lo como um único evento. Se não for um array, trate-o como um único nome de evento, use o nome do evento como a chave, primeiro tente obter a lista de eventos correspondente na propriedade _events da instância atual, se não estiver disponível, dê-lhe um vazio array como o valor padrão e adicione a segunda função de retorno de chamada de parâmetro.
Mais uma frase, quais são os _events da instância? Quando o evento é inicializado, o atributo _event é vinculado à função initEvents e atribuído a um objeto vazio. Este atributo _events é usado como o centro de eventos da instância atual e todos os eventos vinculados a esta instância serão armazenados no atributo _events do centro de eventos.
Este é o princípio interno de $ on.