requirejs.onError = function (err) {
console.log(err.requireType);
console.log('modules: ' + err.requireModules);
};
(function(require) {
//require路径配置
var requireConfig = {
paths: {
jquery: SERVER_PATH + '/bower_components/jquery/dist/jquery.min',
vue: SERVER_PATH + '/bower_components/vue2/vue.min',
vueRouter: SERVER_PATH + '/bower_components/vue2/vue-router.min',
text: SERVER_PATH + '/bower_components/text/text',
util: 'public/util/util',
MINT: SERVER_PATH + '/fe_components/mobile/MINT/index',
axios: SERVER_PATH + '/bower_components/vue2/axios.min',
'emap-mobile': SERVER_PATH + '/fe_components/mobile/emap-mobile.min',
BH_MOBILE: SERVER_PATH + '/fe_components/mobile/BH_MIXIN_SDK',
selectRoleIndex: '../../swpubapp/public/mob/component/selectrole/selectrole',
home: '../../swpubapp/public/mob/component/home/home',
spriteUtils: '../../swpubapp/public/mob/js/spriteUtil',
publicVueComponent: '../../swpubapp/public/mob/component',
'draggable': SERVER_PATH + "/bower_components/vuedraggable/vuedraggable",
'sortable': SERVER_PATH + "/bower_components/sortable/1.5.1/Sortable.min",
emapMin: '../../swpubapp/public/mob/js/emapMin',
pagelog: SERVER_PATH + '/fe_components/sentry/sentry.min',
cropper: SERVER_PATH + '/bower_components/cropper/cropper.min'
},
shim: {
'emap-mobile': {
deps: ['jquery'],
},
'emapMin': {
deps: ['jquery'],
},
'pagelog': {
deps: ['jquery']
}
},
waitSeconds: 0
};
/**
* appLoadAsync用于控制app页面的加载方式
* true: app的所有页面为异步加载,只在使用到时加载
* false: app的所有页面在应用初始化时一次性加载
*/
window.appLoadAsync = false;
//默认的组件库和公共方法以及公共页面
var requir_default_arr = ['jquery', 'vue', 'vueRouter', 'MINT', 'emap-mobile', 'axios', 'spriteUtils', 'draggable', 'emapMin', 'pagelog', 'cropper'];
//封装的公共vue组件
var default_component_arr = [{
name: 'auditProcess',
jsPath: 'publicVueComponent/auditprocess/auditProcess'
}, {
name: 'noneDatas',
jsPath: 'publicVueComponent/nonedatas/nonedatas'
}];
/**
* 用于保存所有模块的全局对象:
* defaultModules:默认的组件库和公共方法以及公共页面
* pageModules:当前应用的所有页面模块
* defaultComponents:封装的公共vue组件
*/
window.REQUIRE_MODULES_ARR = {
defaultModules: requir_default_arr,
pageModules: [],
defaultComponents: default_component_arr
};
//配置require
require.config(requireConfig);
//加载框架所需的库和公共页面
require(requir_default_arr, function($, Vue, VueRouter, mintUI, EMAP_MOBILE, axios, sprite, draggable, emapMin) {
/**
* 用于解决ios 微信虚拟键盘弹出使得页面乱窜的问题
*/
$(document).on("blur", "input,select,textarea", function() {
setTimeout(function() {
const scrollHeight = document.documentElement.scrollTop || document.body.scrollTop || 0;
window.scrollTo(0, Math.max(scrollHeight - 1, 0));
}, 100);
});
//设置拖拽组件
Vue.component('draggable', draggable);
//将各个组件库输出到全局作用域
window.axios = axios;
window.Vue = Vue;
window.VueRouter = VueRouter;
window.mintUI = mintUI;
window.EMAP_MOBILE = EMAP_MOBILE;
window.WIS_EMAP_SERV = emapMin;
//vue路由组件
Vue.use(VueRouter);
//饿了么移动端组件mint-ui
Vue.use(mintUI);
//EMAP相关vue组件
Vue.use(EMAP_MOBILE);
//ids认证
if (userId != null && userId != undefined) {
//获取角色配置相关参数 --> 获取用户授权功能 --> 初始化应用
sprite.getSelRoleConfig().then(sprite.getAuthConfig).then(sprite.initApp);
}
//游客
else {
// 初始化应用--游客模式
sprite.initApp_visitor();
}
});
}(require));
2、对于非游客模式需要ids认证→获取角色配置相关参数 →获取用户授权功能→初始化应用
- sprite.getSelRoleConfig():获取角色配置参数
- sprite.getAuthConfig():自定义的模块加载路径在pageRegister.xml中配置,通过getAuthConfig中/sys/swpubapp/MobileCommon/getMenuInfo.do从后台获取配置文件信息,解析成json格式返回给browser
- sprite.initApp():完成前两步,初始化app
if (userId != null && userId != undefined) {
//获取角色配置相关参数 --> 获取用户授权功能 --> 初始化应用
sprite.getSelRoleConfig().then(sprite.getAuthConfig).then(sprite.initApp);
}
-
/** * 判断是否进入角色选择页 * 如果用户有且只有一个角色,直接渲染该角色有权限的页面,否则进入角色选择页面 */ getSelRoleConfig: function() { var dfd = $.Deferred(); MOB_UTIL.doPost({ url: WIS_CONFIG.ROOT_PATH + '/sys/swpubapp/MobileCommon/getSelRoleConfig.do', params: { APPID: WIS_CONFIG.APPID, APPNAME: WIS_CONFIG.APPNAME } }).done(function(result) { window.IS_NEED_SELECTROLE = result.data.IS_NEED_SELECTROLE; //无需选择角色 if (IS_NEED_SELECTROLE === "0") { roleId = result.data.DEFAULT_ROLEID; } dfd.resolve(); }); return dfd; },
/** * 获取用户授权的页面、按钮 */ getAuthConfig: function(fromSelectRole) { var dfd = $.Deferred(); // IS_NEED_SELECTROLE为1,即需要先选择角色 // 如果url中含有recallUrl参数,表示访问的是问卷调查,不需要进行角色选择 if (!fromSelectRole && window.IS_NEED_SELECTROLE == "1" && (window.location.hash.indexOf('recallUrl') == '-1' && window.location.search.indexOf('recallUrl') == '-1')) { window.REQUIRE_MODULES_ARR.pageModules = [{ vueJsPath: 'selectRoleIndex' }]; dfd.resolve(); } else { //这里在后台去调用查询问卷调查的接口 MOB_UTIL.doPost({ url: WIS_CONFIG.ROOT_PATH + '/sys/swpubapp/MobileCommon/getMenuInfo.do', params: { APPID: WIS_CONFIG.APPID, APPNAME: WIS_CONFIG.APPNAME } }).done(function(result) { //如果发现有问卷需要答,则跳转问卷的地址 if (result.data.NEED_QUESTIONNAIRE) { //这个参数用于标记即将跳转问卷调查地址,无需再做后续的路由解析工作 window.IS_QUESTIONNAIRE = true; //这边替换新的地址 window.location.replace(window.WIS_CONFIG.HOST_PATH + result.data.REDIRECT_URL); dfd.resolve(); } //授权按钮列表 window.MOBILE_BUTTONAUTH_LIST = result.data.BUTTON; //授权页面列表 window.REQUIRE_MODULES_ARR.pageModules = result.data.PAGES; dfd.resolve(); }); } return dfd; }
3、spriteUtil.js -----→sprite.initApp
//初始化应用
initApp: function(callBack) {
addCallback(callBack);
requireAndInit();
},
3、requireAndInit
// 加载组件与页面进行初始化
function requireAndInit() {
//这个参数用于标记即将跳转问卷调查地址,无需再做后续的路由解析工作
if (window.IS_QUESTIONNAIRE) {
//更改状态,避免重复操作
window.IS_QUESTIONNAIRE = false;
return;
}
var require_page_path = []; //页面模块js路径
var require_component_path = []; //公共组件js路径
//设置公共组件路径和页面模块路径
setJsPath(require_page_path, require_component_path);
//需要选择角色
var needSelectRole = window.IS_NEED_SELECTROLE == "1" && require_page_path[0] == "selectRoleIndex";
//如果hash中有recallUrl参数,表示访问的是问卷调查,则不做角色选择
if (window.location.hash.indexOf('recallUrl') != '-1' || window.location.search.indexOf('recallUrl') != '-1') {
needSelectRole = false;
}
//不需要选择角色时,删除selectRole的dom
if (!needSelectRole) {
$('#selectrole').remove();
}
//加载公共组件
require(require_component_path, function() {
//注册公共组件
window.REQUIRE_MODULES_ARR.defaultComponents.forEach(function(defaultComponent) {
Vue.component(defaultComponent.name, spriteUtils.loadComponent(defaultComponent.jsPath));
});
var needSDK = true;
//异步按需加载
if (window.appLoadAsync) {
init(needSDK, needSelectRole);
}
//全部加载
else {
require(require_page_path, function() {
init(needSDK, needSelectRole);
});
}
});
}
4、setJsPath:window.REQUIRE_MODULES_ARR中的页面路径在getAuthConfig中初始化完成
自定义的模块加载路径在pageRegister.xml中配置,通过getAuthConfig中/sys/swpubapp/MobileCommon/getMenuInfo.do从后台获取配置文件信息,解析成json格式返回给browser
/**
* 设置页面与组件的js文件路径
*/
function setJsPath(require_page_path, require_component_path) {
if (window.REQUIRE_MODULES_ARR.pageModules instanceof Array) {
//页面模块js路径
window.REQUIRE_MODULES_ARR.pageModules.forEach(function(pageModule) {
require_page_path.push(pageModule.vueJsPath);
});
}
if (window.REQUIRE_MODULES_ARR.defaultComponents instanceof Array) {
//公共组件js路径
window.REQUIRE_MODULES_ARR.defaultComponents.forEach(function(defaultComponent) {
require_component_path.push(defaultComponent.jsPath);
});
}
}
5、注册公共组件:Vue.component(defaultComponent.name, spriteUtils.loadComponent(defaultComponent.jsPath));
- spriteUtils.loadComponent
-
/** * 加载组件 */ loadComponent: function(path) { return function() { var dfd = $.Deferred(); require([path], function(componentInit) { var component = componentInit(); component.template = compileTpl(component.template); dfd.resolve(component); }); return dfd; }; },
- 使用require加载路径为path的自定义模块,每个自定义模块的格式如下,自定义模块返回一个匿名函数,
-
define(function(require, exports, module) { var tpl = require('text!publicVueComponent/selectrole/selectrole.html'); var spriteUtils = require('spriteUtils'); return function() { var page = { template: tpl, data: function() { return { }; }, created: function() { }, updated: function() { }, methods: { }; return page; }; });
- 该匿名函数在app初始化时,通过require加载,得到函数componentInit,然后执行该函数,即执行return后面的function
- 执行该函数,返回一个page对象,代表当前组件实例,此时数据并未进行初始化,仅得到了一个page对象,该page对象有vue的html模板template和一些列方法
- var component = componentInit();
- component.template = compileTpl(component.template); 正则扫描模板文件,实现按钮权限,删除所有无权限的dom
-
/** * 正则扫描模板文件,实现按钮权限 */ function compileTpl(tpl) { if (!window.MOBILE_BUTTONAUTH_LIST) { window.MOBILE_BUTTONAUTH_LIST = []; } //获取tpl中所有权限id var tplIds = []; var result; var pattern = new RegExp('auth-id=[\'|\"]{1}[^\'^\"]+[\'|\"]{1}', 'gm'); while ((result = pattern.exec(tpl)) != null) { tplIds.push(result[0].substring(9, result[0].length - 1)); }; if (tplIds.length == 0) { return tpl; } //删除所有无权限的dom tplIds.forEach(function(id, index) { if (window.MOBILE_BUTTONAUTH_LIST.indexOf(id) < 0) { var regExp = new RegExp('<[^/].*(auth.*?auth-id=[\'|\"]{1}' + id + '[\'|\"]{1}).*>[\\s\\S]*?</.*auth.*>', 'gm'); tpl = tpl.replace(regExp, ""); } }); return tpl; }
6、应用初始化
//异步按需加载
if (window.appLoadAsync) {
init(needSDK, needSelectRole);
}
//全部加载
else {
require(require_page_path, function() {
init(needSDK, needSelectRole);
});
}
- function init(needSDK, needSelectRole) {}
-
初始化路由
if (needSelectRole) { rootDiv = '#selectrole'; routes = [{ path: '/', name: 'selectrole', component: spriteUtils.loadComponent('selectRoleIndex') }]; } //初始化当前用户有权限访问的页面 else { routes = getVueRoute(); } //生成VueRouter对象 var router = new VueRouter({ routes: routes });
- 路由切换完成后执行的操作
-
router.afterEach(function(to, from, next) { //页面离开时,关闭messagebox mintUI.MessageBox.close(); /** * 当前端组件页面弹出遮罩层,为了控制遮罩层下的文本不滚动, * 在<body></body>与<div id="app"></div>上设置了样式:overflow:hidden;height:100%,锁死了页面。 * 这边手动去除这个样式 */ if (document.body.style.overflow == 'hidden' && document.body.style.height == '100%') { document.body.style.overflow = null; document.body.style.height = null; document.body.firstElementChild.style.overflow = null; document.body.firstElementChild.style.height = null; } /** * 在切换路由后自动执行一个轻微滑动 * 这样写的原因:ios在页面的高度比较高时,从其他页面返回该页面将会出现页面空白的现象 * 需要轻触屏幕进行滑动才能恢复原页面 */ if (!to.meta.keepAlive && !from.meta.keepAlive) { var top = document.body.scrollTop; document.body.scrollTop = top + 1; setTimeout(function() { document.body.scrollTop = top - 1; }, 0); } });
- 路由切换操作1、切换为当前设置的自定义的router和router挂载的自定义div 2、切换为默认路由,挂载为默认的#app上
-
if (needSDK) { initSDKandApp(rootDiv, router); } else { //挂载主vue对象 app = new Vue({ el: '#app', router: router }); finishedCallback() }
- initSDKandApp初始化SDK与应用
-
/** * 初始化SDK与应用 */ function initSDKandApp(rootDiv, router) { if(/dingtalk/.test(navigator.userAgent.toLowerCase())){ getDDSign().then(function(signData) { var config = { //钉钉jdk初始化参数 dd: { corp:signData.corpId, uploadImgsToEmapUrl: WIS_CONFIG.ROOT_PATH + '/sys/swpubapp/MobileCommon/saveFileFromDingding.do' } }; //如果获取到了微信签名,则用该签名对象初始化微信jssdk if ('{}' !== JSON.stringify(signData)) { config.dd.signData = signData; } /** * 判断父窗口中是否加载了SDK,如果加载了则直接使用父窗口的SDK * 这样写的原因:微信SDK在同一页面初始化两次会造成第二次初始化失败 * 即使是iframe嵌套的页面也不行 */ if (window.parent && window.parent.SDK) { window.SDK = window.parent.SDK; //挂载主vue对象 app = new Vue({ el: rootDiv, router: router }); finishedCallback(); return; } //使用BH_MOBILE提供的方法进行SDK的注册 require(['BH_MOBILE'], function(BH_MOBILE) { window.BH_MOBILE = BH_MOBILE; //初始化sdk BH_MOBILE.default(function(res) { window.SDK = res.sdk; //挂载主vue对象 app = new Vue({ el: rootDiv, router: router }); finishedCallback(); }, config); }); }); }else{ getWechatSign().then(function(signData) { var config = { //微信jdk初始化参数 wx: { uploadImgsToEmapUrl: WIS_CONFIG.ROOT_PATH + '/sys/swpubapp/MobileCommon/saveFileFromWechat.do' }, //钉钉jdk初始化参数 dd: {} }; //如果获取到了微信签名,则用该签名对象初始化微信jssdk if ('{}' !== JSON.stringify(signData)) { config.wx.signData = signData; } /** * 判断父窗口中是否加载了SDK,如果加载了则直接使用父窗口的SDK * 这样写的原因:微信SDK在同一页面初始化两次会造成第二次初始化失败 * 即使是iframe嵌套的页面也不行 */ if (window.parent && window.parent.SDK) { window.SDK = window.parent.SDK; //挂载主vue对象 app = new Vue({ el: rootDiv, router: router }); finishedCallback(); return; } //使用BH_MOBILE提供的方法进行SDK的注册 require(['BH_MOBILE'], function(BH_MOBILE) { window.BH_MOBILE = BH_MOBILE; //初始化sdk BH_MOBILE.default(function(res) { window.SDK = res.sdk; //挂载主vue对象 app = new Vue({ el: rootDiv, router: router }); finishedCallback(); }, config); }); }); } }
依据routes生成VueRouter对象:
var router = new VueRouter({routes: routes });
router中有标识为index的页面,默认进入该页面,为展示的第一个页面,只有依据用户交互来切换页面和路由