Skip to content

Commit 5fb37fb

Browse files
committed
support array asset syntax
1 parent 90cdcdb commit 5fb37fb

File tree

2 files changed

+122
-62
lines changed

2 files changed

+122
-62
lines changed

src/util/options.js

Lines changed: 93 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var _ = require('./index')
2+
var config = require('../config')
23
var extend = _.extend
34

45
/**
@@ -145,18 +146,17 @@ strats.paramAttributes = function () {
145146
* options and parent options.
146147
*/
147148

148-
strats.directives =
149-
strats.filters =
150-
strats.transitions =
151-
strats.components =
152-
strats.partials =
153-
strats.elementDirectives = function (parentVal, childVal) {
149+
function mergeAssets (parentVal, childVal) {
154150
var res = Object.create(parentVal)
155151
return childVal
156-
? extend(res, childVal)
152+
? extend(res, guardArrayAssets(childVal))
157153
: res
158154
}
159155

156+
config._assetTypes.forEach(function (type) {
157+
strats[type + 's'] = mergeAssets
158+
})
159+
160160
/**
161161
* Events & Watchers.
162162
*
@@ -206,28 +206,87 @@ var defaultStrat = function (parentVal, childVal) {
206206
: childVal
207207
}
208208

209+
/**
210+
* Merge two option objects into a new one.
211+
* Core utility used in both instantiation and inheritance.
212+
*
213+
* @param {Object} parent
214+
* @param {Object} child
215+
* @param {Vue} [vm] - if vm is present, indicates this is
216+
* an instantiation merge.
217+
*/
218+
219+
exports.mergeOptions = function merge (parent, child, vm) {
220+
guardComponents(child)
221+
guardProps(child)
222+
var options = {}
223+
var key
224+
if (child.mixins) {
225+
for (var i = 0, l = child.mixins.length; i < l; i++) {
226+
parent = merge(parent, child.mixins[i], vm)
227+
}
228+
}
229+
for (key in parent) {
230+
mergeField(key)
231+
}
232+
for (key in child) {
233+
if (!(parent.hasOwnProperty(key))) {
234+
mergeField(key)
235+
}
236+
}
237+
function mergeField (key) {
238+
var strat = strats[key] || defaultStrat
239+
options[key] = strat(parent[key], child[key], vm, key)
240+
}
241+
return options
242+
}
243+
244+
/**
245+
* Resolve an asset.
246+
* This function is used because child instances need access
247+
* to assets defined in its ancestor chain.
248+
*
249+
* @param {Object} options
250+
* @param {String} type
251+
* @param {String} id
252+
* @return {Object|Function}
253+
*/
254+
255+
exports.resolveAsset = function resolve (options, type, id) {
256+
var asset = options[type][id]
257+
while (!asset && options._parent) {
258+
options = options._parent.$options
259+
asset = options[type][id]
260+
}
261+
return asset
262+
}
263+
209264
/**
210265
* Make sure component options get converted to actual
211266
* constructors.
212267
*
213-
* @param {Object} components
268+
* @param {Object} options
214269
*/
215270

216-
function guardComponents (components) {
217-
if (components) {
271+
function guardComponents (options) {
272+
if (options.components) {
273+
var components = options.components =
274+
guardArrayAssets(options.components)
218275
var def
219-
for (var key in components) {
276+
var ids = Object.keys(components)
277+
for (var i = 0, l = ids.length; i < l; i++) {
278+
var key = ids[i]
220279
if (_.commonTagRE.test(key)) {
221280
process.env.NODE_ENV !== 'production' && _.warn(
222281
'Do not use built-in HTML elements as component ' +
223-
'name: ' + key
282+
'id: ' + key
224283
)
225284
continue
226285
}
227286
def = components[key]
228287
if (_.isPlainObject(def)) {
229-
def.name = key
230-
components[key] = _.Vue.extend(def)
288+
def.id = def.id || key
289+
components[key] = def._Ctor || (def._Ctor = _.Vue.extend(def))
231290
}
232291
}
233292
}
@@ -261,56 +320,29 @@ function guardProps (options) {
261320
}
262321

263322
/**
264-
* Merge two option objects into a new one.
265-
* Core utility used in both instantiation and inheritance.
323+
* Guard an Array-format assets option and converted it
324+
* into the key-value Object format.
266325
*
267-
* @param {Object} parent
268-
* @param {Object} child
269-
* @param {Vue} [vm] - if vm is present, indicates this is
270-
* an instantiation merge.
326+
* @param {Object|Array} assets
327+
* @return {Object}
271328
*/
272329

273-
exports.mergeOptions = function merge (parent, child, vm) {
274-
guardComponents(child.components)
275-
guardProps(child)
276-
var options = {}
277-
var key
278-
if (child.mixins) {
279-
for (var i = 0, l = child.mixins.length; i < l; i++) {
280-
parent = merge(parent, child.mixins[i], vm)
281-
}
282-
}
283-
for (key in parent) {
284-
mergeField(key)
285-
}
286-
for (key in child) {
287-
if (!(parent.hasOwnProperty(key))) {
288-
mergeField(key)
330+
function guardArrayAssets (assets) {
331+
if (_.isArray(assets)) {
332+
var res = {}
333+
var i = assets.length
334+
var asset
335+
while (i--) {
336+
asset = assets[i]
337+
if (!asset.id) {
338+
process.env.NODE_ENV !== 'production' && _.warn(
339+
'Array-syntax assets must provide an id field.'
340+
)
341+
} else {
342+
res[asset.id] = asset
343+
}
289344
}
345+
return res
290346
}
291-
function mergeField (key) {
292-
var strat = strats[key] || defaultStrat
293-
options[key] = strat(parent[key], child[key], vm, key)
294-
}
295-
return options
296-
}
297-
298-
/**
299-
* Resolve an asset.
300-
* This function is used because child instances need access
301-
* to assets defined in its ancestor chain.
302-
*
303-
* @param {Object} options
304-
* @param {String} type
305-
* @param {String} id
306-
* @return {Object|Function}
307-
*/
308-
309-
exports.resolveAsset = function resolve (options, type, id) {
310-
var asset = options[type][id]
311-
while (!asset && options._parent) {
312-
options = options._parent.$options
313-
asset = options[type][id]
314-
}
315-
return asset
347+
return assets
316348
}

test/unit/specs/util/options_spec.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ describe('Util - Option merging', function () {
122122
}
123123
})
124124
expect(typeof res.components.test).toBe('function')
125-
expect(res.components.test.options.name).toBe('test')
125+
expect(res.components.test.options.id).toBe('test')
126126
expect(res.components.test.super).toBe(Vue)
127127
})
128128

@@ -274,4 +274,32 @@ describe('Util - Option merging', function () {
274274
expect(res.created[3]).toBe(f4)
275275
})
276276

277+
it('Array assets', function () {
278+
var a = {
279+
components: {
280+
a: Vue.extend({})
281+
}
282+
}
283+
var b = {
284+
components: [{ id: 'b' }]
285+
}
286+
var res = merge(a, b)
287+
expect(res.components.a).toBe(a.components.a)
288+
// b.components is guarded and converted to object hash
289+
expect(res.components.b).toBe(b.components.b)
290+
})
291+
292+
it('warn Array assets without id', function () {
293+
var a = {
294+
components: {
295+
a: Vue.extend({})
296+
}
297+
}
298+
var b = {
299+
components: [{}]
300+
}
301+
merge(a, b)
302+
expect(hasWarned(_, 'must provide an id')).toBe(true)
303+
})
304+
277305
})

0 commit comments

Comments
 (0)