# 在插件组件中获取 App 全局数据 ## 📖 概述 在微信官方阅读器插件的自定义组件中,可以通过 `getApp()` 方法获取小程序的 App 实例,从而访问在 App 中定义的全局数据(globalData)。 ## 🔧 实现步骤 ### 步骤 1:在 app.tsx 中定义 globalData ```typescript // src/app.tsx class App extends Component { // 定义全局数据 globalData = { isShow: false, // 控制是否显示全屏组件 customParams: null, // 自定义参数 userInfo: null, // 用户信息 vipLevel: 0, // VIP 等级 readingMode: 'normal', // 阅读模式:normal/immersive adConfig: { enabled: true, // 是否启用广告 frequency: 5, // 广告频率(每几章显示一次) type: 'fullscreen' // 广告类型:fullscreen/banner } } onLaunch(options) { console.log("apponLaunch", options) // 初始化全局数据 this.globalData.isShow = true this.globalData.customParams = {} // 监听进入插件页事件 novelPlugin.onPageLoad(this.onNovelPluginLoad) } // ... 其他代码 } ``` ### 步骤 2:在插件组件中获取 globalData ```javascript // components/novelPlugin/fullScreen/index.js Component({ lifetimes: { attached() { // ========== 获取 App 全局数据 ========== const app = getApp() console.log('获取 App 实例:', app) console.log('App globalData:', app.globalData) // 读取你在 app.tsx 中定义的参数 if (app.globalData) { const isShow = app.globalData.isShow const customParams = app.globalData.customParams const vipLevel = app.globalData.vipLevel const adConfig = app.globalData.adConfig console.log('isShow:', isShow) console.log('customParams:', customParams) console.log('vipLevel:', vipLevel) console.log('adConfig:', adConfig) // 根据 isShow 决定是否显示全屏组件 if (isShow === false) { console.log('根据配置不显示全屏组件') // 可以在这里调用关闭逻辑 // this.handleClose() } // 根据 VIP 等级显示不同的推荐内容 if (vipLevel >= 3) { // 显示 VIP 专属推荐 this.loadVipRecommendations() } else { // 显示普通推荐 this.loadNormalRecommendations() } // 检查广告是否启用 if (!adConfig.enabled) { console.log('广告已禁用,不显示全屏组件') return } } // ==================================== // ... 其他初始化逻辑 }, }, methods: { loadVipRecommendations() { // 加载 VIP 专属推荐 }, loadNormalRecommendations() { // 加载普通推荐 } } }) ``` ## 💡 常见使用场景 ### 场景 1:根据全局配置控制显示 **app.tsx:** ```typescript class App extends Component { globalData = { showFullScreenAd: true, // 全局控制是否显示全屏广告 adFrequency: 5 // 广告频率 } } ``` **组件中:** ```javascript attached() { const app = getApp() if (!app.globalData.showFullScreenAd) { console.log('全屏广告已禁用') return } // 继续显示逻辑... } ``` ### 场景 2:根据 VIP 等级显示不同内容 **app.tsx:** ```typescript class App extends Component { globalData = { userInfo: { isVip: true, vipLevel: 3, userId: 'user-123' } } } ``` **组件中:** ```javascript attached() { const app = getApp() const { isVip, vipLevel, userId } = app.globalData.userInfo if (isVip) { // VIP 用户显示专属推荐 this.setData({ recommendList: this.getVipBooks(vipLevel) }) } else { // 非 VIP 用户显示普通推荐 this.setData({ recommendList: this.getNormalBooks() }) } // 记录用户行为 this.reportAnalytics('fullscreen_show', { userId, isVip, vipLevel }) } ``` ### 场景 3:动态配置广告策略 **app.tsx:** ```typescript class App extends Component { globalData = { adStrategy: { enableChapterEnd: true, // 章节末尾显示 enableBookEnd: true, // 书籍末尾显示 minChapterInterval: 3, // 最小章节间隔 maxDailyShows: 5, // 每日最大展示次数 blacklistedUsers: [] // 黑名单用户 } } } ``` **组件中:** ```javascript attached() { const app = getApp() const strategy = app.globalData.adStrategy // 检查是否在黑名单中 if (strategy.blacklistedUsers.includes(currentUserId)) { console.log('用户在黑名单中,不显示广告') return } // 检查今日展示次数 const todayShows = Taro.getStorageSync('todayAdShows') || 0 if (todayShows >= strategy.maxDailyShows) { console.log('今日展示次数已达上限') return } // 继续显示逻辑... } ``` ### 场景 4:多语言支持 **app.tsx:** ```typescript class App extends Component { globalData = { language: 'zh-CN', // zh-CN / en-US translations: { 'zh-CN': { close: '关闭', recommend: '推荐阅读' }, 'en-US': { close: 'Close', recommend: 'Recommended' } } } } ``` **组件中:** ```javascript attached() { const app = getApp() const lang = app.globalData.language const t = app.globalData.translations[lang] this.setData({ i18n: { closeText: t.close, recommendTitle: t.recommend } }) } ``` ## 🎯 完整示例 ### app.tsx 完整代码 ```typescript // src/app.tsx import Taro from '@tarojs/taro' const novelPlugin = Taro.requirePlugin('novel-plugin') class App extends Component { // 定义全局数据 globalData = { // 基础配置 isShow: true, customParams: null, // 用户信息 userInfo: null, vipLevel: 0, // 阅读设置 readingMode: 'normal', fontSize: 16, theme: 'light', // 广告配置 adConfig: { enabled: true, frequency: 5, type: 'fullscreen', strategies: { showInChapterEnd: true, showInBookEnd: true, minInterval: 3 } }, // 多语言 language: 'zh-CN', translations: { 'zh-CN': { close: '关闭', recommend: '推荐阅读' }, 'en-US': { close: 'Close', recommend: 'Recommended' } } } onLaunch(options) { console.log("apponLaunch", options) // 初始化全局数据 this.initGlobalData() // 监听进入插件页事件 novelPlugin.onPageLoad(this.onNovelPluginLoad) } initGlobalData() { // 从本地缓存读取配置 const config = Taro.getStorageSync('appConfig') if (config) { this.globalData = { ...this.globalData, ...config } } // 从服务器获取最新配置 this.fetchRemoteConfig() } async fetchRemoteConfig() { try { const response = await Taro.request({ url: 'https://api.example.com/config' }) // 更新全局配置 this.globalData = { ...this.globalData, ...response.data } // 保存到本地缓存 Taro.setStorageSync('appConfig', this.globalData) } catch (error) { console.error('获取远程配置失败:', error) } } // 更新全局数据的方法 updateGlobalData(key, value) { this.globalData[key] = value // 同步到本地缓存 Taro.setStorageSync('appConfig', this.globalData) } // ... 其他代码 } ``` ### 组件中完整使用 ```javascript // components/novelPlugin/fullScreen/index.js const novelPlugin = requirePlugin('novel-plugin') Component({ properties: { novelManagerId: Number, bookId: String, chapterIndex: Number, ext: String, }, data: { recommendList: [], i18n: {}, isVip: false, }, lifetimes: { attached() { // 获取 App 全局数据 const app = getApp() const { userInfo, vipLevel, adConfig, language, translations } = app.globalData console.log('全局配置:', { userInfo, vipLevel, adConfig, language }) // 检查广告是否启用 if (!adConfig.enabled) { console.log('广告已禁用') this.handleClose() return } // 检查用户 VIP 等级 const isVip = !!userInfo && vipLevel > 0 this.setData({ isVip, i18n: translations[language] }) // 根据 VIP 等级加载不同内容 if (isVip) { this.loadVipContent(vipLevel) } else { this.loadNormalContent() } // 解析 ext 参数 this.parseExtParams() // 上报展示数据 this.reportImpression({ userId: userInfo?.id, isVip, vipLevel, chapterIndex: this.properties.chapterIndex }) }, }, methods: { loadVipContent(vipLevel) { // VIP 专属内容 const vipBooks = [ { id: 'vip-1', title: 'VIP 专享书籍 1', description: '仅限 VIP 阅读', coverUrl: 'https://example.com/vip1.jpg' } ] this.setData({ recommendList: vipBooks }) }, loadNormalContent() { // 普通内容 const normalBooks = [ { id: 'normal-1', title: '热门推荐 1', description: '大家都在看', coverUrl: 'https://example.com/normal1.jpg' } ] this.setData({ recommendList: normalBooks }) }, parseExtParams() { if (this.properties.ext) { try { const extData = JSON.parse(this.properties.ext) if (extData.recommendList) { this.setData({ recommendList: extData.recommendList }) } } catch (e) { console.error('解析 ext 失败:', e) } } }, reportImpression(data) { // 上报展示数据到后台 console.log('上报展示:', data) }, handleClose() { const novelManager = novelPlugin.getNovelManager(this.properties.novelManagerId) if (novelManager) { novelManager.setFullScreenComponentStatus({ show: false }) } } } }) ``` ## ⚠️ 注意事项 ### 1. getApp() 的时机 ```javascript // ✅ 正确:在 lifetimes 中使用 lifetimes: { attached() { const app = getApp() console.log(app.globalData) } } // ❌ 错误:在 properties 定义时使用 Component({ properties: { test: getApp().globalData.test // 此时可能无法获取 } }) ``` ### 2. 数据同步问题 ```javascript // app.tsx class App extends Component { globalData = { count: 0 } // 提供更新方法 updateCount(newCount) { this.globalData.count = newCount } } // 组件中 attached() { const app = getApp() console.log('初始值:', app.globalData.count) // 注意:组件中的数据不会自动更新 // 需要在合适的时机重新获取 } ``` ### 3. 类型安全(TypeScript) ```typescript // types/global.d.ts declare interface CustomApp { globalData: { isShow: boolean customParams: any userInfo: UserInfo | null vipLevel: number // ... 其他字段 } } // 组件中使用 const app = getApp() console.log(app.globalData.isShow) // 有类型提示 ``` ## 📊 最佳实践 ### 1. 集中管理配置 ```typescript // config/global.ts export default { adConfig: { enabled: true, frequency: 5 }, vipConfig: { levels: [1, 2, 3, 4, 5], benefits: ['专属内容', '去广告', '折扣'] } } // app.tsx import globalConfig from './config/global' class App extends Component { globalData = globalConfig } ``` ### 2. 提供 getter/setter ```typescript class App extends Component { globalData = { isShow: true } // 提供访问方法 getIsShow() { return this.globalData.isShow } setIsShow(value: boolean) { this.globalData.isShow = value // 触发更新逻辑 this.notifyComponents() } } ``` ### 3. 监听变化 ```javascript // 组件中监听全局数据变化 attached() { const app = getApp() // 定期检查或使用事件监听 setInterval(() => { if (app.globalData.isShow !== this.lastIsShow) { this.lastIsShow = app.globalData.isShow this.handleIsShowChange(app.globalData.isShow) } }, 1000) } ``` ## 🔗 相关文档 - [微信小程序 App API 文档](https://developers.weixin.qq.com/miniprogram/dev/reference/api/App.html) - [getApp() 使用说明](https://developers.weixin.qq.com/miniprogram/dev/reference/api/getApp.html)