Przeglądaj źródła

support array asset syntax

Evan You 10 lat temu
rodzic
commit
5fb37fb12c
2 zmienionych plików z 122 dodań i 62 usunięć
  1. 93 61
      src/util/options.js
  2. 29 1
      test/unit/specs/util/options_spec.js

+ 93 - 61
src/util/options.js

@@ -1,4 +1,5 @@
 var _ = require('./index')
 var _ = require('./index')
+var config = require('../config')
 var extend = _.extend
 var extend = _.extend
 
 
 /**
 /**
@@ -145,18 +146,17 @@ strats.paramAttributes = function () {
  * options and parent options.
  * options and parent options.
  */
  */
 
 
-strats.directives =
-strats.filters =
-strats.transitions =
-strats.components =
-strats.partials =
-strats.elementDirectives = function (parentVal, childVal) {
+function mergeAssets (parentVal, childVal) {
   var res = Object.create(parentVal)
   var res = Object.create(parentVal)
   return childVal
   return childVal
-    ? extend(res, childVal)
+    ? extend(res, guardArrayAssets(childVal))
     : res
     : res
 }
 }
 
 
+config._assetTypes.forEach(function (type) {
+  strats[type + 's'] = mergeAssets
+})
+
 /**
 /**
  * Events & Watchers.
  * Events & Watchers.
  *
  *
@@ -206,28 +206,87 @@ var defaultStrat = function (parentVal, childVal) {
     : childVal
     : childVal
 }
 }
 
 
+/**
+ * Merge two option objects into a new one.
+ * Core utility used in both instantiation and inheritance.
+ *
+ * @param {Object} parent
+ * @param {Object} child
+ * @param {Vue} [vm] - if vm is present, indicates this is
+ *                     an instantiation merge.
+ */
+
+exports.mergeOptions = function merge (parent, child, vm) {
+  guardComponents(child)
+  guardProps(child)
+  var options = {}
+  var key
+  if (child.mixins) {
+    for (var i = 0, l = child.mixins.length; i < l; i++) {
+      parent = merge(parent, child.mixins[i], vm)
+    }
+  }
+  for (key in parent) {
+    mergeField(key)
+  }
+  for (key in child) {
+    if (!(parent.hasOwnProperty(key))) {
+      mergeField(key)
+    }
+  }
+  function mergeField (key) {
+    var strat = strats[key] || defaultStrat
+    options[key] = strat(parent[key], child[key], vm, key)
+  }
+  return options
+}
+
+/**
+ * Resolve an asset.
+ * This function is used because child instances need access
+ * to assets defined in its ancestor chain.
+ *
+ * @param {Object} options
+ * @param {String} type
+ * @param {String} id
+ * @return {Object|Function}
+ */
+
+exports.resolveAsset = function resolve (options, type, id) {
+  var asset = options[type][id]
+  while (!asset && options._parent) {
+    options = options._parent.$options
+    asset = options[type][id]
+  }
+  return asset
+}
+
 /**
 /**
  * Make sure component options get converted to actual
  * Make sure component options get converted to actual
  * constructors.
  * constructors.
  *
  *
- * @param {Object} components
+ * @param {Object} options
  */
  */
 
 
-function guardComponents (components) {
-  if (components) {
+function guardComponents (options) {
+  if (options.components) {
+    var components = options.components =
+      guardArrayAssets(options.components)
     var def
     var def
-    for (var key in components) {
+    var ids = Object.keys(components)
+    for (var i = 0, l = ids.length; i < l; i++) {
+      var key = ids[i]
       if (_.commonTagRE.test(key)) {
       if (_.commonTagRE.test(key)) {
         process.env.NODE_ENV !== 'production' && _.warn(
         process.env.NODE_ENV !== 'production' && _.warn(
           'Do not use built-in HTML elements as component ' +
           'Do not use built-in HTML elements as component ' +
-          'name: ' + key
+          'id: ' + key
         )
         )
         continue
         continue
       }
       }
       def = components[key]
       def = components[key]
       if (_.isPlainObject(def)) {
       if (_.isPlainObject(def)) {
-        def.name = key
-        components[key] = _.Vue.extend(def)
+        def.id = def.id || key
+        components[key] = def._Ctor || (def._Ctor = _.Vue.extend(def))
       }
       }
     }
     }
   }
   }
@@ -261,56 +320,29 @@ function guardProps (options) {
 }
 }
 
 
 /**
 /**
- * Merge two option objects into a new one.
- * Core utility used in both instantiation and inheritance.
+ * Guard an Array-format assets option and converted it
+ * into the key-value Object format.
  *
  *
- * @param {Object} parent
- * @param {Object} child
- * @param {Vue} [vm] - if vm is present, indicates this is
- *                     an instantiation merge.
+ * @param {Object|Array} assets
+ * @return {Object}
  */
  */
 
 
-exports.mergeOptions = function merge (parent, child, vm) {
-  guardComponents(child.components)
-  guardProps(child)
-  var options = {}
-  var key
-  if (child.mixins) {
-    for (var i = 0, l = child.mixins.length; i < l; i++) {
-      parent = merge(parent, child.mixins[i], vm)
-    }
-  }
-  for (key in parent) {
-    mergeField(key)
-  }
-  for (key in child) {
-    if (!(parent.hasOwnProperty(key))) {
-      mergeField(key)
+function guardArrayAssets (assets) {
+  if (_.isArray(assets)) {
+    var res = {}
+    var i = assets.length
+    var asset
+    while (i--) {
+      asset = assets[i]
+      if (!asset.id) {
+        process.env.NODE_ENV !== 'production' && _.warn(
+          'Array-syntax assets must provide an id field.'
+        )
+      } else {
+        res[asset.id] = asset
+      }
     }
     }
+    return res
   }
   }
-  function mergeField (key) {
-    var strat = strats[key] || defaultStrat
-    options[key] = strat(parent[key], child[key], vm, key)
-  }
-  return options
-}
-
-/**
- * Resolve an asset.
- * This function is used because child instances need access
- * to assets defined in its ancestor chain.
- *
- * @param {Object} options
- * @param {String} type
- * @param {String} id
- * @return {Object|Function}
- */
-
-exports.resolveAsset = function resolve (options, type, id) {
-  var asset = options[type][id]
-  while (!asset && options._parent) {
-    options = options._parent.$options
-    asset = options[type][id]
-  }
-  return asset
+  return assets
 }
 }

+ 29 - 1
test/unit/specs/util/options_spec.js

@@ -122,7 +122,7 @@ describe('Util - Option merging', function () {
       }
       }
     })
     })
     expect(typeof res.components.test).toBe('function')
     expect(typeof res.components.test).toBe('function')
-    expect(res.components.test.options.name).toBe('test')
+    expect(res.components.test.options.id).toBe('test')
     expect(res.components.test.super).toBe(Vue)
     expect(res.components.test.super).toBe(Vue)
   })
   })
 
 
@@ -274,4 +274,32 @@ describe('Util - Option merging', function () {
     expect(res.created[3]).toBe(f4)
     expect(res.created[3]).toBe(f4)
   })
   })
 
 
+  it('Array assets', function () {
+    var a = {
+      components: {
+        a: Vue.extend({})
+      }
+    }
+    var b = {
+      components: [{ id: 'b' }]
+    }
+    var res = merge(a, b)
+    expect(res.components.a).toBe(a.components.a)
+    // b.components is guarded and converted to object hash
+    expect(res.components.b).toBe(b.components.b)
+  })
+
+  it('warn Array assets without id', function () {
+    var a = {
+      components: {
+        a: Vue.extend({})
+      }
+    }
+    var b = {
+      components: [{}]
+    }
+    merge(a, b)
+    expect(hasWarned(_, 'must provide an id')).toBe(true)
+  })
+
 })
 })