prohibit replacing Vue.config + support custom keyCodes

This commit is contained in:
Evan You 2016-06-22 11:35:33 -04:00
parent 63da54ddee
commit 4fe51a75a9
8 changed files with 58 additions and 7 deletions

View File

@ -57,6 +57,7 @@ declare interface Component {
_isBeingDestroyed: boolean;
_vnode: ?VNode;
_staticTrees: ?Array<VNode>;
_keyCode: (key: string) => ?number;
// private methods
// lifecycle

View File

@ -53,10 +53,13 @@ function genHandler (
}
function genKeyFilter (key: string): string {
const code = keyCodes[key] || JSON.stringify(key)
const code =
parseInt(key, 10) || // number keyCode
keyCodes[key] || // built-in alias
`_keyCode(${JSON.stringify(key)})` // custom alias
if (Array.isArray(code)) {
return `if(${code.map(c => `$event.keyCode!=${c}`).join('&&')})return;`
return `if(${code.map(c => `$event.keyCode!==${c}`).join('&&')})return;`
} else {
return `if($event.keyCode!=${code})return;`
return `if($event.keyCode!==${code})return;`
}
}

View File

@ -3,13 +3,17 @@
import { no } from 'shared/util'
export type Config = {
// user
optionMergeStrategies: { [key: string]: Function },
silent: boolean,
errorHandler: ?Function,
ignoredElements: ?Array<string>,
keyCodes: { [key: string]: number },
// platform
isReservedTag: (x?: string) => boolean,
isUnknownElement: (x?: string) => boolean,
mustUseProp: (x?: string) => boolean,
// internal
_assetTypes: Array<string>,
_lifecycleHooks: Array<string>,
_maxUpdateCount: number,
@ -38,6 +42,11 @@ const config: Config = {
*/
ignoredElements: null,
/**
* Custom user key aliases for v-on
*/
keyCodes: Object.create(null),
/**
* Check if a tag is reserved so that it cannot be registered as a
* component. This is platform-dependent and may be overwritten.

View File

@ -10,7 +10,17 @@ import { set, del } from '../observer/index'
import builtInComponents from '../components/index'
export function initGlobalAPI (Vue: GlobalAPI) {
Vue.config = config
// config
const configDef = {}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
configDef.set = () => {
util.warn(
'Do not replace the Vue.config object, set individual fields instead.'
)
}
}
Object.defineProperty(Vue, 'config', configDef)
Vue.util = util
Vue.set = set
Vue.delete = del

View File

@ -152,6 +152,9 @@ export function renderMixin (Vue: Class<Component>) {
}
}
}
// expose v-on keyCodes
Vue.prototype._keyCode = key => config.keyCodes[key]
}
function resolveSlots (

View File

@ -126,6 +126,19 @@ describe('Directive v-on', () => {
expect(spy).toHaveBeenCalled()
})
it('should support custom keyCode', () => {
Vue.config.keyCodes.test = 1
vm = new Vue({
el,
template: `<input @keyup.test="foo">`,
methods: { foo: spy }
})
triggerEvent(vm.$el, 'keyup', e => {
e.keyCode = 1
})
expect(spy).toHaveBeenCalled()
})
it('should bind to a child component', () => {
Vue.component('bar', {
template: '<span>Hello</span>'

View File

@ -1,6 +1,13 @@
import Vue from 'vue'
describe('Global config', () => {
it('should warn replacing config object', () => {
const originalConfig = Vue.config
Vue.config = {}
expect(Vue.config).toBe(originalConfig)
expect('Do not replace the Vue.config object').toHaveBeenWarned()
})
describe('silent', () => {
it('should be false by default', () => {
Vue.util.warn('foo')

View File

@ -216,17 +216,22 @@ describe('codegen', () => {
it('generate events with keycode', () => {
assertCodegen(
'<input @input.enter="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!=13)return;onInput($event)}}}))}`
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}}))}`
)
// multiple keycodes (delete)
assertCodegen(
'<input @input.delete="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!=8&&$event.keyCode!=46)return;onInput($event)}}}))}`
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==8&&$event.keyCode!==46)return;onInput($event)}}}))}`
)
// number keycode
assertCodegen(
'<input @input.13="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!="13")return;onInput($event)}}}))}`
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==13)return;onInput($event)}}}))}`
)
// custom keycode
assertCodegen(
'<input @input.custom="onInput">',
`with(this){return _h(_e('input',{on:{"input":function($event){if($event.keyCode!==_keyCode("custom"))return;onInput($event)}}}))}`
)
})