1、spriteFrame.js
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('[\\s\\S]*?', '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();
/**
* 当前端组件页面弹出遮罩层,为了控制遮罩层下的文本不滚动,
* 在与上设置了样式: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的页面,默认进入该页面,为展示的第一个页面,只有依据用户交互来切换页面和路由
作者:flybone7