序
本文论述的是子或孙向父传递数据的情况,自下而上
相信大家平时在小程序开发中肯定遇到过页面或者组件之间的数据通信问题,那小程序数据通信都有哪些方式呢?如何选择合适的通信方式呢?这就是本文要讨论的重点。
关系划分
在讨论都有哪些数据通信方式之前,我们先来定义一下,小程序页面、组件之间都有哪些关系。我总结了一下,大概分为以下3类:
- 父子关系
- 兄弟关系
- 爷孙关系
不同的关系里面,不同角色之间有可能是页面,也有可能是组件,接下来我们就一个个来揭示如何进行数据通信。
父子关系
父子关系一般主要就是两种情况:
父为页面,子为组件 父为组件,子为组件
这种关系可能是频率出现最高的了,毕竟大部分小程序页面都是以小而美为主,可能没有分的太细,碰到这种情况,我们可以通过在父页面监听子组件触发的事件来完成数据通信。
方法一
<!-- 当自定义组件触发“myevent”事件时,调用“onMyEvent”方法 --> <component-tag-name bindmyevent="onMyEvent" /> <!-- 在自定义组件中 --> <button bindtap="onTap">点击这个按钮将触发“myevent”事件</button> Component({ methods: { onTap() { const myEventDetail = {} // detail对象,提供给事件监听函数 const myEventOption = {} // 触发事件的选项 this.triggerEvent('myevent', myEventDetail, myEventOption) } } })
兄弟关系
兄弟关系同样分为两种情况:
- 兄弟间都是页面
- 兄弟间都是组件
兄弟间都是页面
这种关系指的就是,同层次间的页面,简单理解其实就是页面之间的跳转,那从页面A跳到页面B,页面B如何修改页面A的数据呢?
方法二
页面生命周期里面都有 onShow``onHide
方法,通过 localStorage
或者 globalData
作为数据中转,进入到不同页面时,在前一个页面 onShow
里面取出数据,在后一个页面 onShow
里面存储数据,具体做法如下:
<!--app.js--> App({ globalData: { count: 0 }, }); <!--页面A--> onShow(){ let countValue = wx.getStorageSync('count'); <!--globalData的方式--> let countValue = getApp().globalData.count; <!----> if(countValue){ this.setData({ count:countValue }) } <!--globalData的方式 清除数据--> getApp().globalData.count = null <!----> } onHide(){ wx.removeStorageSync('count') } <!--页面B--> onShow(){ <!--globalData的方式--> getApp().globalData.count = 1 <!----> wx.setStorageSync('count',1); }
爷孙关系
爷孙关系算是数据通信中最复杂的了,因为不是直系传递,若是通过 方法一 来监听,那就需要通过多级传递事件了,如果节点比较深,可想而知代码是得多难理解且难以维护。
我们可以通过全局创建一个事件总栈 EventBus
,利用这个 EventBus
来订阅发布事件,也就是我们经常使用的 发布订阅模式 ,那在小程序里面如何实现呢?
方法三
<!--第一步:实现一个事件总栈类--> class EventBus { constructor() { this.bus = {}; } // on 订阅 on(type, fun) { if (typeof fun !== 'function') { console.error('fun is not a function'); return; } (this.bus[type] = this.bus[type] || []).push(fun); } // emit 触发 emit(type, ...param) { let cache = this.bus[type]; if (!cache) return; for (let event of cache) { event.call(this, ...param); } } // off 释放 off(type, fun) { let events = this.bus[type]; if (!events) return; let i = 0, n = events.length; for (i; i < n; i++) { let event = events[i]; if (fun === event) { events.splice(i, 1); break; } } } } module.exports = EventBus; <!--第二步:在app.js文件中引入--> import EventBus from './common/event-bus/index.js'; App({ eventBus: new EventBus(), }); <!--第三步:在父页面或者父组件中监听某个事件--> onLoad: function(options) { app.eventBus.on('add-count', this.addCount); } onUnload: function(options) { app.eventBus.off('add-count', this.addCount); } <!--第四步:在子组件里面触发事件--> methods: { addCount() { app.eventBus.emit('add-count'); } }
除此之外,还有一种方式,我们可以在每个页面 onLoad
周期里面将该页面的 pageModel 对象缓存起来,之后在孙辈组件里面拿到祖孙的页面对象,从而触发祖孙页面对象对应的方法。
<!--第一步:实现一个pageModel,用来缓存页面对象--> class PageModel { constructor() { this.pageCache = {}; } add(page) { let pagePath = this._getPageModelPath(page); this.pageCache[pagePath] = page; } get(path) { return this.pageCache[path]; } delete(page) { delete this.pageCache[this._getPageModelPath(page)]; } <!--这一段代码是关键,存储的是__route__属性--> _getPageModelPath(page) { return page.__route__; } } export default PageModel ; <!--第二步:app.js中引入--> import PageModel from './common/page-model/index.js'; App({ pageModel: new PageModel(), }); <!--第三步:页面onLoad周期里缓存页面--> onLoad: function(options) { app.pageModel.add(this); } <!--第四步:子孙获取祖辈方法--> methods: { addCount() { app.pageModel.get('pages/communicate/index').addCount(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
小程序数据通信,小程序通信
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。