/** * Pilot * @author Tevin */ import Taro, { getCurrentInstance, getCurrentPages } from '@tarojs/taro'; import { $hostBoot } from '@components/bases/HostBoot'; import project from '@project'; export class Pilot { constructor() { } $data() { return {}; } createOptions(dataAdd) { const options = { methods: {}, }; const names = []; let parent = null; // 实例本身的字段 Object.getOwnPropertyNames(this).forEach(name => names.push(name)); // 基类的字段,直到Pilot为止(不含Pilot) parent = Object.getPrototypeOf(this); while (parent instanceof Pilot) { Object.getOwnPropertyNames(parent).forEach(name => names.push(name)); parent = Object.getPrototypeOf(parent); } // 传递 names.forEach(name => { // 构造器忽略,如果存在属性 $methods 也忽略 if (name === 'constructor' || name === '$methods') { return; } if (/^\$/.test(name)) { if (name === '$data' && typeof dataAdd !== 'undefined') { // 转换 dataAdd 中 assets 属性下的图片地址值 if (typeof dataAdd.assets !== 'undefined') { dataAdd.assets = Pilot.transAssets(dataAdd.assets); } options.data = () => { // 当有传data值进来,初始值必须带data中的字段 const dataOrig = this.$data(); return { ...dataOrig, ...dataAdd, }; }; } else { options[name.replace('$', '')] = this[name]; } } else { options.methods[name] = this[name]; } }); this._bindTaroPage(options); return options; } _bindTaroPage(options) { // 绑定页面实例到Page const { created, beforeDestroy, onMessage, onBridge } = options; const option2 = { created() { const instance = getCurrentInstance(); instance.page.$component = this; // 绑定方法到页面实例 this.$poster = Pilot.createPoster(this); this.$onMessage = onMessage || (() => null); this.$onBridge = onBridge || (() => null); // 实际生命周期回调 created && created.call(this); }, beforeDestroy() { const instance = getCurrentInstance(); delete instance.page.$component; // 实际生命周期回调 beforeDestroy && beforeDestroy.call(this); // 取消绑定 this.$onMessage = null; this.$poster = null; this.$onBridge = null; }, }; options.created = option2.created; options.beforeDestroy = option2.beforeDestroy; delete options.onMessage; delete options.poster; delete options.onBridge; } // 创建页面通讯器 static createPoster($vm) { return (pageType, action, data) => { // 解除引用关系 const nextData = JSON.parse(JSON.stringify(data || {})); // 下一页 if (pageType === 'nextPage') { // 持续 3 秒,检测下一页是否存在 let count = 0; const timer = setInterval(() => { if (++count > 60) { clearInterval(timer); } const currentPages = getCurrentPages(); const pageIndex = currentPages.findIndex(page => page.$component === $vm); const nextPage = currentPages[pageIndex + 1]; if (nextPage) { clearInterval(timer); nextPage.$component?.$onMessage(action, nextData); } }, 50); } else if (pageType === 'prevPage') { const currentPages = getCurrentPages(); const pageIndex = currentPages.findIndex(page => page.$component === $vm); const prevPage = currentPages[pageIndex - 1]; if (prevPage) { prevPage.$component?.$onMessage(action, nextData); } } else if (pageType === 'rootPage') { const currentPages = getCurrentPages(); const rootPage = currentPages[0]; rootPage.$component?.$onMessage(action, nextData); } }; } /** * 转换静态图片引用 * @param assets * @return {{}} */ static transAssets(assets = {}) { const assets2 = {}; Object.keys(assets).forEach(key => { let asset = ''; if (assets[key].indexOf('assets') >= 0) { asset = assets[key].split('assets')[1]; } else { asset = assets[key].replace(/^[.\/\\]*/, '/'); } // 网页 if (process.env.TARO_ENV === 'h5') { assets2[key] = project.host.assetsPath + asset; } // 小程序 else if (process.env.TARO_ENV === 'weapp') { assets2[key] = $hostBoot.getHost() + project.host.assetsPath + asset; } }); return assets2; } }