实现场景:
在app组件中,把一个系统的所有页面都使用js编写(schema是js文件)然后设置到app的pages数组中,这样一个系统几百个页面会导致这个数组非常大,可能有5M,会不会出现性能问题,比如第一次进入页面卡顿
存在的问题:
因为无法使用js动态加载页面的schema,可能会导致第一次加载页面卡顿,pages使用schemaApi加载的话,js文件限制很多,我看只能是立即执行函数或者直接返回一个json对象才行,页面如果存在import就会报错
当前方案:
请粘贴你当前方案的完整 amis schema 代码...
index.js:
import 'amis/sdk/sdk.css'
import 'amis/sdk/antd.css'
import 'amis/sdk/helper.css'
import 'amis/sdk/iconfont.css'
import 'amis/sdk/sdk.js'
import { createBrowserHistory } from 'history';
import * as u from './utils'
import {configAxios} from './axiosConfig'
import pages from './site'
import loadMenus from './menu'
;(async () => {
//这里加入登录token判断,没有登录就跳转到login页面
if(!u.getToken()){
window.location = '/login.html'
return;
}
//configAxios();
//const menuResult = await loadMenus();
let amis = amisRequire('amis/embed');
const match = amisRequire('path-to-regexp').match;
// 如果想用 browserHistory 请切换下这处代码, 其他不用变
const history = createBrowserHistory();
//const history = createHashHistory();
const app = {
type: 'app',
brandName: 'XXX管理后台',
logo: '/public/logo.png',
header: {
type: 'tpl',
inline: false,
className: 'w-full',
tpl: '<div class="flex justify-between"><div>顶部区域左侧</div><div>顶部区域右侧</div></div>'
},
// footer: '<div class="p-2 text-center bg-light">底部区域</div>',
// asideBefore: '<div class="p-2 text-center">菜单前面区域</div>',
// asideAfter: '<div class="p-2 text-center">菜单后面区域</div>',
pages: pages
};
function normalizeLink(to, location = history.location) {
to = to || '';
if (to && to[0] === '#') {
to = location.pathname + location.search + to;
} else if (to && to[0] === '?') {
to = location.pathname + to;
}
const idx = to.indexOf('?');
const idx2 = to.indexOf('#');
let pathname = ~idx
? to.substring(0, idx)
: ~idx2
? to.substring(0, idx2)
: to;
let search = ~idx ? to.substring(idx, ~idx2 ? idx2 : undefined) : '';
let hash = ~idx2 ? to.substring(idx2) : location.hash;
if (!pathname) {
pathname = location.pathname;
} else if (pathname[0] != '/' && !/^https?\:\/\//.test(pathname)) {
let relativeBase = location.pathname;
const paths = relativeBase.split('/');
paths.pop();
let m;
while ((m = /^\.\.?\//.exec(pathname))) {
if (m[0] === '../') {
paths.pop();
}
pathname = pathname.substring(m[0].length);
}
pathname = paths.concat(pathname).join('/');
}
return pathname + search + hash;
}
function isCurrentUrl(to, ctx) {
if (!to) {
return false;
}
const pathname = history.location.pathname;
const link = normalizeLink(to, {
...location,
pathname,
hash: ''
});
if (!~link.indexOf('http') && ~link.indexOf(':')) {
let strict = ctx && ctx.strict;
return match(link, {
decode: decodeURIComponent,
strict: typeof strict !== 'undefined' ? strict : true
})(pathname);
}
return decodeURI(pathname) === link;
}
let amisInstance = amis.embed(
'#app',
app,
{
location: history.location,
data: {
// 全局数据,是受控的数据
},
context: {
// 全局上下文数据, 非受控的数据,无论哪一层都能获取到,包括弹窗自定义数据映射后都能获取到。
// 可以用来放一下全局配置等。比如 API_HOST, 这样页面配置里面可以通过 ${API_HOST} 来获取到。
API_HOST: import.meta.env.VITE_API_URL
}
},
{
// watchRouteChange: fn => {
// return history.listen(fn);
// },
updateLocation: (location, replace) => {
location = normalizeLink(location);
if (location === 'goBack') {
return history.goBack();
} else if (
(!/^https?\:\/\//.test(location) &&
location ===
history.location.pathname + history.location.search) ||
location === history.location.href
) {
// 目标地址和当前地址一样,不处理,免得重复刷新
return;
} else if (/^https?\:\/\//.test(location) || !history) {
return (window.location.href = location);
}
history[replace ? 'replace' : 'push'](location);
},
jumpTo: (to, action) => {
if (to === 'goBack') {
return history.goBack();
}
to = normalizeLink(to);
if (isCurrentUrl(to)) {
return;
}
if (action && action.actionType === 'url') {
action.blank === false
? (window.location.href = to)
: window.open(to, '_blank');
return;
} else if (action && action.blank) {
window.open(to, '_blank');
return;
}
if (/^https?:\/\//.test(to)) {
window.location.href = to;
} else if (
(!/^https?\:\/\//.test(to) &&
to === history.pathname + history.location.search) ||
to === history.location.href
) {
// do nothing
} else {
history.push(to);
}
},
requestAdaptor: async (api, context) => {
const headers = api.headers || {};
headers['X-APP'] = 'bqex';
//这里加入token的逻辑,如果获取到了就放到header中
if(!u.isIgnoreUrl(api.url)){
headers['Authorization'] = u.getToken() || '';
}
api.headers = headers;
console.log(api.url)
//当请求url不包含http且不是js和json后缀的时候(amis本身的请求,非后端接口),自动加上域名
if(!api.url.startsWith('http') && !api.url.includes('.js') && !api.url.includes('.json')){
api.url = import.meta.env.VITE_API_URL + api.url;
}
return api;
},
responseAdaptor: (api, payload, query, request, response) => {
if(payload.code == 401){
window.location = '/login.html';
return;
}
if(api.url.includes('.js')){
let module = {};
let oldModule = window.module;
window.module = module;
try {
eval('(' + payload + ')');
} catch (e) {
console.error('Error loading script: ', e);
}
window.module = oldModule;
payload = module.exports;
}
return payload;
},
isCurrentUrl: isCurrentUrl,
theme: 'antd'
}
);
//这里可以拦截路由变化
history.listen(state => {
amisInstance.updateProps({
location: state.location || state
});
});
})();
site.js(app的pages返回值)
import rolePage from './pages/role/index'
import roleOrgPage from './pages/role/org-index'
import menuPage from './pages/menu/index'
import userPage from './pages/user/index'
import adminPage from './pages/admin/index'
import onlineUserPage from './pages/user/online'
import systemPage from './pages/system/index'
import regionPage from './pages/region/index'
import areaPage from './pages/area/index'
import dictPage from './pages/dict/index'
import loginLogPage from './pages/log/login-log'
import operationLogPage from './pages/log/operation-log'
export default [
{
label: 'Home',
url: '/',
redirect: '/user'
},
{
children: [
{
label: '系统管理',
children: [
{
label: '用户管理',
url: 'user',
schema: userPage
},
{
label: '管理员管理',
url: 'admin',
schema: adminPage
},
{
label: '在线用户',
url: 'user/online',
schema: onlineUserPage
},
{
label: '菜单管理',
url: 'menu',
schema: menuPage
},
{
label: '角色管理',
url: 'role',
schema: rolePage
},
{
label: '机构角色管理',
url: 'role/org',
schema: roleOrgPage
},
{
label: '子系统管理',
url: 'system',
schema: systemPage
},
{
label: '片区管理',
url: 'region',
schema: regionPage
},
{
label: '行政区管理',
url: 'area',
schema: areaPage
},
{
label: '字典表管理',
url: 'dict',
schema: dictPage
},
{
label: '登录日志管理',
url: 'log/login',
schema: loginLogPage
},
{
label: '操作日志管理',
url: 'log/operation',
schema: operationLogPage
}
]
}
]
}
]
上面这种需要一次性import所有的页面,导致pages对象非常大,有没有办法动态import呢
8条答案
按热度按时间ukxgm1gy1#
schema能否支持动态import,比如schema: await import('./xxx.js')
ne5o7dgx2#
schema用api动态加载就行了,再api配置上缓存,也不会重复加载
oyjwcjzk3#
schema用api动态加载就行了,再api配置上缓存,也不会重复加载
api方式不支持加载模块化的js代码呢,有demo吗,因为一个页面的js文件需要导入其他js函数不是简单的返回json对象的
cbwuti444#
如你的:
{ label: '用户管理', url: 'user', schema: userPage },
改成
{ label: '用户管理', url: 'user', schemaApi: { "method": "get", "url": "/pages/user/index", "cache": 2000 } },
后端返回这个json格式
y1aodyip5#
如你的:
{ label: '用户管理', url: 'user', schema: userPage },
改成{ label: '用户管理', url: 'user', schemaApi: { "method": "get", "url": "/pages/user/index", "cache": 2000 } },
后端返回这个json格式如果userPage中有一些自定义的逻辑需要import其他库函数就不行了,如果全都是单纯的js那很好办,都可以直接使用js:xxxx.js来加载,问题就是每个js都有可能有自定义逻辑的
t8e9dugd6#
杠精不看文档?/pages/user/index接口返回这个不就可以模块化加载了?
{"type":"page","onEvent":{"init":{"actions":[{"actionType":"custom","script":"console.log('加载你的动态js')"}]}}}
crcmnpdw7#
杠精不看文档?/pages/user/index接口返回这个不就可以模块化加载了?
{"type":"page","onEvent":{"init":{"actions":[{"actionType":"custom","script":"console.log('加载你的动态js')"}]}}}
没有杠精的意思,虚心请教,文档也看了很多遍了,确实不知道schemaApi如何加载模块化的js文件,直接return {}这种是官方有介绍,actionType为custom的文档里面没有看到过
jdg4fx2g8#
杠精不看文档?/pages/user/index接口返回这个不就可以模块化加载了?
{"type":"page","onEvent":{"init":{"actions":[{"actionType":"custom","script":"console.log('加载你的动态js')"}]}}}
/pages/user/index这个是一个js文件,js里面又import了其他模块的js