lifecycle.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. var _ = require('../util')
  2. var compile = require('../compile/compile')
  3. var transclude = require('../compile/transclude')
  4. /**
  5. * Set instance target element and kick off the compilation
  6. * process. The passed in `el` can be a selector string, an
  7. * existing Element, or a DocumentFragment (for block
  8. * instances).
  9. *
  10. * @param {Element|DocumentFragment|string} el
  11. * @public
  12. */
  13. exports.$mount = function (el) {
  14. if (this._isCompiled) {
  15. _.warn('$mount() should be called only once.')
  16. return
  17. }
  18. this._callHook('beforeCompile')
  19. var options = this.$options
  20. if (options._linker) {
  21. // pre-compiled linker. this means the element has
  22. // been trancluded and compiled. just link it.
  23. this._initElement(el)
  24. options._linker(this, el)
  25. } else {
  26. el = transclude(el, options)
  27. this._initElement(el)
  28. var linker = compile(el, options)
  29. linker(this, el)
  30. }
  31. this._callHook('compiled')
  32. if (_.inDoc(this.$el)) {
  33. this._callHook('attached')
  34. ready.call(this)
  35. } else {
  36. this.$once('hook:attached', ready)
  37. }
  38. }
  39. /**
  40. * Initialize instance element. Called in the public
  41. * $mount() method.
  42. *
  43. * @param {Element} el
  44. */
  45. exports._initElement = function (el) {
  46. if (el instanceof DocumentFragment) {
  47. this._isBlock = true
  48. this.$el = this._blockStart = el.firstChild
  49. this._blockEnd = el.lastChild
  50. this._blockFragment = el
  51. } else {
  52. this.$el = el
  53. }
  54. this.$el.__vue__ = this
  55. }
  56. /**
  57. * Mark an instance as ready.
  58. */
  59. function ready () {
  60. this._isAttached = true
  61. this._isReady = true
  62. this._callHook('ready')
  63. this._initDOMHooks()
  64. }
  65. /**
  66. * Teardown an instance, unobserves the data, unbind all the
  67. * directives, turn off all the event listeners, etc.
  68. *
  69. * @param {Boolean} remove - whether to remove the DOM node.
  70. * @public
  71. */
  72. exports.$destroy = function (remove) {
  73. if (this._isDestroyed) {
  74. return
  75. }
  76. this._callHook('beforeDestroy')
  77. // remove DOM element
  78. if (remove) {
  79. if (this.$el === document.body) {
  80. this.$el.innerHTML = ''
  81. } else {
  82. this.$remove()
  83. }
  84. }
  85. var i
  86. // remove self from parent. only necessary
  87. // if this is called by the user.
  88. var parent = this.$parent
  89. if (parent && !parent._isDestroyed) {
  90. i = parent._children.indexOf(this)
  91. parent._children.splice(i)
  92. }
  93. // destroy all children.
  94. if (this._children) {
  95. i = this._children.length
  96. while (i--) {
  97. this._children[i].$destroy()
  98. }
  99. }
  100. // teardown all directives. this also tearsdown all
  101. // directive-owned watchers.
  102. i = this._directives.length
  103. while (i--) {
  104. this._directives[i]._teardown()
  105. }
  106. // teardown all user watchers.
  107. for (i in this._userWatchers) {
  108. this._userWatchers[i].teardown()
  109. }
  110. // clean up
  111. this._data =
  112. this._watchers =
  113. this._userWatchers =
  114. this._activeWatcher =
  115. this.$el =
  116. this.$el.__vue__ =
  117. this.$parent =
  118. this.$observer =
  119. this._children =
  120. this._bindings =
  121. this._directives = null
  122. // call the last hook...
  123. this._isDestroyed = true
  124. this._callHook('afterDestroy')
  125. // turn off all instance listeners.
  126. this.$off()
  127. }