Jelajahi Sumber

fragment abstraction

Evan You 10 tahun lalu
induk
melakukan
c2533a56e4
3 mengubah file dengan 95 tambahan dan 48 penghapusan
  1. 17 48
      src/fast-repeat.js
  2. 47 0
      src/fragment/factory.js
  3. 31 0
      src/fragment/fragment.js

+ 17 - 48
src/fast-repeat.js

@@ -1,6 +1,7 @@
 var _ = require('./util')
 var compiler = require('./compiler')
 var templateParser = require('./parsers/template')
+var FragmentFactory = require('./fragment/factory')
 
 module.exports = {
 
@@ -10,72 +11,40 @@ module.exports = {
       this.arg = inMatch[1]
       this._watcherExp = inMatch[2]
     }
-
     this.start = _.createAnchor('fast-repeat-start')
     this.end = _.createAnchor('fast-repeat-end')
     _.replace(this.el, this.end)
     _.before(this.start, this.end)
+    // fragment factory
+    this.factory = new FragmentFactory(this.vm, this.el)
+  },
 
-    var vm = this.vm
-    var template = _.isTemplate(this.el)
-      ? templateParser.parse(this.el, true)
-      : this.el
-    var linker = compiler.compile(template, vm.$options, true)
+  create: function (data) {
+    var host = this._host
     var parentScope = this._scope || this.vm
+    var scope = Object.create(parentScope)
     var alias = this.arg
-    var host = this._host
-    this.create = function (data) {
-      var el = templateParser.clone(template)
-      var scope = Object.create(parentScope)
-      Object.defineProperty(scope, alias, {
-        enumberable: true,
-        configurable: true,
-        value: data
-      })
-      var unlink = linker(vm, el, host, scope)
-      return new Fragment(el, unlink)
-    }
+    Object.defineProperty(scope, alias, {
+      enumberable: true,
+      configurable: true,
+      value: data
+    })
+    return this.factory.create(host, scope)
   },
 
   update: function (list) {
-    if (!list) debugger
+    var self = this
     var anchor = this.end
     if (this.frags) {
       this.frags.forEach(function (f) {
         f.destroy()
       })
     }
-    this.frags = list.map(this.create)
+    this.frags = list.map(function (data) {
+      return self.create(data)
+    })
     this.frags.forEach(function (f) {
       f.before(anchor)
     })
   }
 }
-
-function Fragment (el, unlink) {
-  this.start = _.createAnchor('fragment')
-  this.end = _.createAnchor('fragment')
-  this.frag = el
-  this.unlink = unlink
-}
-
-Fragment.prototype.before = function (target) {
-  _.before(this.start, target)
-  _.before(this.frag, target)
-  _.before(this.end, target)
-}
-
-Fragment.prototype.remove = function () {
-  var parent = this.start.parentNode
-  var node = this.start.nextSibling
-  while (node !== this.end) {
-    this.frag.appendChild(node)
-  }
-  parent.removeChild(this.start)
-  parent.removeChild(this.end)
-}
-
-Fragment.prototype.destroy = function () {
-  this.remove()
-  this.unlink()
-}

+ 47 - 0
src/fragment/factory.js

@@ -0,0 +1,47 @@
+var _ = require('../util')
+var compiler = require('../compiler')
+var templateParser = require('../parsers/template')
+var Fragment = require('./fragment')
+var Cache = require('../cache')
+var linkerCache = new Cache(5000)
+
+/**
+ * A factory that can be used to create instances of a
+ * fragment. Caches the compiled linker if possible.
+ *
+ * @param {Vue} vm
+ * @param {Element} el
+ */
+
+function FragmentFactory (vm, el) {
+  this.vm = vm
+  var template = this.template = _.isTemplate(el)
+    ? templateParser.parse(el, true)
+    : el
+  // linker can be cached, but only for components
+  var linker
+  var cid = vm.constructor.cid
+  if (cid > 0) {
+    var cacheId = cid + el.outerHTML
+    linker = linkerCache.get(cacheId)
+    if (!linker) {
+      linker = compiler.compile(template, vm.$options, true)
+      linkerCache.put(cacheId, linker)
+    }
+  } else {
+    linker = compiler.compile(template, vm.$options, true)
+  }
+  this.linker = linker
+}
+
+/**
+ * Create a fragment instance with given host and scope.
+ */
+
+FragmentFactory.prototype.create = function (host, scope) {
+  var el = templateParser.clone(this.template)
+  var unlink = this.linker(this.vm, el, host, scope)
+  return new Fragment(el, unlink)
+}
+
+module.exports  = FragmentFactory

+ 31 - 0
src/fragment/fragment.js

@@ -0,0 +1,31 @@
+var _ = require('../util')
+
+function Fragment (el, unlink) {
+  this.start = _.createAnchor('fragment')
+  this.end = _.createAnchor('fragment')
+  this.frag = el
+  this.unlink = unlink
+}
+
+Fragment.prototype.before = function (target) {
+  _.before(this.start, target)
+  _.before(this.frag, target)
+  _.before(this.end, target)
+}
+
+Fragment.prototype.remove = function () {
+  var parent = this.start.parentNode
+  var node = this.start.nextSibling
+  while (node !== this.end) {
+    this.frag.appendChild(node)
+  }
+  parent.removeChild(this.start)
+  parent.removeChild(this.end)
+}
+
+Fragment.prototype.destroy = function () {
+  this.remove()
+  this.unlink()
+}
+
+module.exports = Fragment