完整代码片段见: https://www.yuque.com/g/lingjun-nb4x6/owsx4w/folder/24602615

H5迁移进微信小程序内,主要问题:

微信小程序内websocket链接openfire服务,同Vue项目下主要区别在于:

1- ObjTree.js jkl-dumper.js 在微信小程序内不可直接使用,需改造成微信小程序识别的模块化方法;
2- H5页面内,websocket长连接openfire,发送+接收消息都 在一个H5页面内,无需处理不同页面间的消息同步问题;
3- H5页面内,登录验证时,Base64编码用的浏览器自带的,var token = window.btoa(temp);

解决方案:

针对1:将ObjTree.js jkl-dumper.js 改造成微信小程序识别的模块化方法;
针对2:小程序内引入broadcast.js 广播js;在spp.js中消息发送成功后+接收到消息后,通过发送广播,告知imChat.js,处理后续逻辑。
针对3:使用 base64src.Str2b64() 对权限验证时的temp进行base64处理;

重点关注:

1- ObjTree.js 改造:

统一说明:
灰色背景为原H5页面内,js定义方法;
浅蓝色背景为小程序改造后js定义;
各方法名修改后,对应的调用也需要修改,在下文编著中未体现;
// ========================================================================
// XML.ObjTree — XML source code from/to JavaScript object like E4X
// ========================================================================
// v引入XmlDom转换js对象,在将XML字符串转换成XML对象时用到。parseXML()
var Parse = require(‘../xmlDom/dom-parser’)
// if ( typeof(XML) == ‘undefined’ ) XML = function() {};
const XML = () =>{
}
// constructor
// XML.ObjTree = function () {
// return this;
// };
const ObjTree = function () {
return this;
};
// class variables
// XML.ObjTree.VERSION = “0.23”;
const VERSION = “0.23”;
// object prototype
// XML.ObjTree.prototype.xmlDecl = ‘<?xml version=”1.0” encoding=”UTF-8” ?>\n’;
// XML.ObjTree.prototype.attr_prefix = ‘-‘;
const xmlDecl = ‘<?xml version=”1.0” encoding=”UTF-8” ?>\n’;
const attr_prefix = ‘-‘;
// 生命的全局变量
const force_array=[]
const force_array=[]
// method: parseXML( xmlsource )
// XML.ObjTree.prototype.parseXML = function ( xml ) {
// var root;
// if ( window.DOMParser ) {
// var xmldom = new DOMParser();
// // xmldom.async = false; // DOMParser is always sync-mode
// var dom = xmldom.parseFromString( xml, “application/xml” );
// if ( ! dom ) return;
// root = dom.documentElement;
// } else if ( window.ActiveXObject ) {
// xmldom = new ActiveXObject(‘Microsoft.XMLDOM’);
// xmldom.async = false;
// xmldom.loadXML( xml );
// root = xmldom.documentElement;
// }
// if ( ! root ) return;
// return this.parseDOM( root );
// };
// 使用映入的Parse 对象,处理XML字符串,转换为XML对象
const parseXML = function ( xml ) {
var XMLParse = new Parse.DOMParser();
var doc = XMLParse.parseFromString(xml);
return parseDOM( doc );
};
// method: parseHTTP( url, options, callback )
// XML.ObjTree.prototype.parseHTTP = function ( url, options, callback ) {
const parseHTTP = function ( url, options, callback ) {
var myopt = {};
for( var key in options ) {
myopt[key] = options[key]; // copy object
}
if ( ! myopt.method ) {
if ( typeof(myopt.postBody) == “undefined” &&
typeof(myopt.postbody) == “undefined” &&
typeof(myopt.parameters) == “undefined” ) {
myopt.method = “get”;
} else {
myopt.method = “post”;
}
}
if ( callback ) {
myopt.asynchronous = true; // async-mode
// var
this = this;
var func = callback;
var
save = myopt.onComplete;
myopt.onComplete = function ( trans ) {
var tree;
if ( trans && trans.responseXML && trans.responseXML.documentElement ) {
tree = parseDOM( trans.responseXML.documentElement );
}
func( tree, trans );
if (
save ) save( trans );
};
} else {
myopt.asynchronous = false; // sync-mode
}
var trans;
if ( typeof(HTTP) != “undefined” && HTTP.Request ) {
myopt.uri = url;
var req = new HTTP.Request( myopt ); // JSAN
if ( req ) trans = req.transport;
} else if ( typeof(Ajax) != “undefined” && Ajax.Request ) {
var req = new Ajax.Request( url, myopt ); // ptorotype.js
if ( req ) trans = req.transport;
}
if ( callback ) return trans;
if ( trans && trans.responseXML && trans.responseXML.documentElement ) {
return parseDOM( trans.responseXML.documentElement );
}
}
// method: parseDOM( documentroot )
// XML.ObjTree.prototype.parseDOM = function ( root ) {
const parseDOM = function ( root ) {
if ( ! root ) return;
var
force_array = {};
if ( force_array ) {
for( var i=0; i force_array[force_array[i]] = 1;
}
}
var json = parseElement( root ); // parse root node
if (
force_array[root.nodeName] ) {
json = [ json ];
}
if ( root.nodeType != 11 ) { // DOCUMENT_FRAGMENT_NODE
var tmp = {};
tmp[root.nodeName] = json; // root nodeName
json = tmp;
}
var document = json[“#document”];
if(document){
return document;
}
return json;
};
// method: parseElement( element )
// XML.ObjTree.prototype.parseElement = function ( elem ) {
const parseElement = function ( elem ) {
// COMMENT_NODE
if ( elem.nodeType == 7 ) {
return;
}
// TEXT_NODE CDATA_SECTION_NODE
if ( elem.nodeType == 3 || elem.nodeType == 4 ) {
var bool = elem.nodeValue.match( /[^\x00-\x20]/ );
if ( bool == null ) return; // ignore white spaces
return elem.nodeValue;
}
var retval;
var cnt = {};
// parse attributes
if ( elem.attributes && elem.attributes.length ) {
retval = {};
for ( var i=0; i var key = elem.attributes[i].nodeName;
if ( typeof(key) != “string” ) continue;
var val = elem.attributes[i].nodeValue;
if ( ! val ) continue;
key = attr_prefix + key;
if ( typeof(cnt[key]) == “undefined” ) cnt[key] = 0;
cnt[key] ++;
addNode( retval, key, cnt[key], val );
}
}
// parse child nodes (recursive)
if ( elem.childNodes && elem.childNodes.length ) {
var textonly = true;
if ( retval ) textonly = false; // some attributes exists
for ( var i=0; i var ntype = elem.childNodes[i].nodeType;
if ( ntype == 3 || ntype == 4 ) continue;
textonly = false;
}
if ( textonly ) {
if ( ! retval ) retval = “”;
for ( var i=0; i retval += elem.childNodes[i].nodeValue;
}
} else {
if ( ! retval ) retval = {};
for ( var i=0; i var key = elem.childNodes[i].nodeName;
if ( typeof(key) != “string” ) continue;
var val = parseElement( elem.childNodes[i] );
if ( ! val ) continue;
if ( typeof(cnt[key]) == “undefined” ) cnt[key] = 0;
cnt[key] ++;
addNode( retval, key, cnt[key], val );
}
}
}
return retval;
};
// method: addNode( hash, key, count, value )
// XML.ObjTree.prototype.addNode = function ( hash, key, cnts, val ) {
const addNode = function ( hash, key, cnts, val ) {
if ( __force_array[key] ) {
if ( cnts == 1 ) hash[key] = [];
hash[key][hash[key].length] = val; // push
} else if ( cnts == 1 ) { // 1st sibling
hash[key] = val;
} else if ( cnts == 2 ) { // 2nd sibling
hash[key] = [ hash[key], val ];
} else { // 3rd sibling and more
hash[key][hash[key].length] = val;
}
};
// method: writeXML( tree )
// XML.ObjTree.prototype.writeXML = function ( tree ) {
const writeXML = function ( tree ) {
var xml = hash_to_xml( null, tree );
return xmlDecl + xml;
};
// method: hash_to_xml( tagName, tree )
// XML.ObjTree.prototype.hash_to_xml = function ( name, tree ) {
const hash_to_xml = function ( name, tree ) {
var elem = [];
var attr = [];
for( var key in tree ) {
if ( ! tree.hasOwnProperty(key) ) continue;
var val = tree[key];
if ( key.charAt(0) != attr_prefix ) {
if ( typeof(val) == “undefined” || val == null ) {
elem[elem.length] = “<”+key+” />”;
} else if ( typeof(val) == “object” && val.constructor == Array ) {
elem[elem.length] = array_to_xml( key, val );
} else if ( typeof(val) == “object” ) {
elem[elem.length] = hash_to_xml( key, val );
} else {
elem[elem.length] = scalar_to_xml( key, val );
}
} else {
attr[attr.length] = “ “+(key.substring(1))+’=”‘+(xml_escape( val ))+’”‘;
}
}
var jattr = attr.join(“”);
var jelem = elem.join(“”);
if ( typeof(name) == “undefined” || name == null ) {
// no tag
} else if ( elem.length > 0 ) {
if ( jelem.match( /\n/ )) {
jelem = “<”+name+jattr+”>\n”+jelem+”</“+name+”>\n”;
} else {
jelem = “<”+name+jattr+”>” +jelem+”</“+name+”>\n”;
}
} else {
jelem = “<”+name+jattr+” />\n”;
}
return jelem;
};
// method: array_to_xml( tagName, array )
// XML.ObjTree.prototype.array_to_xml = function ( name, array ) {
const array_to_xml = function ( name, array ) {
var out = [];
for( var i=0; i var val = array[i];
if ( typeof(val) == “undefined” || val == null ) {
out[out.length] = “<”+name+” />”;
} else if ( typeof(val) == “object” && val.constructor == Array ) {
out[out.length] = array_to_xml( name, val );
} else if ( typeof(val) == “object” ) {
out[out.length] = hash_to_xml( name, val );
} else {
out[out.length] = scalar_to_xml( name, val );
}
}
return out.join(“”);
};
// method: scalar_to_xml( tagName, text )
// XML.ObjTree.prototype.scalar_to_xml = function ( name, text ) {
const scalar_to_xml = function ( name, text ) {
if ( name == “#text” ) {
return xml_escape(text);
} else {
return “<”+name+”>”+xml_escape(text)+”</“+name+”>\n”;
}
};
// method: xml_escape( text )
// XML.ObjTree.prototype.xml_escape = function ( text ) {
const xml_escape = function ( text ) {
return text.replace(/&/g,’&’).replace(//g,’>’).replace(/“/g,’"’);
};
//模块化:暴露方法:其他js 文件中,引入可直接调用
module.exports.XML = XML
exports.ObjTree = ObjTree
exports.writeXML = writeXML
exports.parseXML = parseXML