/** * @fileoverview 递归子组件,用于显示节点树 */ Component({ data: { ctrl: {}, // 控制信号 // #ifdef MP-WEIXIN isiOS: wx.getSystemInfoSync().system.includes('iOS') // #endif }, properties: { childs: Array, // 子节点列表 opts: Array // 设置 [是否开启懒加载, 加载中占位图, 错误占位图, 是否使用长按菜单] }, options: { addGlobalClass: true }, // #ifndef MP-TOUTIAO attached () { // #ifndef MP-ALIPAY this.triggerEvent('add', this, { bubbles: true, composed: true }) // #endif // #ifdef MP-ALIPAY this.props.onAdd(this) // #endif }, // #endif methods: { noop () { }, /** * @description 获取标签 * @param {String} path 路径 */ getNode (path) { try { const nums = path.split('_') let node = this.properties.childs[nums[0]] for (let i = 1; i < nums.length; i++) { node = node.children[nums[i]] } return node } catch { return { text: '', attrs: {}, children: [] } } }, /** * @description 播放视频事件 * @param {Event} e */ play (e) { const i = e.target.dataset.i const node = this.getNode(i) this.root.triggerEvent('play', { source: node.name, attrs: { ...node.attrs, src: node.src[this.data.ctrl[i] || 0] } }) if (this.root.properties.pauseVideo) { let flag = false const id = e.target.id for (let i = this.root._videos.length; i--;) { if (this.root._videos[i].id === id) { flag = true } else { this.root._videos[i].pause() // 自动暂停其他视频 } } // 将自己加入列表 if (!flag) { const ctx = wx.createVideoContext(id // #ifndef MP-BAIDU , this // #endif ) ctx.id = id if (this.root.playbackRate) { ctx.playbackRate(this.root.playbackRate) } this.root._videos.push(ctx) } } }, /** * @description 图片点击事件 * @param {Event} e */ imgTap (e) { const node = this.getNode(e.target.dataset.i) // 父级中有链接 if (node.a) return this.linkTap(node.a) if (node.attrs.ignore) return this.root.triggerEvent('imgtap', node.attrs) if (this.root.properties.previewImg) { const current = // #ifndef MP-ALIPAY this.root.imgList[node.i] // #endif // #ifdef MP-ALIPAY node.i // eslint-disable-line // #endif // 自动预览图片 wx.previewImage({ // #ifdef MP-WEIXIN showmenu: this.root.properties.showImgMenu, // #endif // #ifdef MP-ALIPAY enablesavephoto: this.root.properties.showImgMenu, enableShowPhotoDownload: this.root.properties.showImgMenu, // #endif current, urls: this.root.imgList }) } }, /** * @description 图片加载完成事件 * @param {Event} e */ imgLoad (e) { const i = e.target.dataset.i const node = this.getNode(i) let val if (!node.w) { val = e.detail.width } else if ((this.properties.opts[1] && !this.data.ctrl[i]) || this.data.ctrl[i] === -1) { // 加载完毕,取消加载中占位图 val = 1 } if (val // #ifdef MP-TOUTIAO && val !== this.data.ctrl[i] // eslint-disable-line // #endif ) { this.setData({ ['ctrl.' + i]: val }) } this.checkReady() }, /** * @description 检查是否所有图片加载完毕 */ checkReady () { if (!this.root.properties.lazyLoad) { this.root.imgList._unloadimgs -= 1 if (!this.root.imgList._unloadimgs) { setTimeout(() => { this.root.getRect().then(rect => { this.root.triggerEvent('ready', rect) }).catch(() => { this.root.triggerEvent('ready', {}) }) }, 350) } } }, /** * @description 链接点击事件 * @param {Event} e */ linkTap (e) { const node = e.currentTarget ? this.getNode(e.currentTarget.dataset.i) : {} const attrs = node.attrs || e const href = attrs.href this.root.triggerEvent('linktap', Object.assign({ innerText: this.root.getText(node.children || []) // 链接内的文本内容 }, attrs)) if (href) { if (href[0] === '#') { // 跳转锚点 this.root.navigateTo(href.substring(1)).catch(() => { }) } else if (href.split('?')[0].includes('://')) { // 复制外部链接 if (this.root.properties.copyLink) { wx.setClipboardData({ data: href, success: () => wx.showToast({ title: '链接已复制' }) }) } } else { // 跳转页面 wx.navigateTo({ url: href, fail () { wx.switchTab({ url: href, fail () { } }) } }) } } }, /** * @description 错误事件 * @param {Event} e */ mediaError (e) { const i = e.target.dataset.i const node = this.getNode(i) if (node.name === 'video' || node.name === 'audio') { // 加载其他源 let index = (this.data.ctrl[i] || 0) + 1 if (index > node.src.length) { index = 0 } if (index < node.src.length) { return this.setData({ ['ctrl.' + i]: index }) } } else if (node.name === 'img') { // 显示错误占位图 if (this.properties.opts[2]) { this.setData({ ['ctrl.' + i]: -1 }) } this.checkReady() } if (this.root) { this.root.triggerEvent('error', { source: node.name, attrs: node.attrs, errMsg: e.detail.errMsg }) } } } })