Browse Source

better dep parsing

Evan You 13 năm trước cách đây
mục cha
commit
c4f31a5d65
4 tập tin đã thay đổi với 71 bổ sung48 xóa
  1. 0 4
      TODO.md
  2. 4 7
      examples/todos.html
  3. 51 30
      src/directive-parser.js
  4. 16 7
      src/seed.js

+ 0 - 4
TODO.md

@@ -1,9 +1,5 @@
-- complete arrayWatcher
-
 - computed properties (through invoking functions, need to rework the setter triggering mechanism using emitter)
 - computed properties (through invoking functions, need to rework the setter triggering mechanism using emitter)
 
 
-- the data object passed in should become an absolute source of truth, so multiple controllers can bind to the same data (i.e. second seed using it should insert dependency instead of overwriting it)
-
 - nested properties in scope (kinda hard but try)
 - nested properties in scope (kinda hard but try)
 
 
 - parse textNodes
 - parse textNodes

+ 4 - 7
examples/todos.html

@@ -62,7 +62,7 @@
                 { text: 'parse textnodes', done: false }
                 { text: 'parse textnodes', done: false }
             ]
             ]
 
 
-            Seed.controller('Todos', function (scope, seed) {
+            Seed.controller('Todos', function (scope) {
 
 
                 // regular properties
                 // regular properties
                 scope.todos = todos
                 scope.todos = todos
@@ -82,13 +82,10 @@
 
 
                 // event handlers
                 // event handlers
                 scope.addTodo = function (e) {
                 scope.addTodo = function (e) {
-                    var text = e.el.value
-                    if (text) {
+                    var val = e.el.value
+                    if (val) {
                         e.el.value = ''
                         e.el.value = ''
-                        scope.todos.push({
-                            text: text,
-                            done: false
-                        })
+                        scope.todos.unshift({ text: val, done: false })
                         scope.remaining++
                         scope.remaining++
                     }
                     }
                 }
                 }

+ 51 - 30
src/directive-parser.js

@@ -8,6 +8,46 @@ var KEY_RE          = /^[^\|<]+/,
     FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
     FILTER_TOKEN_RE = /[^\s']+|'[^']+'/g,
     DEPS_RE         = /<[^<\|]+/g
     DEPS_RE         = /<[^<\|]+/g
 
 
+// parse a key, extract argument and nesting/root info
+function parseKey (rawKey) {
+
+    var res = {},
+        argMatch = rawKey.match(ARG_RE)
+
+    res.key = argMatch
+        ? argMatch[2].trim()
+        : rawKey.trim()
+
+    res.arg = argMatch
+        ? argMatch[1].trim()
+        : null
+
+    var nesting = res.key.match(/^\^+/)
+    res.nesting = nesting
+        ? nesting[0].length
+        : false
+
+    res.root = res.key.charAt(0) === '$'
+    return res
+}
+
+function parseFilter (filter) {
+
+    var tokens = filter.slice(1)
+        .match(FILTER_TOKEN_RE)
+        .map(function (token) {
+            return token.replace(/'/g, '').trim()
+        })
+
+    return {
+        name  : tokens[0],
+        apply : filters[tokens[0]],
+        args  : tokens.length > 1
+                ? tokens.slice(1)
+                : null
+    }
+}
+
 function Directive (directiveName, expression) {
 function Directive (directiveName, expression) {
 
 
     var directive = directives[directiveName]
     var directive = directives[directiveName]
@@ -26,41 +66,22 @@ function Directive (directiveName, expression) {
     this.directiveName = directiveName
     this.directiveName = directiveName
     this.expression = expression
     this.expression = expression
 
 
-    var rawKey   = expression.match(KEY_RE)[0], // guarded in parse
-        argMatch = rawKey.match(ARG_RE)
-
-    this.key = argMatch
-        ? argMatch[2].trim()
-        : rawKey.trim()
+    var rawKey   = expression.match(KEY_RE)[0],
+        keyInfo  = parseKey(rawKey)
 
 
-    this.arg = argMatch
-        ? argMatch[1].trim()
-        : null
+    for (var prop in keyInfo) {
+        this[prop] = keyInfo[prop]
+    }
     
     
     var filterExps = expression.match(FILTERS_RE)
     var filterExps = expression.match(FILTERS_RE)
-    if (filterExps) {
-        this.filters = filterExps.map(function (filter) {
-            var tokens = filter.slice(1)
-                .match(FILTER_TOKEN_RE)
-                .map(function (token) {
-                    return token.replace(/'/g, '').trim()
-                })
-            return {
-                name  : tokens[0],
-                apply : filters[tokens[0]],
-                args  : tokens.length > 1
-                        ? tokens.slice(1)
-                        : null
-            }
-        })
-    } else {
-        this.filters = null
-    }
+    this.filters = filterExps
+        ? filterExps.map(parseFilter)
+        : null
 
 
     var depExp = expression.match(DEPS_RE)
     var depExp = expression.match(DEPS_RE)
-    if (depExp) {
-        this.deps = depExp[0].slice(1).trim().split(/\s+/)
-    }
+    this.deps = depExp
+        ? depExp[0].slice(1).trim().split(/\s+/).map(parseKey)
+        : null
 }
 }
 
 
 Directive.prototype.update = function (value) {
 Directive.prototype.update = function (value) {

+ 16 - 7
src/seed.js

@@ -25,17 +25,19 @@ function Seed (el, options) {
 
 
     // initialize the scope object
     // initialize the scope object
     var dataPrefix = config.prefix + '-data'
     var dataPrefix = config.prefix + '-data'
-    this.scope =
+    var scope = this.scope =
             (options && options.data)
             (options && options.data)
             || config.datum[el.getAttribute(dataPrefix)]
             || config.datum[el.getAttribute(dataPrefix)]
             || {}
             || {}
     el.removeAttribute(dataPrefix)
     el.removeAttribute(dataPrefix)
 
 
-    this.scope.$seed    = this
-    this.scope.$destroy = this._destroy.bind(this)
-    this.scope.$dump    = this._dump.bind(this)
-    this.scope.$index   = options.index
-    this.scope.$parent  = options.parentSeed && options.parentSeed.scope
+    scope.$seed     = this
+    scope.$destroy  = this._destroy.bind(this)
+    scope.$dump     = this._dump.bind(this)
+    scope.$on       = this.on.bind(this)
+    scope.$emit     = this.emit.bind(this)
+    scope.$index    = options.index
+    scope.$parent   = options.parentSeed && options.parentSeed.scope
 
 
     // revursively process nodes for directives
     // revursively process nodes for directives
     this._compileNode(el, true)
     this._compileNode(el, true)
@@ -46,7 +48,7 @@ function Seed (el, options) {
         el.removeAttribute(ctrlAttr)
         el.removeAttribute(ctrlAttr)
         var controller = config.controllers[ctrlID]
         var controller = config.controllers[ctrlID]
         if (controller) {
         if (controller) {
-            controller.call(this, this.scope, this)
+            controller.call(this, this.scope)
         } else {
         } else {
             console.warn('controller ' + ctrlID + ' is not defined.')
             console.warn('controller ' + ctrlID + ' is not defined.')
         }
         }
@@ -151,6 +153,13 @@ Seed.prototype._bind = function (node, directive) {
 
 
     directive.key = key
     directive.key = key
 
 
+    // computed properties
+    if (directive.deps) {
+        directive.deps.forEach(function (dep) {
+            console.log(dep)
+        })
+    }
+
     var binding = scopeOwner._bindings[key] || scopeOwner._createBinding(key)
     var binding = scopeOwner._bindings[key] || scopeOwner._createBinding(key)
 
 
     // add directive to this binding
     // add directive to this binding