可以看出模版中的内容展示部分用了蛮多的block加判断语句wx:if wx:elif wx:else。这些都是为了需要根据解析后的内容类型来判断需要展示什么标签和样式。解析后的内容大概格式是这样的:
{ body: [ title: '标题', author: '作者', bio: '签名', avatar: '头像', more: '更多地址', content: [ //内容 { type: 'p', value: '普通段落内容' }, { type: 'img', value: 'http://xxx.xx.xx/1.jpg' }, { type: 'pem', value: '...' }, ... ] ], ... }需要注意的一点是主题日报有时候返回的html内容是经过unicode编码的不能直接显示,里边全是类似&#xxxx;的字符,这需要单独为主题日报的日报详情解析编码,微信小程序是不会解析特殊符号的,我们要手动转换,这里只转了最常用几个。
再点击主题日报中的列表项是,传递一个标记是主题日报的参数theme
//跳转到日报详情页 toDetailPage: function( e ) { var id = e.currentTarget.dataset.id; wx.navigateTo( { url: '../detail/detail?theme=1&id=' + id }); },然后在Detail.js的onLoad事件中接受参数
//获取列表残过来的参数 id:日报id, theme:是否是主题日报内容(因为主题日报的内容有些需要单独解析) onLoad: function( options ) { var id = options.id; var isTheme = options[ 'theme' ]; this.setData( { id: id, isTheme: isTheme }); },之后开始请求接口获取日报详情,并根据是否是主题日报进行个性化解析
//加载页面相关数据 function loadData() { var _this = this; var id = this.data.id; var isTheme = this.data.isTheme; //获取日报详情内容 _this.setData( { loading: true }); requests.getNewsDetail( id, ( data ) => { data.body = utils.parseStory( data.body, isTheme ); _this.setData( { news: data, pageShow: 'block' }); wx.setNavigationBarTitle( { title: data.title }); //设置标题 }, null, () => { _this.setData( { loading: false }); }); }以上传入一个isTheme参数进入解析方法,解析方法根据此参数判断是否需要进行单独的编码解析。
内容解析的库代码比较多,就不贴出了,可以到git上查看。这里给出解析的封装。
var HtmlParser = require( 'htmlParseUtil.js' ); String.prototype.trim = function() { return this.replace( /(^\s*)|(\s*$)/g, '' ); } String.prototype.isEmpty = function() { return this.trim() == ''; } /** * 快捷方法 获取HtmlParser对象 * @param {string} html html文本 * @return {object} HtmlParser */ function $( html ) { return new HtmlParser( html ); } /** * 解析story对象的body部分 * @param {string} html body的html文本 * @param {boolean} isDecode 是否需要unicode解析 * @return {object} 解析后的对象 */ function parseStory( html, isDecode ) { var questionArr = $( html ).tag( 'div' ).attr( 'class', 'question' ).match(); var stories = []; var $story; if( questionArr ) { for( var i = 0, len = questionArr.length;i < len;i++ ) { $story = $( questionArr[ i ] ); stories.push( { title: getArrayContent( $story.tag( 'h2' ).attr( 'class', 'question-title' ).match() ), avatar: getArrayContent( getArrayContent( $story.tag( 'div' ).attr( 'class', 'meta' ).match() ).jhe_ma( 'img', 'src' ) ), author: getArrayContent( $story.tag( 'span' ).attr( 'class', 'author' ).match() ), bio: getArrayContent( $story.tag( 'span' ).attr( 'class', 'bio' ).match() ), content: parseStoryContent( $story, isDecode ), more: getArrayContent( getArrayContent( $( html ).tag( 'div' ).attr( 'class', 'view-more' ).match() ).jhe_ma( 'a', 'href' ) ) }); } } return stories; } /** * 解析文章内容 * @param {string} $story htmlparser对象 * @param {boolean} isDecode 是否需要unicode解析 * @returb {object} 文章内容对象 */ function parseStoryContent( $story, isDecode ) { var content = []; var ps = $story.tag( 'p' ).match(); var p, strong, img, blockquote, em; if( ps ) { for( var i = 0, len = ps.length;i < len;i++ ) { p = transferSign(ps[ i ]); //获取<p>的内容 ,并将特殊符号转义 if( !p || p.isEmpty() ) continue; img = getArrayContent(( p.jhe_ma( 'img', 'src' ) ) ); strong = getArrayContent( p.jhe_om( 'strong' ) ); em = getArrayContent( p.jhe_om( 'em' ) ); blockquote = getArrayContent( p.jhe_om( 'blockquote' ) ); if( !img.isEmpty() ) { //获取图片 img=img.replace("pic1","pic3"); img=img.replace("pic2","pic3"); content.push( { type: 'img', value: img }); } else if( isOnly( p, strong ) ) { //获取加粗段落<p><strong>...</strong></p> strong = decodeHtml( strong, isDecode ); if( !strong.isEmpty() ) content.push( { type: 'pstrong', value: strong }); } else if( isOnly( p, em ) ) { //获取强调段落 <p><em>...</em></p> em = decodeHtml( em, isDecode ); if( !em.isEmpty() ) content.push( { type: 'pem', value: em }); } else if( isOnly( p, blockquote ) ) { //获取引用块 <p><blockquote>...</blockquote></p> blockquote = decodeHtml( blockquote, isDecode ); if( !blockquote.isEmpty() ) content.push( { type: 'blockquote', value: blockquote }); } else { //其他类型 归类为普通段落 ....太累了 不想解析了T_T p = decodeHtml( p, isDecode ); if( !p.isEmpty() ) content.push( { type: 'p', value: p }); } } } return content; } /** * 取出多余或者难以解析的html并且替换转义符号 */ function decodeHtml( value, isDecode ) { if( !value ) return ''; value = value.replace( /<[^>]+>/g, '' ) .replace( / /g, ' ' ) .replace( /“/g, '"' ) .replace( /”/g, '"' ).replace( /·/g, '·' ); if( isDecode ) return decodeUnicode( value.replace( /&#/g, '\\u' ) ); return value; } /** * 解析段落的unicode字符,主题日报中的内容又很多是编码过的 */ function decodeUnicode( str ) { var ret = ''; var splits = str.split( ';' ); for( let i = 0;i < splits.length;i++ ) { ret += spliteDecode( splits[ i ] ); } return ret; }; /** * 解析单个unidecode字符 */ function spliteDecode( value ) { var target = value.match( /\\u\d+/g ); if( target && target.length > 0 ) { //解析类似 "7.1 \u20998" 参杂其他字符 target = target[ 0 ]; var temp = value.replace( target, '{{@}}' ); target = target.replace( '\\u', '' ); target = String.fromCharCode( parseInt( target ) ); return temp.replace( "{{@}}", target ); } else { // value = value.replace( '\\u', '' ); // return String.fromCharCode( parseInt( value, '10' ) ) return value; } } /** * 获取数组中的内容(一般为第一个元素) * @param {array} arr 内容数组 * @return {string} 内容 */ function getArrayContent( arr ) { if( !arr || arr.length == 0 ) return ''; return arr[ 0 ]; } function isOnly( src, target ) { return src.trim() == target; } module.exports = { parseStory: parseStory } /** * 将转义字符转为实体 * @param data * @returns {*} */ function transferSign(data){ data=data.replace(/–/g,"–"); data=data.replace(/—/g,"—"); data=data.replace(/…/g,"…"); data=data.replace(/•/g,""); data=data.replace(/’/g,"’"); data=data.replace(/–/g,"–"); return data; }代码的解析过程比较繁杂,大家可以根据返回的html结构和参照解析库的作者写的文章来解读。
底部工具栏