Forráskód Böngészése

computed filters first pass

Evan You 12 éve
szülő
commit
4ebff990e3
3 módosított fájl, 47 hozzáadás és 17 törlés
  1. 8 5
      src/compiler.js
  2. 24 11
      src/directive.js
  3. 15 1
      src/exp-parser.js

+ 8 - 5
src/compiler.js

@@ -517,7 +517,7 @@ CompilerProto.bindDirective = function (directive) {
 
     if (directive.isExp) {
         // expression bindings are always created on current compiler
-        binding = compiler.createBinding(key, true, directive.isFn)
+        binding = compiler.createBinding(key, directive)
     } else {
         // recursively locate which compiler owns the binding
         while (compiler) {
@@ -545,18 +545,20 @@ CompilerProto.bindDirective = function (directive) {
 /**
  *  Create binding and attach getter/setter for a key to the viewmodel object
  */
-CompilerProto.createBinding = function (key, isExp, isFn) {
+CompilerProto.createBinding = function (key, directive) {
 
     utils.log('  created binding: ' + key)
 
     var compiler = this,
+        isExp    = directive && directive.isExp,
+        isFn     = directive && directive.isFn,
         bindings = compiler.bindings,
         computed = compiler.options.computed,
         binding  = new Binding(compiler, key, isExp, isFn)
 
     if (isExp) {
         // expression bindings are anonymous
-        compiler.defineExp(key, binding)
+        compiler.defineExp(key, binding, directive)
     } else {
         bindings[key] = binding
         if (binding.root) {
@@ -650,8 +652,9 @@ CompilerProto.defineMeta = function (key, binding) {
  *  Define an expression binding, which is essentially
  *  an anonymous computed property
  */
-CompilerProto.defineExp = function (key, binding) {
-    var getter = ExpParser.parse(key, this)
+CompilerProto.defineExp = function (key, binding, directive) {
+    var filters = directive && directive.computeFilters && directive.filters,
+        getter  = ExpParser.parse(key, this, null, filters)
     if (getter) {
         this.markComputed(binding, getter)
         this.exps.push(binding)

+ 24 - 11
src/directive.js

@@ -1,6 +1,5 @@
 var utils      = require('./utils'),
     directives = require('./directives'),
-    filters    = require('./filters'),
 
     // Regexes!
 
@@ -21,11 +20,13 @@ var utils      = require('./utils'),
  *  Directive class
  *  represents a single directive instance in the DOM
  */
-function Directive (definition, expression, rawKey, compiler, node) {
+function Directive (dirname, definition, expression, rawKey, compiler, node) {
 
-    this.compiler = compiler
-    this.vm       = compiler.vm
-    this.el       = node
+    this.name           = dirname
+    this.compiler       = compiler
+    this.vm             = compiler.vm
+    this.el             = node
+    this.computeFilters = false
 
     var isEmpty   = expression === ''
 
@@ -55,20 +56,32 @@ function Directive (definition, expression, rawKey, compiler, node) {
     ).trim()
     
     parseKey(this, rawKey)
-
-    this.isExp = !SINGLE_VAR_RE.test(this.key) || NESTING_RE.test(this.key)
     
     var filterExps = this.expression.slice(rawKey.length).match(FILTERS_RE)
     if (filterExps) {
         this.filters = []
         for (var i = 0, l = filterExps.length, filter; i < l; i++) {
             filter = parseFilter(filterExps[i], this.compiler)
-            if (filter) this.filters.push(filter)
+            if (filter) {
+                this.filters.push(filter)
+                if (filter.apply.computed) {
+                    // some special filters, e.g. filterBy & orderBy,
+                    // can involve VM properties and they often need to
+                    // be computed.
+                    this.computeFilters = true
+                }
+            }
         }
         if (!this.filters.length) this.filters = null
     } else {
         this.filters = null
     }
+
+    this.isExp =
+        this.computeFilters ||
+        !SINGLE_VAR_RE.test(this.key) ||
+        NESTING_RE.test(this.key)
+
 }
 
 var DirProto = Directive.prototype
@@ -102,7 +115,7 @@ function parseFilter (filter, compiler) {
     })
 
     var name = tokens[0],
-        apply = compiler.getOption('filters', name) || filters[name]
+        apply = compiler.getOption('filters', name)
     if (!apply) {
         utils.warn('Unknown filter: ' + name)
         return
@@ -128,7 +141,7 @@ DirProto.update = function (value, init) {
         this.value = value
         if (this._update) {
             this._update(
-                this.filters
+                this.filters && !this.computeFilters
                     ? this.applyFilters(value)
                     : value,
                 init
@@ -192,7 +205,7 @@ Directive.parse = function (dirname, expression, compiler, node) {
     
     // have a valid raw key, or be an empty directive
     return (rawKey || expression === '')
-        ? new Directive(dir, expression, rawKey, compiler, node)
+        ? new Directive(dirname, dir, expression, rawKey, compiler, node)
         : utils.warn('invalid directive expression: ' + expression)
 }
 

+ 15 - 1
src/exp-parser.js

@@ -113,7 +113,7 @@ function escapeDollar (v) {
  *  from an arbitrary expression, together with a list of paths to be
  *  created as bindings.
  */
-exports.parse = function (exp, compiler, data) {
+exports.parse = function (exp, compiler, data, filters) {
     // unicode and 'constructor' are not allowed for XSS security.
     if (unicodeRE.test(exp) || constructorRE.test(exp)) {
         utils.warn('Unsafe expression: ' + exp)
@@ -125,6 +125,18 @@ exports.parse = function (exp, compiler, data) {
         return makeGetter('return ' + exp, exp)
     }
     vars = utils.unique(vars)
+
+    if (filters) {
+        filters.forEach(function (filter) {
+            var args = filter.args
+                ? ',[' + filter.args.map(function (arg) {
+                    return '"' + arg + '"'
+                }).join(',') + ']'
+                : ''
+            exp = 'this.$compiler.getOption("filters", "' + filter.name + '").call(this,' + exp + args + ')'
+        })
+    }
+
     var accessors = '',
         has       = utils.hash(),
         strings   = [],
@@ -165,6 +177,8 @@ exports.parse = function (exp, compiler, data) {
         return strings[i]
     }
 
+    console.log(body)
+
     return makeGetter(body, exp)
 }