index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. <template>
  2. <view>
  3. <slot v-if="!nodes.length"/>
  4. <!--#ifdef APP-PLUS-NVUE-->
  5. <web-view id="_top" ref="web" :style="'margin-top:-2px;height:'+height+'px'" @onPostMessage="_message"/>
  6. <!--#endif-->
  7. <!--#ifndef APP-PLUS-NVUE-->
  8. <view id="_top" :style="showAm+(selectable?';user-select:text;-webkit-user-select:text':'')">
  9. <!--#ifdef H5 || MP-360-->
  10. <div :id="'rtf'+uid"></div>
  11. <!--#endif-->
  12. <!--#ifndef H5 || MP-360-->
  13. <trees :nodes="nodes" :lazyLoad="lazyLoad" :loading="loadingImg"/>
  14. <!--#endif-->
  15. </view>
  16. <!--#endif-->
  17. </view>
  18. </template>
  19. <script>
  20. /* eslint-disable */
  21. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  22. import trees from './libs/trees';
  23. var cache = {},
  24. // #ifdef MP-WEIXIN || MP-TOUTIAO
  25. fs = uni.getFileSystemManager ? uni.getFileSystemManager() : null,
  26. // #endif
  27. Parser = require('./libs/MpHtmlParser.js');
  28. var dom;
  29. // 计算 cache 的 key
  30. function hash(str) {
  31. for (var i = str.length, val = 5381; i--;)
  32. val += (val << 5) + str.charCodeAt(i);
  33. return val;
  34. }
  35. // #endif
  36. // #ifdef H5 || APP-PLUS-NVUE || MP-360
  37. var rpx = uni.getSystemInfoSync().windowWidth / 750,
  38. cfg = require('./libs/config.js');
  39. // #endif
  40. // #ifdef APP-PLUS-NVUE
  41. var weexDom = weex.requireModule('dom');
  42. // #endif
  43. /**
  44. * Parser 富文本组件
  45. * @tutorial https://github.com/jin-yufeng/Parser
  46. * @property {String} html 富文本数据
  47. * @property {Boolean} autopause 是否在播放一个视频时自动暂停其他视频
  48. * @property {Boolean} autoscroll 是否自动给所有表格添加一个滚动层
  49. * @property {Boolean} autosetTitle 是否自动将 title 标签中的内容设置到页面标题
  50. * @property {Number} compress 压缩等级
  51. * @property {String} domain 图片、视频等链接的主域名
  52. * @property {Boolean} lazyLoad 是否开启图片懒加载
  53. * @property {String} loadingImg 图片加载完成前的占位图
  54. * @property {Boolean} selectable 是否开启长按复制
  55. * @property {Object} tagStyle 标签的默认样式
  56. * @property {Boolean} showWithAnimation 是否使用渐显动画
  57. * @property {Boolean} useAnchor 是否使用锚点
  58. * @property {Boolean} useCache 是否缓存解析结果
  59. * @event {Function} parse 解析完成事件
  60. * @event {Function} load dom 加载完成事件
  61. * @event {Function} ready 所有图片加载完毕事件
  62. * @event {Function} error 错误事件
  63. * @event {Function} imgtap 图片点击事件
  64. * @event {Function} linkpress 链接点击事件
  65. * @author JinYufeng
  66. * @version 20200615
  67. * @listens MIT
  68. */
  69. export default {
  70. name: 'parser',
  71. data() {
  72. return {
  73. // #ifdef H5 || MP-360
  74. uid: this._uid,
  75. // #endif
  76. // #ifdef APP-PLUS-NVUE
  77. height: 1,
  78. // #endif
  79. // #ifndef APP-PLUS-NVUE
  80. showAm: '',
  81. // #endif
  82. nodes: []
  83. };
  84. },
  85. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  86. components: {
  87. trees
  88. },
  89. // #endif
  90. props: {
  91. html: String,
  92. autopause: {
  93. type: Boolean,
  94. default: true
  95. },
  96. autoscroll: Boolean,
  97. autosetTitle: {
  98. type: Boolean,
  99. default: true
  100. },
  101. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  102. compress: Number,
  103. loadingImg: String,
  104. useCache: Boolean,
  105. // #endif
  106. domain: String,
  107. lazyLoad: Boolean,
  108. selectable: Boolean,
  109. tagStyle: Object,
  110. showWithAnimation: Boolean,
  111. useAnchor: Boolean
  112. },
  113. watch: {
  114. html(html) {
  115. this.setContent(html);
  116. }
  117. },
  118. created() {
  119. // 图片数组
  120. this.imgList = [];
  121. this.imgList.each = function(f) {
  122. for (var i = 0, len = this.length; i < len; i++)
  123. this.setItem(i, f(this[i], i, this));
  124. };
  125. this.imgList.setItem = function(i, src) {
  126. if (i == void 0 || !src) return;
  127. // #ifndef MP-ALIPAY || APP-PLUS
  128. // 去重
  129. if (src.indexOf('http') == 0 && this.includes(src)) {
  130. var newSrc = src.split('://')[0];
  131. for (var j = newSrc.length, c; c = src[j]; j++) {
  132. if (c == '/' && src[j - 1] != '/' && src[j + 1] != '/') break;
  133. newSrc += Math.random() > 0.5 ? c.toUpperCase() : c;
  134. }
  135. newSrc += src.substr(j);
  136. return this[i] = newSrc;
  137. }
  138. // #endif
  139. this[i] = src;
  140. // 暂存 data src
  141. if (src.includes('data:image')) {
  142. var filePath, info = src.match(/data:image\/(\S+?);(\S+?),(.+)/);
  143. if (!info) return;
  144. // #ifdef MP-WEIXIN || MP-TOUTIAO
  145. filePath = `${wx.env.USER_DATA_PATH}/${Date.now()}.${info[1]}`;
  146. fs && fs.writeFile({
  147. filePath,
  148. data: info[3],
  149. encoding: info[2],
  150. success: () => this[i] = filePath
  151. });
  152. // #endif
  153. // #ifdef APP-PLUS
  154. filePath = `_doc/parser_tmp/${Date.now()}.${info[1]}`;
  155. var bitmap = new plus.nativeObj.Bitmap();
  156. bitmap.loadBase64Data(src, () => {
  157. bitmap.save(filePath, {}, () => {
  158. bitmap.clear();
  159. this[i] = filePath;
  160. });
  161. });
  162. // #endif
  163. }
  164. };
  165. },
  166. mounted() {
  167. // #ifdef H5 || MP-360
  168. this.document = document.getElementById('rtf' + this._uid);
  169. // #endif
  170. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  171. if (dom) this.document = new dom(this);
  172. // #endif
  173. // #ifdef APP-PLUS-NVUE
  174. this.document = this.$refs.web;
  175. setTimeout(() => {
  176. // #endif
  177. if (this.html) this.setContent(this.html);
  178. // #ifdef APP-PLUS-NVUE
  179. }, 30);
  180. // #endif
  181. },
  182. beforeDestroy() {
  183. // #ifdef H5 || MP-360
  184. if (this._observer) this._observer.disconnect();
  185. // #endif
  186. this.imgList.each(src => {
  187. // #ifdef APP-PLUS
  188. if (src && src.includes('_doc')) {
  189. plus.io.resolveLocalFileSystemURL(src, entry => {
  190. entry.remove();
  191. });
  192. }
  193. // #endif
  194. // #ifdef MP-WEIXIN || MP-TOUTIAO
  195. if (src && src.includes(uni.env.USER_DATA_PATH))
  196. fs && fs.unlink({
  197. filePath: src
  198. });
  199. // #endif
  200. });
  201. clearInterval(this._timer);
  202. },
  203. methods: {
  204. // #ifdef H5 || APP-PLUS-NVUE || MP-360
  205. _handleHtml(html, append) {
  206. if (!append) {
  207. // 处理 tag-style 和 userAgentStyles
  208. var style = '<style>@keyframes _show{0%{opacity:0}100%{opacity:1}}img{max-width:100%}';
  209. for (var item in cfg.userAgentStyles)
  210. style += `${item}{${cfg.userAgentStyles[item]}}`;
  211. for (item in this.tagStyle)
  212. style += `${item}{${this.tagStyle[item]}}`;
  213. style += '</style>';
  214. html = style + html;
  215. }
  216. // 处理 rpx
  217. if (html.includes('rpx'))
  218. html = html.replace(/[0-9.]+\s*rpx/g, $ => parseFloat($) * rpx + 'px');
  219. return html;
  220. },
  221. // #endif
  222. setContent(html, append) {
  223. // #ifdef APP-PLUS-NVUE
  224. if (!html)
  225. return this.height = 1;
  226. if (append)
  227. this.$refs.web.evalJs('var b=document.createElement(\'div\');b.innerHTML=\'' + html.replace(/'/g, '\\\'') +
  228. '\';document.getElementById(\'parser\').appendChild(b)');
  229. else {
  230. html =
  231. '<meta charset="utf-8" /><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><base href="' +
  232. this.domain + '"><div id="parser"' + (this.selectable ? '>' : ' style="user-select:none">') + this._handleHtml(html).replace(/\n/g, '\\n') +
  233. '</div><script>"use strict";function e(e){if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){var t={data:[e]};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(t):window.__dcloud_weex_.postMessage(JSON.stringify(t))}}' +
  234. (this.showWithAnimation ? 'document.body.style.animation="_show .5s",' : '') +
  235. 'setTimeout(function(){e({action:"load",text:document.body.innerText,height:document.getElementById("parser").scrollHeight+16})},50);\x3c/script>';
  236. this.$refs.web.evalJs('document.write(\'' + html.replace(/'/g, '\\\'') + '\');document.close()');
  237. }
  238. this.$refs.web.evalJs(
  239. 'var t=document.getElementsByTagName("title");t.length&&e({action:"getTitle",title:t[0].innerText});for(var o,n=document.getElementsByTagName("style"),r=0;o=n[r++];)o.innerHTML=o.innerHTML.replace(/body/g,"#parser");for(var i,a=document.getElementsByTagName("img"),s=[],c=0,l=0;i=a[c];c++)i.onerror=function(){' +
  240. (cfg.errorImg ? 'this.src="' + cfg.errorImg + '",' : '') +
  241. 'e({action:"error",source:"img",target:this})},i.hasAttribute("ignore")||"A"==i.parentElement.nodeName||(i.i=l++,s.push(i.src),i.onclick=function(){e({action:"preview",img:{i:this.i,src:this.src}})});e({action:"getImgList",imgList:s});for(var d,u=document.getElementsByTagName("a"),g=0;d=u[g];g++)d.onclick=function(){var t,o=this.getAttribute("href");if("#"==o[0]){var n=document.getElementById(o.substr(1));n&&(t=n.offsetTop)}return e({action:"linkpress",href:o,offset:t}),!1};for(var m,f=document.getElementsByTagName("video"),h=0;m=f[h];h++)m.style.maxWidth="100%",m.onerror=function(){e({action:"error",source:"video",target:this})}' +
  242. (this.autopause ? ',m.onplay=function(){for(var e,t=0;e=f[t];t++)e!=this&&e.pause()}' : '') +
  243. ';for(var v,y=document.getElementsByTagName("audio"),_=0;v=y[_];_++)v.onerror=function(){e({action:"error",source:"audio",target:this})};' +
  244. (this.autoscroll ? 'for(var p,w=document.getElementsByTagName("table"),T=0;p=w[T];T++){var E=document.createElement("div");E.style.overflow="scroll",p.parentNode.replaceChild(E,p),E.appendChild(p)}' : '') +
  245. '(function(){return new Promise(function(e){var t=document.getElementById("parser"),o=t.scrollHeight,n=setInterval(function(){o==t.scrollHeight?(clearInterval(n),e(o)):o=t.scrollHeight},500)})})().then(function(t){e({action:"ready",height:t+16})})'
  246. );
  247. this.nodes = [1];
  248. // #endif
  249. // #ifdef H5 || MP-360
  250. if (!html) {
  251. if (this.rtf && !append) this.rtf.parentNode.removeChild(this.rtf);
  252. return;
  253. }
  254. var div = document.createElement('div');
  255. if (!append) {
  256. if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
  257. this.rtf = div;
  258. } else {
  259. if (!this.rtf) this.rtf = div;
  260. else this.rtf.appendChild(div);
  261. }
  262. div.innerHTML = this._handleHtml(html, append);
  263. for (var styles = this.rtf.getElementsByTagName('style'), i = 0, style; style = styles[i++];) {
  264. style.innerHTML = style.innerHTML.replace(/body/g, '#rtf' + this._uid);
  265. style.setAttribute('scoped', 'true');
  266. }
  267. // 懒加载
  268. if (!this._observer && this.lazyLoad && IntersectionObserver) {
  269. this._observer = new IntersectionObserver(changes => {
  270. for (let item, i = 0; item = changes[i++];) {
  271. if (item.isIntersecting) {
  272. item.target.src = item.target.getAttribute('data-src');
  273. item.target.removeAttribute('data-src');
  274. this._observer.unobserve(item.target);
  275. }
  276. }
  277. }, {
  278. rootMargin: '500px 0px 500px 0px'
  279. });
  280. }
  281. var _ts = this;
  282. // 获取标题
  283. var title = this.rtf.getElementsByTagName('title');
  284. if (title.length && this.autosetTitle)
  285. uni.setNavigationBarTitle({
  286. title: title[0].innerText
  287. });
  288. // 图片处理
  289. this.imgList.length = 0;
  290. var imgs = this.rtf.getElementsByTagName('img');
  291. for (let i = 0, j = 0, img; img = imgs[i]; i++) {
  292. var src = img.getAttribute('src');
  293. if (this.domain && src) {
  294. if (src[0] == '/') {
  295. if (src[1] == '/')
  296. img.src = (this.domain.includes('://') ? this.domain.split('://')[0] : '') + ':' + src;
  297. else img.src = this.domain + src;
  298. } else if (!src.includes('://')) img.src = this.domain + '/' + src;
  299. }
  300. if (!img.hasAttribute('ignore') && img.parentElement.nodeName != 'A') {
  301. img.i = j++;
  302. _ts.imgList.push(img.src || img.getAttribute('data-src'));
  303. img.onclick = function() {
  304. var preview = true;
  305. this.ignore = () => preview = false;
  306. _ts.$emit('imgtap', this);
  307. if (preview) {
  308. uni.previewImage({
  309. current: this.i,
  310. urls: _ts.imgList
  311. });
  312. }
  313. };
  314. }
  315. img.onerror = function() {
  316. if (cfg.errorImg)
  317. _ts.imgList[this.i] = this.src = cfg.errorImg;
  318. _ts.$emit('error', {
  319. source: 'img',
  320. target: this
  321. });
  322. };
  323. if (_ts.lazyLoad && this._observer && img.src && img.i != 0) {
  324. img.setAttribute('data-src', img.src);
  325. img.removeAttribute('src');
  326. this._observer.observe(img);
  327. }
  328. }
  329. // 链接处理
  330. var links = this.rtf.getElementsByTagName('a');
  331. for (var link of links) {
  332. link.onclick = function() {
  333. var jump = true,
  334. href = this.getAttribute('href');
  335. _ts.$emit('linkpress', {
  336. href,
  337. ignore: () => jump = false
  338. });
  339. if (jump && href) {
  340. if (href[0] == '#') {
  341. if (_ts.useAnchor) {
  342. _ts.navigateTo({
  343. id: href.substr(1)
  344. });
  345. }
  346. } else if (href.indexOf('http') == 0 || href.indexOf('//') == 0)
  347. return true;
  348. else
  349. uni.navigateTo({
  350. url: href
  351. });
  352. }
  353. return false;
  354. };
  355. }
  356. // 视频处理
  357. var videos = this.rtf.getElementsByTagName('video');
  358. _ts.videoContexts = videos;
  359. for (let video, i = 0; video = videos[i++];) {
  360. video.style.maxWidth = '100%';
  361. video.onerror = function() {
  362. _ts.$emit('error', {
  363. source: 'video',
  364. target: this
  365. });
  366. };
  367. video.onplay = function() {
  368. if (_ts.autopause)
  369. for (let item, i = 0; item = _ts.videoContexts[i++];)
  370. if (item != this) item.pause();
  371. };
  372. }
  373. // 音频处理
  374. var audios = this.rtf.getElementsByTagName('audio');
  375. for (var audio of audios)
  376. audio.onerror = function() {
  377. _ts.$emit('error', {
  378. source: 'audio',
  379. target: this
  380. });
  381. };
  382. // 表格处理
  383. if (this.autoscroll) {
  384. var tables = this.rtf.getElementsByTagName('table');
  385. for (var table of tables) {
  386. let div = document.createElement('div');
  387. div.style.overflow = 'scroll';
  388. table.parentNode.replaceChild(div, table);
  389. div.appendChild(table);
  390. }
  391. }
  392. if (!append) this.document.appendChild(this.rtf);
  393. this.$nextTick(() => {
  394. this.nodes = [1];
  395. this.$emit('load');
  396. });
  397. setTimeout(() => this.showAm = '', 500);
  398. // #endif
  399. // #ifndef APP-PLUS-NVUE
  400. // #ifndef H5 || MP-360
  401. var nodes;
  402. if (!html) return this.nodes = [];
  403. var parser = new Parser(html, this);
  404. // 缓存读取
  405. if (this.useCache) {
  406. var hashVal = hash(html);
  407. if (cache[hashVal])
  408. nodes = cache[hashVal];
  409. else {
  410. nodes = parser.parse();
  411. cache[hashVal] = nodes;
  412. }
  413. } else nodes = parser.parse();
  414. this.$emit('parse', nodes);
  415. if (append) this.nodes = this.nodes.concat(nodes);
  416. else this.nodes = nodes;
  417. if (nodes.length && nodes.title && this.autosetTitle)
  418. uni.setNavigationBarTitle({
  419. title: nodes.title
  420. });
  421. if (this.imgList) this.imgList.length = 0;
  422. this.videoContexts = [];
  423. this.$nextTick(() => {
  424. (function f(cs) {
  425. for (var i = cs.length; i--;) {
  426. if (cs[i].top) {
  427. cs[i].controls = [];
  428. cs[i].init();
  429. f(cs[i].$children);
  430. }
  431. }
  432. })(this.$children);
  433. this.$emit('load');
  434. });
  435. // #endif
  436. var height;
  437. clearInterval(this._timer);
  438. this._timer = setInterval(() => {
  439. // #ifdef H5 || MP-360
  440. this.rect = this.rtf.getBoundingClientRect();
  441. // #endif
  442. // #ifndef H5 || MP-360
  443. uni.createSelectorQuery().in(this)
  444. .select('#_top').boundingClientRect().exec(res => {
  445. if (!res) return;
  446. this.rect = res[0];
  447. // #endif
  448. if (this.rect.height == height) {
  449. this.$emit('ready', this.rect);
  450. clearInterval(this._timer);
  451. }
  452. height = this.rect.height;
  453. // #ifndef H5 || MP-360
  454. });
  455. // #endif
  456. }, 350);
  457. if (this.showWithAnimation && !append) this.showAm = 'animation:_show .5s';
  458. // #endif
  459. },
  460. getText(ns = this.nodes) {
  461. var txt = '';
  462. // #ifdef APP-PLUS-NVUE
  463. txt = this._text;
  464. // #endif
  465. // #ifdef H5 || MP-360
  466. txt = this.rtf.innerText;
  467. // #endif
  468. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  469. for (var i = 0, n; n = ns[i++];) {
  470. if (n.type == 'text') txt += n.text.replace(/&nbsp;/g, '\u00A0').replace(/&lt;/g, '<').replace(/&gt;/g, '>')
  471. .replace(/&amp;/g, '&');
  472. else if (n.type == 'br') txt += '\n';
  473. else {
  474. // 块级标签前后加换行
  475. var block = n.name == 'p' || n.name == 'div' || n.name == 'tr' || n.name == 'li' || (n.name[0] == 'h' && n.name[1] >
  476. '0' && n.name[1] < '7');
  477. if (block && txt && txt[txt.length - 1] != '\n') txt += '\n';
  478. if (n.children) txt += this.getText(n.children);
  479. if (block && txt[txt.length - 1] != '\n') txt += '\n';
  480. else if (n.name == 'td' || n.name == 'th') txt += '\t';
  481. }
  482. }
  483. // #endif
  484. return txt;
  485. },
  486. navigateTo(obj) {
  487. if (!this.useAnchor)
  488. return obj.fail && obj.fail({
  489. errMsg: 'Anchor is disabled'
  490. });
  491. // #ifdef APP-PLUS-NVUE
  492. if (!obj.id)
  493. weexDom.scrollToElement(this.$refs.web);
  494. else
  495. this.$refs.web.evalJs('var pos=document.getElementById("' + obj.id +
  496. '");if(pos)post({action:"linkpress",href:"#",offset:pos.offsetTop+' + (obj.offset || 0) + '})');
  497. obj.success && obj.success({
  498. errMsg: 'pageScrollTo:ok'
  499. });
  500. // #endif
  501. // #ifdef H5 || MP-360
  502. if (!obj.id) {
  503. window.scrollTo(0, this.rtf.offsetTop);
  504. return obj.success && obj.success({
  505. errMsg: 'pageScrollTo:ok'
  506. });
  507. }
  508. var target = document.getElementById(obj.id);
  509. if (!target) return obj.fail && obj.fail({
  510. errMsg: 'Label not found'
  511. });
  512. obj.scrollTop = this.rtf.offsetTop + target.offsetTop + (obj.offset || 0);
  513. uni.pageScrollTo(obj);
  514. // #endif
  515. // #ifndef H5 || APP-PLUS-NVUE || MP-360
  516. var d = ' ';
  517. // #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
  518. d = '>>>';
  519. // #endif
  520. uni.createSelectorQuery().in(this).select('#_top' + (obj.id ? d + '#' + obj.id + ',#_top' + d + '.' + obj.id : '')).boundingClientRect()
  521. .selectViewport().scrollOffset().exec(res => {
  522. if (!res || !res[0])
  523. return obj.fail && obj.fail({
  524. errMsg: 'Label not found'
  525. });
  526. obj.scrollTop = res[1].scrollTop + res[0].top + (obj.offset || 0);
  527. // #ifdef MP-ALIPAY
  528. obj.duration = 300;
  529. my.
  530. // #endif
  531. // #ifndef MP-ALIPAY
  532. uni.
  533. // #endif
  534. pageScrollTo(obj);
  535. });
  536. // #endif
  537. },
  538. getVideoContext(id) {
  539. // #ifndef APP-PLUS-NVUE
  540. if (!id) return this.videoContexts;
  541. else
  542. for (var i = this.videoContexts.length; i--;)
  543. if (this.videoContexts[i].id == id) return this.videoContexts[i];
  544. // #endif
  545. },
  546. // #ifdef APP-PLUS-NVUE
  547. _message(e) {
  548. // 接收 web-view 消息
  549. var data = e.detail.data[0];
  550. if (data.action == 'load') {
  551. this.$emit('load');
  552. this.height = data.height;
  553. this._text = data.text;
  554. } else if (data.action == 'getTitle') {
  555. if (this.autosetTitle)
  556. uni.setNavigationBarTitle({
  557. title: data.title
  558. });
  559. } else if (data.action == 'getImgList') {
  560. this.imgList.length = 0;
  561. for (var i = data.imgList.length; i--;)
  562. this.imgList.setItem(i, data.imgList[i]);
  563. } else if (data.action == 'preview') {
  564. var preview = true;
  565. data.img.ignore = () => preview = false;
  566. this.$emit('imgtap', data.img);
  567. if (preview)
  568. uni.previewImage({
  569. current: data.img.i,
  570. urls: this.imgList
  571. });
  572. } else if (data.action == 'linkpress') {
  573. var jump = true,
  574. href = data.href;
  575. this.$emit('linkpress', {
  576. href,
  577. ignore: () => jump = false
  578. });
  579. if (jump && href) {
  580. if (href[0] == '#') {
  581. if (this.useAnchor)
  582. weexDom.scrollToElement(this.$refs.web, {
  583. offset: data.offset
  584. });
  585. } else if (href.includes('://'))
  586. plus.runtime.openWeb(href);
  587. else
  588. uni.navigateTo({
  589. url: href
  590. });
  591. }
  592. } else if (data.action == 'error') {
  593. if (data.source == 'img' && cfg.errorImg)
  594. this.imgList.setItem(data.target.i, cfg.errorImg);
  595. this.$emit('error', {
  596. source: data.source,
  597. target: data.target
  598. });
  599. } else if (data.action == 'ready') {
  600. this.height = data.height;
  601. this.$nextTick(() => {
  602. uni.createSelectorQuery().in(this).select('#_top').boundingClientRect().exec(res => {
  603. this.rect = res[0];
  604. this.$emit('ready', res[0]);
  605. });
  606. });
  607. }
  608. }
  609. // #endif
  610. }
  611. };
  612. </script>
  613. <style>
  614. @keyframes _show {
  615. 0% {
  616. opacity: 0;
  617. }
  618. 100% {
  619. opacity: 1;
  620. }
  621. }
  622. /* #ifdef MP-WEIXIN */
  623. :host {
  624. display: block;
  625. overflow: scroll;
  626. -webkit-overflow-scrolling: touch;
  627. }
  628. /* #endif */
  629. </style>