events.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /* @flow */
  2. import { isDef, isUndef } from 'shared/util'
  3. import { updateListeners } from 'core/vdom/helpers/index'
  4. import { isIE, supportsPassive } from 'core/util/index'
  5. import { RANGE_TOKEN, CHECKBOX_RADIO_TOKEN } from 'web/compiler/directives/model'
  6. // normalize v-model event tokens that can only be determined at runtime.
  7. // it's important to place the event as the first in the array because
  8. // the whole point is ensuring the v-model callback gets called before
  9. // user-attached handlers.
  10. function normalizeEvents (on) {
  11. /* istanbul ignore if */
  12. if (isDef(on[RANGE_TOKEN])) {
  13. // IE input[type=range] only supports `change` event
  14. const event = isIE ? 'change' : 'input'
  15. on[event] = [].concat(on[RANGE_TOKEN], on[event] || [])
  16. delete on[RANGE_TOKEN]
  17. }
  18. // This was originally intended to fix #4521 but no longer necessary
  19. // after 2.5. Keeping it for backwards compat with generated code from < 2.4
  20. /* istanbul ignore if */
  21. if (isDef(on[CHECKBOX_RADIO_TOKEN])) {
  22. on.change = [].concat(on[CHECKBOX_RADIO_TOKEN], on.change || [])
  23. delete on[CHECKBOX_RADIO_TOKEN]
  24. }
  25. }
  26. let target: any
  27. function createOnceHandler (event, handler, capture) {
  28. const _target = target // save current target element in closure
  29. return function onceHandler () {
  30. const res = handler.apply(null, arguments)
  31. if (res !== null) {
  32. remove(event, onceHandler, capture, _target)
  33. }
  34. }
  35. }
  36. function add (
  37. event: string,
  38. handler: Function,
  39. capture: boolean,
  40. passive: boolean
  41. ) {
  42. target.addEventListener(
  43. event,
  44. handler,
  45. supportsPassive
  46. ? { capture, passive }
  47. : capture
  48. )
  49. }
  50. function remove (
  51. event: string,
  52. handler: Function,
  53. capture: boolean,
  54. _target?: HTMLElement
  55. ) {
  56. (_target || target).removeEventListener(
  57. event,
  58. handler._withTask || handler,
  59. capture
  60. )
  61. }
  62. function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {
  63. if (isUndef(oldVnode.data.on) && isUndef(vnode.data.on)) {
  64. return
  65. }
  66. const on = vnode.data.on || {}
  67. const oldOn = oldVnode.data.on || {}
  68. target = vnode.elm
  69. normalizeEvents(on)
  70. updateListeners(on, oldOn, add, remove, createOnceHandler, vnode.context)
  71. target = undefined
  72. }
  73. export default {
  74. create: updateDOMListeners,
  75. update: updateDOMListeners
  76. }