You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
141 lines
5.8 KiB
141 lines
5.8 KiB
var MyVueExt = (function () {
|
|
Vue.Ext = true;
|
|
var exports = {};
|
|
var debug = false;
|
|
var basePath = document.location.pathname.substr(0, document.location.pathname.lastIndexOf('/'));
|
|
var componentsPath = '/views/components/';
|
|
var fileExt = '.html';
|
|
var styleCounter = 'vc-style-counter';
|
|
var routerHome = '/views/home';
|
|
function log(msg) {
|
|
if (debug) {
|
|
console.log(msg);
|
|
}
|
|
}
|
|
function append(parent, html) {
|
|
var frag = document.createDocumentFragment();
|
|
var div = document.createElement('div');
|
|
div.innerHTML = html;
|
|
frag.appendChild(div.firstChild);
|
|
parent.appendChild(frag);
|
|
}
|
|
function templateToModel(html, name, url) {
|
|
var doc = new DOMParser().parseFromString(html, 'text/html');
|
|
var templateTag = doc.querySelector('template');
|
|
var template = templateTag ? templateTag.innerHTML : '<template></template>';
|
|
var scriptTag = doc.querySelector('script');
|
|
var script = scriptTag ? scriptTag.innerHTML : '{}';
|
|
var modelScript = '(' + script.replace(/^\s*export\s*default\s*/, '').replace(/;?\s*$/, '') + ')\n//# sourceURL=' + url;
|
|
var model = eval(modelScript) || {};
|
|
var styleTag = doc.querySelector('style');
|
|
if (styleTag) {
|
|
styleTag.setAttribute('class', name);
|
|
styleTag.setAttribute(MyVueExt.styleCounter, 1);
|
|
model.style = styleTag.outerHTML;
|
|
}
|
|
model.template = template;
|
|
return model;
|
|
}
|
|
function addComponent(instance, name, url) {
|
|
log('add vue component:' + name + ' from ' + url);
|
|
instance.component(name, Vue.defineAsyncComponent(() => new Promise((resolve, reject) => {
|
|
fetch(url).then(function (response) {
|
|
return response.text();
|
|
}).then(function (text) {
|
|
if (text) {
|
|
var component = MyVueExt.templateToModel(text, name, url);
|
|
component.created = function () {
|
|
var style = document.querySelector('head style.' + name);
|
|
if (style) {
|
|
var counter = parseInt(style.getAttribute(MyVueExt.styleCounter));
|
|
style.setAttribute(MyVueExt.styleCounter, counter + 1);
|
|
}
|
|
else {
|
|
if (component.style) {
|
|
MyVueExt.append(document.querySelector('head'), component.style)
|
|
}
|
|
}
|
|
};
|
|
component.unmounted = function () {
|
|
var style = document.querySelector('head style.' + name);
|
|
if (style) {
|
|
var counter = parseInt(style.getAttribute(MyVueExt.styleCounter));
|
|
if (counter - 1 > 0) {
|
|
style.setAttribute(MyVueExt.styleCounter, counter - 1);
|
|
}
|
|
else {
|
|
document.head.removeChild(style);
|
|
}
|
|
}
|
|
};
|
|
resolve(component);
|
|
}
|
|
});
|
|
})));
|
|
}
|
|
function patchComponent(instance, name, fun) {
|
|
var result = fun();
|
|
if (!result || typeof (result) === 'string') {
|
|
var url = basePath + componentsPath + name.replaceAll('-', "/") + fileExt;
|
|
addComponent(instance, name, url);
|
|
result = fun();
|
|
}
|
|
return result;
|
|
}
|
|
function configRouter(router) {
|
|
router.beforeEach((to, from, next) => {
|
|
var url = to.path === '/' ? routerHome : to.path;
|
|
var name = url.substring(1).replaceAll('/', "-");
|
|
url = MyVueExt.basePath + url + MyVueExt.fileExt;
|
|
if (!router.hasRoute(name)) {
|
|
fetch(url).then(function (response) {
|
|
return response.text();
|
|
}).then(function (text) {
|
|
if (text) {
|
|
var model = MyVueExt.templateToModel(text, name, url);
|
|
var route = {
|
|
name: name,
|
|
path: to.path,
|
|
component: model,
|
|
meta: model.meta
|
|
};
|
|
router.addRoute(route);
|
|
router.push({ path: to.path, query: to.query });
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
next();
|
|
}
|
|
});
|
|
router.beforeResolve(async function (to) {
|
|
var route = router.getRoutes().find(function (item, index) { return item.name === to.name });
|
|
if (route.components.default.style && !document.querySelector('head style.' + to.name)) {
|
|
MyVueExt.append(document.querySelector('head'), route.components.default.style)
|
|
}
|
|
});
|
|
router.afterEach(function (to, from) {
|
|
if (from.name) {
|
|
if (to.path !== from.path) {
|
|
var style = document.querySelector('head style.' + from.name);
|
|
if (style) {
|
|
document.head.removeChild(style);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
exports.debug = debug;
|
|
exports.basePath = basePath;
|
|
exports.componentsPath = componentsPath;
|
|
exports.fileExt = fileExt;
|
|
exports.styleCounter = styleCounter;
|
|
exports.log = log;
|
|
exports.append = append;
|
|
exports.templateToModel = templateToModel;
|
|
exports.addComponent = addComponent;
|
|
exports.patchComponent = patchComponent;
|
|
exports.configRouter = configRouter;
|
|
exports.routerHome = routerHome;
|
|
return exports;
|
|
}()); |