diff --git a/packages/fineui/src/core/5.inject.js b/packages/fineui/src/core/5.inject.js index dc3392106..0246f2497 100644 --- a/packages/fineui/src/core/5.inject.js +++ b/packages/fineui/src/core/5.inject.js @@ -1,4 +1,16 @@ -import { isFunction, isNull, isNotNull, isArray, each, isWidget, extend, init, isEmpty, remove } from "./2.base"; +import { + isFunction, + isNull, + isNotNull, + isArray, + each, + isWidget, + extend, + init, + isEmpty, + remove, + isString +} from "./2.base"; import { OB } from "./3.ob"; import { Widget } from "./4.widget"; import { Plugin } from "./6.plugin"; @@ -6,6 +18,7 @@ import { aspect } from "./structure"; import { Events } from "./constant"; import { _global } from "./0.foundation"; import { SystemProvider } from "./system"; +import { loadResources } from "./platform"; const moduleInjection = {}, moduleInjectionMap = { components: {}, @@ -46,6 +59,7 @@ export function module(xtype, cls) { } const constantInjection = {}; + export function constant(xtype, cls) { if (isNotNull(constantInjection[xtype])) { _global.console && console.error(`constant: [${xtype}]already registered`); @@ -57,6 +71,7 @@ export function constant(xtype, cls) { } const modelInjection = {}; + export function model(xtype, cls) { if (isNotNull(modelInjection[xtype])) { _global.console && console.error(`model: [${xtype}] already registered`); @@ -68,6 +83,7 @@ export function model(xtype, cls) { } const storeInjection = {}; + export function store(xtype, cls) { if (isNotNull(storeInjection[xtype])) { _global.console && console.error(`store: [${xtype}] already registered`); @@ -79,6 +95,7 @@ export function store(xtype, cls) { } const serviceInjection = {}; + export function service(xtype, cls) { if ((serviceInjection[xtype])) { _global.console && console.error(`service: [${xtype}] already registered`); @@ -90,6 +107,7 @@ export function service(xtype, cls) { } const providerInjection = {}; + export function provider(xtype, cls) { if ((providerInjection[xtype])) { _global.console && console.error(`provider: [${xtype}] already registered`); @@ -114,7 +132,7 @@ const runConfigFunction = (type, configFn) => { queue = configFunctions[type]; delete configFunctions[type]; } - + const dependencies = Providers.getProvider(SystemProvider.xtype).getDependencies(); const modules = moduleInjectionMap.components[type] || moduleInjectionMap.constants[type] @@ -167,6 +185,50 @@ const runConfigFunction = (type, configFn) => { } }; +/** + * 配置组件依赖 + * @param deps + */ +function configWidgetDeps(deps) { + each(deps, (key, dep) => { + const deps = (isArray(dep) ? dep : [dep]).map(d => { + if (isString(d)) { + return { + src: d, + async: false + }; + } else { + return d; + } + }); + + config(key, props => { + + const asyncLoad = deps.some(dep => dep.async); + // 异步加载资源 + if (asyncLoad && !props._depsLoaded) { + return { + type: Widget, + beforeInit: () => { + return loadResources(deps); + }, + render: () => { + return { + ...props, + _depsLoaded: true + }; + }, + }; + } + + // 同步加载资源 + loadResources(deps); + + return props; + }); + }); +} + export function config(type, configFn, opt) { if (isFunction(type)) { opt = configFn; @@ -184,7 +246,7 @@ export function config(type, configFn, opt) { if (providerInstance[type]) { delete providerInstance[type]; } - + return configFn(providers[type]); } @@ -196,6 +258,10 @@ export function config(type, configFn, opt) { opt, }); + if (opt.deps) { + configWidgetDeps(opt.deps); + } + if (opt.immediately) { return runConfigFunction(type, configFn); } @@ -207,10 +273,11 @@ export function getReference(type, fn) { const actions = {}; const globalAction = []; + export function action(type, actionFn) { if (isFunction(type)) { globalAction.push(type); - + return () => { remove(globalAction, idx => globalAction.indexOf(actionFn) === idx); }; @@ -219,7 +286,7 @@ export function action(type, actionFn) { actions[type] = []; } actions[type].push(actionFn); - + return () => { remove(actions[type], idx => actions[type].indexOf(actionFn) === idx); if (actions[type].length === 0) { @@ -229,6 +296,7 @@ export function action(type, actionFn) { } const points = {}; + export function point(type, action, pointFn, after) { if (!points[type]) { points[type] = {}; @@ -243,25 +311,25 @@ export function point(type, action, pointFn, after) { } export const Modules = { - getModule (type) { + getModule(type) { if (!moduleInjection[type]) { _global.console && console.error(`module: [${type}] undefined`); } - + return moduleInjection[type]; }, - getAllModules () { + getAllModules() { return moduleInjection; }, }; export const Constants = { - getConstant (type) { + getConstant(type) { if (isNull(constantInjection[type])) { _global.console && console.error(`constant: [${type}] undefined`); } runConfigFunction(type); - + return isFunction(constantInjection[type]) ? constantInjection[type]() : constantInjection[type]; }, }; @@ -273,8 +341,8 @@ function callPoint(inst, types) { for (const action in points[type]) { const bfns = points[type][action].before; if (bfns) { - aspect.before(inst, action, (function (bfns) { - return function () { + aspect.before(inst, action, (function(bfns) { + return function() { for (let i = 0, len = bfns.length; i < len; i++) { try { bfns[i].apply(inst, arguments); @@ -287,8 +355,8 @@ function callPoint(inst, types) { } const afns = points[type][action].after; if (afns) { - aspect.after(inst, action, (function (afns) { - return function () { + aspect.after(inst, action, (function(afns) { + return function() { for (let i = 0, len = afns.length; i < len; i++) { try { afns[i].apply(inst, arguments); @@ -305,7 +373,7 @@ function callPoint(inst, types) { } export const Models = { - getModel (type, config) { + getModel(type, config) { if (!modelInjection[type]) { _global.console && console.error(`model: [${type}] undefined`); } @@ -314,14 +382,14 @@ export const Models = { inst._constructor && inst._constructor(config); inst.mixins && callPoint(inst, inst.mixins); callPoint(inst, type); - + return inst; }, }; const stores = {}; export const Stores = { - getStore (type, config) { + getStore(type, config) { if (!storeInjection[type]) { _global.console && console.error(`store: [${type}] undefined`); } @@ -333,7 +401,7 @@ export const Stores = { delete stores[type]; }); callPoint(inst, type); - + return inst; }, }; @@ -349,7 +417,7 @@ export const Services = { } services[type] = new serviceInjection[type](config); callPoint(services[type], type); - + return services[type]; }, }; @@ -368,13 +436,13 @@ export const Providers = { if (!providerInstance[type] && providers[type].$get) { providerInstance[type] = new (providers[type].$get())(config); } - + return providerInstance[type]; }, }; export const Actions = { - runAction (type, event, config) { + runAction(type, event, config) { each(actions[type], (i, act) => { try { act(event, config); @@ -383,7 +451,7 @@ export const Actions = { } }); }, - runGlobalAction () { + runGlobalAction() { const args = [].slice.call(arguments); each(globalAction, (i, act) => { try { @@ -396,6 +464,7 @@ export const Actions = { }; const kv = {}; + export function shortcut(xtype, cls) { if (isNotNull(kv[xtype])) { _global.console && console.error(`widget: [${xtype}] already registered`); @@ -403,12 +472,12 @@ export function shortcut(xtype, cls) { if (cls) { cls.xtype = xtype; } - + // 兼容性 if (!cls.hasOwnProperty("superclass")) { cls.superclass = Object.getPrototypeOf(cls.prototype); } - + kv[xtype] = cls; } @@ -436,7 +505,7 @@ const createRealWidget = (config, context, lazy) => { widget._lazyConstructor(); // } pushed && Widget.popContext(); - + return widget; }; @@ -480,7 +549,7 @@ export function createWidget(item, options, context, lazy) { if (!w.listeners || isArray(w.listeners)) { w.listeners = (w.listeners || []).concat([{ eventName: Events.MOUNT, - action: function () { + action: function() { Plugin.getObject(elType, this); }, }]); @@ -492,10 +561,10 @@ export function createWidget(item, options, context, lazy) { ].concat(w.listeners[Events.MOUNT] || []); } } - + return createRealWidget(w, context, lazy); } - + return createWidget(w, options, context, lazy); } if (isWidget(item.el)) { @@ -504,13 +573,13 @@ export function createWidget(item, options, context, lazy) { throw new Error("widget: Unable to create widget from item ", item); } -export function _lazyCreateWidget (item, options, context) { +export function _lazyCreateWidget(item, options, context) { return createWidget(item, options, context, true); } export function createElement() { const widget = createWidget.apply(this, arguments); - + return widget.element; } diff --git a/packages/fineui/src/core/platform/web/load.js b/packages/fineui/src/core/platform/web/load.js index 8daf6cbb9..6dd203ea1 100644 --- a/packages/fineui/src/core/platform/web/load.js +++ b/packages/fineui/src/core/platform/web/load.js @@ -1,6 +1,7 @@ import $ from "jquery"; const _LOADED = {}; // alex:保存加载过的 + function loadReady(src, must) { const $scripts = $("head script, body script"); $.each($scripts, (i, item) => { @@ -56,3 +57,99 @@ export function $import(src, ext, must) { }); } } + +/** + * 同步加载javascript + * @param uri + * @returns {boolean} + */ +export function syncLoadScript(uri) { + if (_LOADED[uri]) { + return true; + } + const xhr = new XMLHttpRequest(); + xhr.open("GET", uri, false); + xhr.send(null); + if (xhr.status === 200) { + const script = document.createElement("script"); + script.type = "text/javascript"; + script.text = xhr.responseText; + document.head.appendChild(script); + _LOADED[uri] = true; + return true; + } + return false; +} + +/** + * 默认的异步加载javascript方法 + * @param uri + * @returns {Promise|Promise} + */ +export function loadScript(uri) { + if (_LOADED[uri]) { + return Promise.resolve(true); + } + return new Promise(resolve => { + const script = document.createElement("script"); + script.type = "application/javascript"; + script.src = uri; + script.onload = function() { + resolve(true); + }; + document.head.appendChild(script); + _LOADED[uri] = true; + }); +} + +/** + * 加载css方法,这没同步异步之分,都是同步的 + * @param uri + * @returns {boolean} + */ +export function loadStyleSheet(uri) { + if (_LOADED[uri]) { + return true; + } + const link = document.createElement("link"); + link.type = "text/css"; + link.ref = "stylesheet"; + link.href = uri; + document.head.appendChild(link); + _LOADED[uri] = true; + + return true; +} + + +export function loadResource(opt) { + const { src, async = false } = opt; + let extension = opt.extension; + if (!extension) { + const match = src.match(/\.[^.]+$/g); + if (match && match.length > 0) { + extension = match[0]; + } + } + if (extension === ".css") { + return loadStyleSheet(src); + } + if (async) { + return loadScript(src); + } + + return syncLoadScript(src); +} + + +export function loadResources(resources) { + const asyncLoad = resources.some(resource => resource.async); + + if (asyncLoad) { + return Promise.all(resources.map(resource => loadResource(resource))); + } + + return resources.forEach(resource => { + loadResource(resource); + }); +}