github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/instance/internal/lifecycle.js (about) 1 import Directive from '../../directive' 2 3 import { 4 replace, 5 getAttr, 6 isFragment 7 } from '../../util/index' 8 9 import { 10 compile, 11 compileRoot, 12 transclude, 13 resolveSlots 14 } from '../../compiler/index' 15 16 export default function (Vue) { 17 /** 18 * Update v-ref for component. 19 * 20 * @param {Boolean} remove 21 */ 22 23 Vue.prototype._updateRef = function (remove) { 24 var ref = this.$options._ref 25 if (ref) { 26 var refs = (this._scope || this._context).$refs 27 if (remove) { 28 if (refs[ref] === this) { 29 refs[ref] = null 30 } 31 } else { 32 refs[ref] = this 33 } 34 } 35 } 36 37 /** 38 * Transclude, compile and link element. 39 * 40 * If a pre-compiled linker is available, that means the 41 * passed in element will be pre-transcluded and compiled 42 * as well - all we need to do is to call the linker. 43 * 44 * Otherwise we need to call transclude/compile/link here. 45 * 46 * @param {Element} el 47 */ 48 49 Vue.prototype._compile = function (el) { 50 var options = this.$options 51 52 // transclude and init element 53 // transclude can potentially replace original 54 // so we need to keep reference; this step also injects 55 // the template and caches the original attributes 56 // on the container node and replacer node. 57 var original = el 58 el = transclude(el, options) 59 this._initElement(el) 60 61 // handle v-pre on root node (#2026) 62 if (el.nodeType === 1 && getAttr(el, 'v-pre') !== null) { 63 return 64 } 65 66 // root is always compiled per-instance, because 67 // container attrs and props can be different every time. 68 var contextOptions = this._context && this._context.$options 69 var rootLinker = compileRoot(el, options, contextOptions) 70 71 // resolve slot distribution 72 resolveSlots(this, options._content) 73 74 // compile and link the rest 75 var contentLinkFn 76 var ctor = this.constructor 77 // component compilation can be cached 78 // as long as it's not using inline-template 79 if (options._linkerCachable) { 80 contentLinkFn = ctor.linker 81 if (!contentLinkFn) { 82 contentLinkFn = ctor.linker = compile(el, options) 83 } 84 } 85 86 // link phase 87 // make sure to link root with prop scope! 88 var rootUnlinkFn = rootLinker(this, el, this._scope) 89 var contentUnlinkFn = contentLinkFn 90 ? contentLinkFn(this, el) 91 : compile(el, options)(this, el) 92 93 // register composite unlink function 94 // to be called during instance destruction 95 this._unlinkFn = function () { 96 rootUnlinkFn() 97 // passing destroying: true to avoid searching and 98 // splicing the directives 99 contentUnlinkFn(true) 100 } 101 102 // finally replace original 103 if (options.replace) { 104 replace(original, el) 105 } 106 107 this._isCompiled = true 108 this._callHook('compiled') 109 } 110 111 /** 112 * Initialize instance element. Called in the public 113 * $mount() method. 114 * 115 * @param {Element} el 116 */ 117 118 Vue.prototype._initElement = function (el) { 119 if (isFragment(el)) { 120 this._isFragment = true 121 this.$el = this._fragmentStart = el.firstChild 122 this._fragmentEnd = el.lastChild 123 // set persisted text anchors to empty 124 if (this._fragmentStart.nodeType === 3) { 125 this._fragmentStart.data = this._fragmentEnd.data = '' 126 } 127 this._fragment = el 128 } else { 129 this.$el = el 130 } 131 this.$el.__vue__ = this 132 this._callHook('beforeCompile') 133 } 134 135 /** 136 * Create and bind a directive to an element. 137 * 138 * @param {Object} descriptor - parsed directive descriptor 139 * @param {Node} node - target node 140 * @param {Vue} [host] - transclusion host component 141 * @param {Object} [scope] - v-for scope 142 * @param {Fragment} [frag] - owner fragment 143 */ 144 145 Vue.prototype._bindDir = function (descriptor, node, host, scope, frag) { 146 this._directives.push( 147 new Directive(descriptor, this, node, host, scope, frag) 148 ) 149 } 150 151 /** 152 * Teardown an instance, unobserves the data, unbind all the 153 * directives, turn off all the event listeners, etc. 154 * 155 * @param {Boolean} remove - whether to remove the DOM node. 156 * @param {Boolean} deferCleanup - if true, defer cleanup to 157 * be called later 158 */ 159 160 Vue.prototype._destroy = function (remove, deferCleanup) { 161 if (this._isBeingDestroyed) { 162 if (!deferCleanup) { 163 this._cleanup() 164 } 165 return 166 } 167 168 var destroyReady 169 var pendingRemoval 170 171 var self = this 172 // Cleanup should be called either synchronously or asynchronoysly as 173 // callback of this.$remove(), or if remove and deferCleanup are false. 174 // In any case it should be called after all other removing, unbinding and 175 // turning of is done 176 var cleanupIfPossible = function () { 177 if (destroyReady && !pendingRemoval && !deferCleanup) { 178 self._cleanup() 179 } 180 } 181 182 // remove DOM element 183 if (remove && this.$el) { 184 pendingRemoval = true 185 this.$remove(function () { 186 pendingRemoval = false 187 cleanupIfPossible() 188 }) 189 } 190 191 this._callHook('beforeDestroy') 192 this._isBeingDestroyed = true 193 var i 194 // remove self from parent. only necessary 195 // if parent is not being destroyed as well. 196 var parent = this.$parent 197 if (parent && !parent._isBeingDestroyed) { 198 parent.$children.$remove(this) 199 // unregister ref (remove: true) 200 this._updateRef(true) 201 } 202 // destroy all children. 203 i = this.$children.length 204 while (i--) { 205 this.$children[i].$destroy() 206 } 207 // teardown props 208 if (this._propsUnlinkFn) { 209 this._propsUnlinkFn() 210 } 211 // teardown all directives. this also tearsdown all 212 // directive-owned watchers. 213 if (this._unlinkFn) { 214 this._unlinkFn() 215 } 216 i = this._watchers.length 217 while (i--) { 218 this._watchers[i].teardown() 219 } 220 // remove reference to self on $el 221 if (this.$el) { 222 this.$el.__vue__ = null 223 } 224 225 destroyReady = true 226 cleanupIfPossible() 227 } 228 229 /** 230 * Clean up to ensure garbage collection. 231 * This is called after the leave transition if there 232 * is any. 233 */ 234 235 Vue.prototype._cleanup = function () { 236 if (this._isDestroyed) { 237 return 238 } 239 // remove self from owner fragment 240 // do it in cleanup so that we can call $destroy with 241 // defer right when a fragment is about to be removed. 242 if (this._frag) { 243 this._frag.children.$remove(this) 244 } 245 // remove reference from data ob 246 // frozen object may not have observer. 247 if (this._data && this._data.__ob__) { 248 this._data.__ob__.removeVm(this) 249 } 250 // Clean up references to private properties and other 251 // instances. preserve reference to _data so that proxy 252 // accessors still work. The only potential side effect 253 // here is that mutating the instance after it's destroyed 254 // may affect the state of other components that are still 255 // observing the same object, but that seems to be a 256 // reasonable responsibility for the user rather than 257 // always throwing an error on them. 258 this.$el = 259 this.$parent = 260 this.$root = 261 this.$children = 262 this._watchers = 263 this._context = 264 this._scope = 265 this._directives = null 266 // call the last hook... 267 this._isDestroyed = true 268 this._callHook('destroyed') 269 // turn off all instance listeners. 270 this.$off() 271 } 272 }