diff --git a/packages/mip/src/services/extensions.js b/packages/mip/src/services/extensions.js index ee6a9c6c..b38f5d1f 100644 --- a/packages/mip/src/services/extensions.js +++ b/packages/mip/src/services/extensions.js @@ -245,37 +245,6 @@ export class Extensions { this.currentExtensionId = extensionId factory(...args) - /** - * This extension needs `mip-vue` service. - */ - if ( - document.documentElement.hasAttribute('mip-vue') && - !Services.getServiceOrNull('mip-vue') - ) { - /** - * Inserts script of `mip-vue` service if needed. - */ - if (!document.querySelector('script[src*="mip-vue.js"]')) { - /* istanbul ignore if */ - if (process.env.NODE_ENV === 'production') { - insertScript(`https://c.mipcdn.com/static/v2/mip-vue.js`) - } else { - const baseUrl = document.querySelector('script[src*="mip.js"]').src.replace(/\/[^/]+$/, '') - - insertScript(`${baseUrl}/mip-vue.js`) - } - } - - /** - * Interrupts current registration. - * Reregisters this extension while `mip-vue` service is loaded. - */ - Services.getServicePromise('mip-vue') - .then(() => this.registerExtension(extensionId, factory, ...args)) - - return - } - /** * It still possible that all element instances in current extension call lifecycle `build` synchronously. * Executes callback in microtask to make sure all these elements are built. @@ -290,6 +259,29 @@ export class Extensions { } } + /** + * load mip-vue script + */ + loadVueScript () { + if ( + document.documentElement.hasAttribute('mip-vue') && + !Services.getServiceOrNull('mip-vue') + ) { + /** + * Inserts script of `mip-vue` service if needed. + */ + if (!document.querySelector('script[src*="mip-vue.js"]')) { + /* istanbul ignore if */ + if (process.env.NODE_ENV === 'production') { + insertScript(`https://c.mipcdn.com/static/v2/mip-vue.js`) + } else { + const baseUrl = document.querySelector('script[src*="mip.js"]').src.replace(/\/[^/]+$/, '') + insertScript(`${baseUrl}/mip-vue.js`) + } + } + } + } + /** * To see if all elements registered in current extension are built. * @@ -380,12 +372,31 @@ export class Extensions { holder.extension.elements[name] = element } - const registrator = this.getElementRegistrator(element) - + let registrator = this.getElementRegistrator(element) + // only vue registrator would return undefined + // so reload vue script and get registrator again if (!registrator) { - return + this.loadVueScript() + Services.getServicePromise('mip-vue').then(() => { + registrator = this.getElementRegistrator(element) + this.execRegisterElement(registrator, name, implementation, css, holder) + }) + } else { + this.execRegisterElement(registrator, name, implementation, css, holder) } + } + + /** + * using registrator to execute registration + * + * @param {Function} registrator MIP Component registrator + * @param {string} name Component name + * @param {!Object | !Object} implementation implementation + * @param {string=} css css string + * @param {Object} holder component holder + */ + execRegisterElement (registrator, name, implementation, css, holder) { /** @type {?HTMLElement[]} */ let elementInstances = registrator(name, implementation, css) diff --git a/packages/mip/test/specs/mip1-polyfill/element.spec.js b/packages/mip/test/specs/mip1-polyfill/element.spec.js index 6da42721..cd7a98e7 100644 --- a/packages/mip/test/specs/mip1-polyfill/element.spec.js +++ b/packages/mip/test/specs/mip1-polyfill/element.spec.js @@ -354,10 +354,13 @@ describe('mip1 element', function () { let node = createDomByTag(name) node.setAttribute('name', 'MIP') - return extensions.waitForExtension(name).then(function () { - document.body.removeChild(node) - expect(queue).to.deep.equal(['createdCallback', 'attachedCallback', 'build', 'detachedCallback']) - }) + return extensions.waitForExtension(name) + .then(function () { + document.body.removeChild(node) + }) + .then(function () { + expect(queue).to.deep.equal(['createdCallback', 'attachedCallback', 'build', 'detachedCallback']) + }) }) })