github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/vue-1.0.24/src/fragment/fragment.js (about)

     1  import {
     2    createAnchor,
     3    before,
     4    prepend,
     5    inDoc,
     6    mapNodeRange,
     7    removeNodeRange
     8  } from '../util/index'
     9  
    10  import {
    11    beforeWithTransition,
    12    removeWithTransition
    13  } from '../transition/index'
    14  
    15  /**
    16   * Abstraction for a partially-compiled fragment.
    17   * Can optionally compile content with a child scope.
    18   *
    19   * @param {Function} linker
    20   * @param {Vue} vm
    21   * @param {DocumentFragment} frag
    22   * @param {Vue} [host]
    23   * @param {Object} [scope]
    24   * @param {Fragment} [parentFrag]
    25   */
    26  
    27  export default function Fragment (linker, vm, frag, host, scope, parentFrag) {
    28    this.children = []
    29    this.childFrags = []
    30    this.vm = vm
    31    this.scope = scope
    32    this.inserted = false
    33    this.parentFrag = parentFrag
    34    if (parentFrag) {
    35      parentFrag.childFrags.push(this)
    36    }
    37    this.unlink = linker(vm, frag, host, scope, this)
    38    var single = this.single =
    39      frag.childNodes.length === 1 &&
    40      // do not go single mode if the only node is an anchor
    41      !(frag.childNodes[0].__v_anchor)
    42    if (single) {
    43      this.node = frag.childNodes[0]
    44      this.before = singleBefore
    45      this.remove = singleRemove
    46    } else {
    47      this.node = createAnchor('fragment-start')
    48      this.end = createAnchor('fragment-end')
    49      this.frag = frag
    50      prepend(this.node, frag)
    51      frag.appendChild(this.end)
    52      this.before = multiBefore
    53      this.remove = multiRemove
    54    }
    55    this.node.__v_frag = this
    56  }
    57  
    58  /**
    59   * Call attach/detach for all components contained within
    60   * this fragment. Also do so recursively for all child
    61   * fragments.
    62   *
    63   * @param {Function} hook
    64   */
    65  
    66  Fragment.prototype.callHook = function (hook) {
    67    var i, l
    68    for (i = 0, l = this.childFrags.length; i < l; i++) {
    69      this.childFrags[i].callHook(hook)
    70    }
    71    for (i = 0, l = this.children.length; i < l; i++) {
    72      hook(this.children[i])
    73    }
    74  }
    75  
    76  /**
    77   * Insert fragment before target, single node version
    78   *
    79   * @param {Node} target
    80   * @param {Boolean} withTransition
    81   */
    82  
    83  function singleBefore (target, withTransition) {
    84    this.inserted = true
    85    var method = withTransition !== false
    86      ? beforeWithTransition
    87      : before
    88    method(this.node, target, this.vm)
    89    if (inDoc(this.node)) {
    90      this.callHook(attach)
    91    }
    92  }
    93  
    94  /**
    95   * Remove fragment, single node version
    96   */
    97  
    98  function singleRemove () {
    99    this.inserted = false
   100    var shouldCallRemove = inDoc(this.node)
   101    var self = this
   102    this.beforeRemove()
   103    removeWithTransition(this.node, this.vm, function () {
   104      if (shouldCallRemove) {
   105        self.callHook(detach)
   106      }
   107      self.destroy()
   108    })
   109  }
   110  
   111  /**
   112   * Insert fragment before target, multi-nodes version
   113   *
   114   * @param {Node} target
   115   * @param {Boolean} withTransition
   116   */
   117  
   118  function multiBefore (target, withTransition) {
   119    this.inserted = true
   120    var vm = this.vm
   121    var method = withTransition !== false
   122      ? beforeWithTransition
   123      : before
   124    mapNodeRange(this.node, this.end, function (node) {
   125      method(node, target, vm)
   126    })
   127    if (inDoc(this.node)) {
   128      this.callHook(attach)
   129    }
   130  }
   131  
   132  /**
   133   * Remove fragment, multi-nodes version
   134   */
   135  
   136  function multiRemove () {
   137    this.inserted = false
   138    var self = this
   139    var shouldCallRemove = inDoc(this.node)
   140    this.beforeRemove()
   141    removeNodeRange(this.node, this.end, this.vm, this.frag, function () {
   142      if (shouldCallRemove) {
   143        self.callHook(detach)
   144      }
   145      self.destroy()
   146    })
   147  }
   148  
   149  /**
   150   * Prepare the fragment for removal.
   151   */
   152  
   153  Fragment.prototype.beforeRemove = function () {
   154    var i, l
   155    for (i = 0, l = this.childFrags.length; i < l; i++) {
   156      // call the same method recursively on child
   157      // fragments, depth-first
   158      this.childFrags[i].beforeRemove(false)
   159    }
   160    for (i = 0, l = this.children.length; i < l; i++) {
   161      // Call destroy for all contained instances,
   162      // with remove:false and defer:true.
   163      // Defer is necessary because we need to
   164      // keep the children to call detach hooks
   165      // on them.
   166      this.children[i].$destroy(false, true)
   167    }
   168    var dirs = this.unlink.dirs
   169    for (i = 0, l = dirs.length; i < l; i++) {
   170      // disable the watchers on all the directives
   171      // so that the rendered content stays the same
   172      // during removal.
   173      dirs[i]._watcher && dirs[i]._watcher.teardown()
   174    }
   175  }
   176  
   177  /**
   178   * Destroy the fragment.
   179   */
   180  
   181  Fragment.prototype.destroy = function () {
   182    if (this.parentFrag) {
   183      this.parentFrag.childFrags.$remove(this)
   184    }
   185    this.node.__v_frag = null
   186    this.unlink()
   187  }
   188  
   189  /**
   190   * Call attach hook for a Vue instance.
   191   *
   192   * @param {Vue} child
   193   */
   194  
   195  function attach (child) {
   196    if (!child._isAttached && inDoc(child.$el)) {
   197      child._callHook('attached')
   198    }
   199  }
   200  
   201  /**
   202   * Call detach hook for a Vue instance.
   203   *
   204   * @param {Vue} child
   205   */
   206  
   207  function detach (child) {
   208    if (child._isAttached && !inDoc(child.$el)) {
   209      child._callHook('detached')
   210    }
   211  }