Procházet zdrojové kódy

better unbind/destroy

Evan You před 12 roky
rodič
revize
6d81bff63a
7 změnil soubory, kde provedl 61 přidání a 59 odebrání
  1. 0 0
      examples/nested.html
  2. 3 5
      examples/todos.html
  3. 4 1
      src/config.js
  4. 14 11
      src/directives.js
  5. 10 3
      src/filters.js
  6. 10 28
      src/main.js
  7. 20 11
      src/seed.js

+ 0 - 0
dev/nested.html → examples/nested.html


+ 3 - 5
dev/todos.html → examples/todos.html

@@ -29,7 +29,7 @@
         </style>
     </head>
     <body>
-        <div id="app" sd-controller="Todos" sd-data="test" sd-class="filter">
+        <div id="app" sd-controller="Todos" sd-class="filter">
             <div>
                 <input placeholder="What needs to be done?" sd-on="change:addTodo">
             </div>
@@ -62,12 +62,10 @@
                 { text: 'parse textnodes', done: false }
             ]
 
-            Seed.data('test', { todos: todos })
-
             Seed.controller('Todos', function (scope, seed) {
 
                 // regular properties
-                // scope.todos = todos
+                scope.todos = todos
                 scope.filter = 'all'
                 scope.remaining = todos.reduce(function (count, todo) {
                     return count + (todo.done ? 0 : 1)
@@ -110,7 +108,7 @@
 
             })
 
-            Seed.bootstrap()
+            var app = Seed.bootstrap()
 
         </script>
     </body>

+ 4 - 1
src/config.js

@@ -1,3 +1,6 @@
 module.exports = {
-    prefix: 'sd'
+    prefix: 'sd',
+    controllers: {},
+    datum: {},
+    seeds: {}
 }

+ 14 - 11
src/directives.js

@@ -52,7 +52,7 @@ module.exports = {
                         el            : e.currentTarget,
                         originalEvent : e,
                         directive     : self,
-                        seed          : self.seed
+                        seed          : e.currentTarget.seed
                     })
                 }
                 this.el.addEventListener(event, proxy)
@@ -77,12 +77,8 @@ module.exports = {
             this.childSeeds = []
         },
         update: function (collection) {
-            if (this.childSeeds.length) {
-                this.childSeeds.forEach(function (child) {
-                    child.destroy()
-                })
-                this.childSeeds = []
-            }
+            this.unbind(true)
+            this.childSeeds = []
             if (!Array.isArray(collection)) return
             watchArray(collection, this.mutate.bind(this))
             var self = this
@@ -90,9 +86,6 @@ module.exports = {
                 self.childSeeds.push(self.buildItem(item, i, collection))
             })
         },
-        mutate: function (mutation) {
-            console.log(mutation)
-        },
         buildItem: function (data, index, collection) {
             var Seed = require('./seed'),
                 node = this.el.cloneNode(true)
@@ -100,12 +93,22 @@ module.exports = {
                     eachPrefixRE: new RegExp('^' + this.arg + '.'),
                     parentSeed: this.seed,
                     index: index,
-                    eachCollection: collection,
                     data: data
                 })
             this.container.insertBefore(node, this.marker)
             collection[index] = spore.scope
             return spore
+        },
+        mutate: function (mutation) {
+            console.log(mutation)
+        },
+        unbind: function (rm) {
+            if (this.childSeeds.length) {
+                var fn = rm ? 'destroy' : 'unbind'
+                this.childSeeds.forEach(function (child) {
+                    child[fn]()
+                })
+            }
         }
     }
 

+ 10 - 3
src/filters.js

@@ -9,11 +9,18 @@ module.exports = {
         return value.toString().toUpperCase()
     },
 
+    // TODO probably there's a better way.
+    // Angular doesn't support delegation either
+    // any real performance gain?
     delegate: function (handler, args) {
         var selector = args[0]
         return function (e) {
-            if (delegateCheck(e.target, e.currentTarget, selector)) {
-                handler.apply(this, arguments)
+            var oe = e.originalEvent,
+                target = delegateCheck(oe.target, oe.currentTarget, selector)
+            if (target) {
+                e.el = target
+                e.seed = target.seed
+                handler.call(this, e)
             }
         }
     }
@@ -22,7 +29,7 @@ module.exports = {
 
 function delegateCheck (current, top, selector) {
     if (current.webkitMatchesSelector(selector)) {
-        return true
+        return current
     } else if (current === top) {
         return false
     } else {

+ 10 - 28
src/main.js

@@ -3,30 +3,12 @@ var config      = require('./config'),
     directives  = require('./directives'),
     filters     = require('./filters')
 
-var controllers = config.controllers = {},
-    datum       = config.datum = {},
+var controllers = config.controllers,
+    datum       = config.datum,
     api         = {}
 
 // API
 
-api.extend = function (opts) {
-    var Spore = function () {
-        Seed.apply(this, arguments)
-        for (var prop in this.extensions) {
-            var ext = this.extensions[prop]
-            this.scope[prop] = (typeof ext === 'function')
-                ? ext.bind(this)
-                : ext
-        }
-    }
-    Spore.prototype = Object.create(Seed.prototype)
-    Spore.prototype.extensions = {}
-    for (var prop in opts) {
-        Spore.prototype.extensions[prop] = opts[prop]
-    }
-    return Spore
-}
-
 api.data = function (id, data) {
     if (!data) return datum[id]
     if (datum[id]) {
@@ -43,6 +25,14 @@ api.controller = function (id, extensions) {
     controllers[id] = extensions
 }
 
+api.directive = function (name, fn) {
+    directives[name] = fn
+}
+
+api.filter = function (name, fn) {
+    filters[name] = fn
+}
+
 api.bootstrap = function (opts) {
     if (opts) {
         config.prefix = opts.prefix || config.prefix
@@ -60,12 +50,4 @@ api.bootstrap = function (opts) {
     return n > 1 ? app : seed
 }
 
-api.directive = function (name, fn) {
-    directives[name] = fn
-}
-
-api.filter = function (name, fn) {
-    filters[name] = fn
-}
-
 module.exports = api

+ 20 - 11
src/seed.js

@@ -14,9 +14,9 @@ function Seed (el, options) {
         el = document.querySelector(el)
     }
 
-    el.seed        = this
-    this.el        = el
-    this._bindings = {}
+    el.seed         = this
+    this.el         = el
+    this._bindings  = {}
 
     // copy options
     if (options) {
@@ -51,8 +51,6 @@ function Seed (el, options) {
     }
 }
 
-Emitter(Seed.prototype)
-
 Seed.prototype._compileNode = function (node, root) {
     var self = this
 
@@ -190,17 +188,28 @@ Seed.prototype._createBinding = function (key) {
     return binding
 }
 
-Seed.prototype.destroy = function () {
+Seed.prototype.unbind = function () {
+    var unbind = function (instance) {
+        if (instance.unbind) {
+            instance.unbind()
+        }
+    }
     for (var key in this._bindings) {
         this._bindings[key].instances.forEach(unbind)
-        ;delete this._bindings[key]
     }
+    this.childSeeds.forEach(function (child) {
+        child.unbind()
+    })
+}
+
+Seed.prototype.destroy = function () {
+    this.unbind()
     this.el.parentNode.removeChild(this.el)
-    function unbind (instance) {
-        if (instance.unbind) {
-            instance.unbind()
-        }
+    if (this.parentSeed && this.id) {
+        delete this.parentSeed['$' + this.id]
     }
 }
 
+Emitter(Seed.prototype)
+
 module.exports = Seed