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  }