Skip to content

Commit 11614d6

Browse files
committed
feat(v-on): support v-on object syntax with no arguments
Note this does not support modifiers and is meant to be used for handling events proxying in higher-order-components.
1 parent b0b6b7e commit 11614d6

File tree

12 files changed

+178
-23
lines changed

12 files changed

+178
-23
lines changed

flow/compiler.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ declare type ASTElement = {
133133
once?: true;
134134
onceProcessed?: boolean;
135135
wrapData?: (code: string) => string;
136+
wrapListeners?: (code: string) => string;
136137

137138
// 2.4 ssr optimization
138139
ssrOptimizability?: number;

flow/component.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ declare interface Component {
121121
_t: (name: string, fallback: ?Array<VNode>, props: ?Object) => ?Array<VNode>;
122122
// apply v-bind object
123123
_b: (data: any, tag: string, value: any, asProp: boolean, isSync?: boolean) => VNodeData;
124+
// apply v-on object
125+
_g: (data: any, value: any) => VNodeData;
124126
// check custom keyCode
125127
_k: (eventKeyCode: number, key: string, builtInAlias: number | Array<number> | void) => boolean;
126128
// resolve scoped slots

flow/vnode.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ declare type VNodeWithData = {
2727
context: Component;
2828
key: string | number | void;
2929
parent?: VNodeWithData;
30+
componentOptions?: VNodeComponentOptions;
3031
componentInstance?: Component;
3132
isRootInsert: boolean;
3233
};

src/compiler/codegen/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/* @flow */
22

33
import { genHandlers } from './events'
4-
import { baseWarn, pluckModuleFunction } from '../helpers'
54
import baseDirectives from '../directives/index'
65
import { camelize, no, extend } from 'shared/util'
6+
import { baseWarn, pluckModuleFunction } from '../helpers'
77

88
type TransformFunction = (el: ASTElement, code: string) => string;
99
type DataGenFunction = (el: ASTElement) => string;
@@ -268,6 +268,10 @@ export function genData (el: ASTElement, state: CodegenState): string {
268268
if (el.wrapData) {
269269
data = el.wrapData(data)
270270
}
271+
// v-on data wrap
272+
if (el.wrapListeners) {
273+
data = el.wrapListeners(data)
274+
}
271275
return data
272276
}
273277

src/compiler/directives/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
/* @flow */
22

3+
import on from './on'
34
import bind from './bind'
45
import { noop } from 'shared/util'
56

67
export default {
8+
on,
79
bind,
810
cloak: noop
911
}

src/compiler/directives/on.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* @flow */
2+
3+
import { warn } from 'core/util/index'
4+
5+
export default function on (el: ASTElement, dir: ASTDirective) {
6+
if (process.env.NODE_ENV !== 'production' && dir.modifiers) {
7+
warn(`v-on without argument does not support modifiers.`)
8+
}
9+
el.wrapListeners = (code: string) => `_g(${code},${dir.value})`
10+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* @flow */
2+
3+
import { warn, extend, isPlainObject } from 'core/util/index'
4+
5+
export function bindObjectListeners (data: any, value: any): VNodeData {
6+
if (value) {
7+
if (!isPlainObject(value)) {
8+
process.env.NODE_ENV !== 'production' && warn(
9+
'v-on without argument expects an Object value',
10+
this
11+
)
12+
} else {
13+
const on = data.on = data.on ? extend({}, data.on) : {}
14+
for (const key in value) {
15+
const existing = on[key]
16+
const ours = value[key]
17+
on[key] = existing ? [ours].concat(existing) : ours
18+
}
19+
}
20+
}
21+
return data
22+
}

src/core/instance/render.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { resolveFilter } from './render-helpers/resolve-filter'
2424
import { checkKeyCodes } from './render-helpers/check-keycodes'
2525
import { bindObjectProps } from './render-helpers/bind-object-props'
2626
import { renderStatic, markOnce } from './render-helpers/render-static'
27+
import { bindObjectListeners } from './render-helpers/bind-object-listeners'
2728
import { resolveSlots, resolveScopedSlots } from './render-helpers/resolve-slots'
2829

2930
export function initRender (vm: Component) {
@@ -121,4 +122,5 @@ export function renderMixin (Vue: Class<Component>) {
121122
Vue.prototype._v = createTextVNode
122123
Vue.prototype._e = createEmptyVNode
123124
Vue.prototype._u = resolveScopedSlots
125+
Vue.prototype._g = bindObjectListeners
124126
}

src/core/vdom/create-component.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,8 @@ export function createComponent (
161161
return createFunctionalComponent(Ctor, propsData, data, context, children)
162162
}
163163

164-
// extract listeners, since these needs to be treated as
165-
// child component listeners instead of DOM listeners
164+
// keep listeners
166165
const listeners = data.on
167-
// replace with listeners with .native modifier
168-
data.on = data.nativeOn
169166

170167
if (isTrue(Ctor.options.abstract)) {
171168
// abstract components do not keep anything

src/platforms/web/runtime/modules/events.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,14 @@ function remove (
6666
}
6767

6868
function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
69-
if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
69+
const isComponentRoot = isDef(vnode.componentOptions)
70+
let oldOn = isComponentRoot ? oldVnode.data.nativeOn : oldVnode.data.on
71+
let on = isComponentRoot ? vnode.data.nativeOn : vnode.data.on
72+
if (isUndef(oldOn) && isUndef(on)) {
7073
return
7174
}
72-
const on = vnode.data.on || {}
73-
const oldOn = oldVnode.data.on || {}
75+
on = on || {}
76+
oldOn = oldOn || {}
7477
target = vnode.elm
7578
normalizeEvents(on)
7679
updateListeners(on, oldOn, add, remove, vnode.context)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy