events.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. var _ = require('../util')
  2. var inDoc = _.inDoc
  3. /**
  4. * Setup the instance's option events & watchers.
  5. * If the value is a string, we pull it from the
  6. * instance's methods by name.
  7. */
  8. exports._initEvents = function () {
  9. var options = this.$options
  10. registerCallbacks(this, '$on', options.events)
  11. registerCallbacks(this, '$watch', options.watch)
  12. }
  13. /**
  14. * Register callbacks for option events and watchers.
  15. *
  16. * @param {Vue} vm
  17. * @param {String} action
  18. * @param {Object} hash
  19. */
  20. function registerCallbacks (vm, action, hash) {
  21. if (!hash) return
  22. var handlers, key, i, j
  23. for (key in hash) {
  24. handlers = hash[key]
  25. if (_.isArray(handlers)) {
  26. for (i = 0, j = handlers.length; i < j; i++) {
  27. register(vm, action, key, handlers[i])
  28. }
  29. } else {
  30. register(vm, action, key, handlers)
  31. }
  32. }
  33. }
  34. /**
  35. * Helper to register an event/watch callback.
  36. *
  37. * @param {Vue} vm
  38. * @param {String} action
  39. * @param {String} key
  40. * @param {Function|String|Object} handler
  41. * @param {Object} [options]
  42. */
  43. function register (vm, action, key, handler, options) {
  44. var type = typeof handler
  45. if (type === 'function') {
  46. vm[action](key, handler, options)
  47. } else if (type === 'string') {
  48. var methods = vm.$options.methods
  49. var method = methods && methods[handler]
  50. if (method) {
  51. vm[action](key, method, options)
  52. } else {
  53. _.warn(
  54. 'Unknown method: "' + handler + '" when ' +
  55. 'registering callback for ' + action +
  56. ': "' + key + '".'
  57. )
  58. }
  59. } else if (handler && type === 'object') {
  60. register(vm, action, key, handler.handler, handler)
  61. }
  62. }
  63. /**
  64. * Setup recursive attached/detached calls
  65. */
  66. exports._initDOMHooks = function () {
  67. this.$on('hook:attached', onAttached)
  68. this.$on('hook:detached', onDetached)
  69. }
  70. /**
  71. * Callback to recursively call attached hook on children
  72. */
  73. function onAttached () {
  74. if (!this._isAttached) {
  75. this._isAttached = true
  76. this.$children.forEach(callAttach)
  77. }
  78. }
  79. /**
  80. * Iterator to call attached hook
  81. *
  82. * @param {Vue} child
  83. */
  84. function callAttach (child) {
  85. if (!child._isAttached && inDoc(child.$el)) {
  86. child._callHook('attached')
  87. }
  88. }
  89. /**
  90. * Callback to recursively call detached hook on children
  91. */
  92. function onDetached () {
  93. if (this._isAttached) {
  94. this._isAttached = false
  95. this.$children.forEach(callDetach)
  96. }
  97. }
  98. /**
  99. * Iterator to call detached hook
  100. *
  101. * @param {Vue} child
  102. */
  103. function callDetach (child) {
  104. if (child._isAttached && !inDoc(child.$el)) {
  105. child._callHook('detached')
  106. }
  107. }
  108. /**
  109. * Trigger all handlers for a hook
  110. *
  111. * @param {String} hook
  112. */
  113. exports._callHook = function (hook) {
  114. var handlers = this.$options[hook]
  115. if (handlers) {
  116. for (var i = 0, j = handlers.length; i < j; i++) {
  117. handlers[i].call(this)
  118. }
  119. }
  120. this.$emit('hook:' + hook)
  121. }