///https://html5boilerplate.com/ ///config.js //config const config = { debug: true, path: document.location.pathname.substr(0, document.location.pathname.lastIndexOf('/')), ext: '.html', componentCounter: 'vue-component-counter', file: function (file) { return this.path + file; } }; //log function log(message) { if (config.debug) { console.log(message); } } //解析组件 function parseModel(response, name) { var html = new DOMParser().parseFromString(response.data, 'text/html'); var template = html.getElementsByTagName('template')[0]; var script = html.getElementsByTagName('script')[0].innerHTML; script = '(' + script.replace(/^\s*export\s*default\s*/, '').replace(/;?\s*$/, '') + ')\n//# sourceURL=' + response.config.url; var model = eval(script) || {}; var style = html.getElementsByTagName('style')[0]; if (style) { style.setAttribute('class', name); style.setAttribute(config.componentCounter, 1); model.style = style.outerHTML; } model.template = template; return model; } //添加vue异步组件 function addVueComponentsByEval(app, cfg) { for (var i in cfg.list) { (function () { var item = cfg.list[i]; var url = config.path + cfg.prefix + item + config.ext; var path = url.substring(config.path.length); var name = path.substring(cfg.prefix.length, path.length - config.ext.length).replaceAll('/', "-"); app.component(name, Vue.defineAsyncComponent(() => new Promise((resolve, reject) => { axios.get(url, { headers: { 'Cache-Control': 'no-cache' } }).then(function (response) { var component = parseModel(response, name); component.created = function () { var style = document.querySelector('head style.' + name); if (style) { var counter = parseInt(style.getAttribute(config.componentCounter)); style.setAttribute(config.componentCounter, counter + 1); } else { if (component.style) { $('head').append(component.style); } } }; component.unmounted = function () { var style = document.querySelector('head style.' + name); if (style) { var counter = parseInt(style.getAttribute(config.componentCounter)); if (counter - 1 > 0) { style.setAttribute(config.componentCounter, counter - 1); } else { document.head.removeChild(style); } } }; resolve(component); }); }))); })(); } } ///router.js var router = new VueRouter.createRouter({ history: VueRouter.createWebHashHistory(), routes: [] }); router.beforeEach((to, from, next) => { console.log('to------',to) var url = to.path === '/' ? '/views/home' : to.path; var name = url.substring(1).replaceAll('/', "-"); url = config.path + url + config.ext; if (!router.hasRoute(name)) { axios.get(url, { headers: { 'Cache-Control': 'no-cache' } }).then(function (response) { var model = parseModel(response, name); 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 to => { var route = Enumerable.from(router.getRoutes()).firstOrDefault(o => o.name === to.name); if (route.components.default.style && !document.querySelector('head style.' + to.name)) { $('head').append(route.components.default.style); } console.log(to); }); router.afterEach((to, from) => { if (from.name) { if (to.path !== from.path) { var style = document.querySelector('head style.' + from.name); if (style) { document.head.removeChild(style); } } } }); ///site.js const store = { state: Vue.reactive({ show: true, query: '', showOverlay: false }) }; const app = Vue.createApp({ data() { return store.state; }, mounted() { window.addEventListener('hashchange', () => { let currentPath = window.location.hash.slice(1) if (this.$route.path !== currentPath) { this.$router.push(currentPath) } }, false); }, methods: { reload() { this.show = false; this.$nextTick(function () { this.show = true; }); } } }); //添加组件 var cfg = { prefix: '/views/components/', list: [ 'layout', 'pagination' ] }; addVueComponentsByEval(app, cfg); app.component("v-chart", VueECharts); app.use(router); var vm = app.mount("#app");