微信小程序全栈开发实践 第三章 微信小程序开发常用的API介绍及使用 -- 3.7 网络接口简介(七)学习EventChannel对象

零、回顾

在之前我们自定义实现picker-view组件的时候,
曾经使用过一个pop-up的自定义组件,
这个组件可以在底部滑入一个面板,
现在我们把登录按钮放在底部滑入的面板之上,
然后在完成登录以后,
再将这个面板滑出。



一、EventChannel

现在我们使用pop-up这个自定义组件,
可以实现登录面板的滑入滑出,
但是现在还有另外一个问题,
对于使用自动登录整合功能的页面,
它避免不了会有一些代码上的侵入。
对于侵入的代码,我们没有办法完全避免,
但是我们可以尽量减少这种侵入,
在小程序里面,有一个EventChannel这样的一个对象,
这个对象,它像一个观察者模式对象一样,有我们需要的方法。
`它有哪些方法:`

EventChannel
基础库 2.7.3 开始支持,低版本需做兼容处理。

页面间事件通信通道

方法
EventChannel.emit(string eventName, any args)
触发一个事件

EventChannel.on(string eventName, EventCallback fn)
持续监听一个事件

EventChannel.once(string eventName, EventCallback fn)
监听一个事件一次,触发后失效

EventChannel.off(string eventName, EventCallback fn)
取消监听一个事件。给出第二个参数时,只取消给出的监听函数,否则取消所有监听函数

在这里插入图片描述

这个EventChannel对象,可以让我们在一个页面,
跳转向下一个页面之前,就提前像这个页面发送数据。
即使要跳转的这个页面从来没有打开过,也是可以的。

但是这个EventChannel对象,
1.从onLoad周期函数里面,
使用Page对象的getOpenerEventChannel这个方法去获取。

const eventChannel = this.getOpenerEventChannel() `1.获取eventChannel对象`
this指的是当前我们这个页面page的一个实例.

success:function(res){
	res.eventChannel   `2.获取eventChannel对象`
}
2.或者在打开者页面中在wx.navigateTo等路由接口的success方法中,
通过结果对象的一个EventChannel属性去获取.


这个eventChannel对象它没有办法直接实例化,
它的封装很方便,但是同时也损失掉了一部分灵活性。

eventChannel对象,可以使我们在页面没有打开之前,
先加载这个页面所需要的数据,
然后在这个页面打开的同时,将这个数据传递过去。
这样新页面就不需要等待了,这样可以显著提升用户的体验。
现在我们需要一个观察者对象,用于在用户登录成功的时候,
通知我们的消费代码,为此我们定义一个Event模块,
自定义实现一个简单的观察者模式对象。

现在我们归纳一下为了完成用户登录的自动整合功能,
接下来我们大概需要做`3件事情`1.使用pop-up组件,实现一个底部滑出的登录面板
2.自定义实现一个观察者模式对象 Event
3.在 wxp 组件中扩展实现 request3 接口

二、使用pop-up组件 实现一个底部滑出的登录面板

1.新建 components/login/…
2.components/login/index.json 引入pop-up组件
在这里插入图片描述

{
  "component": true,
  "usingComponents": {
    "pop-up":"../pop-up"
  }
}

3.components/login/index.wxml
4.components/login/index.js
在这里插入图片描述

<pop-up visible="{{visible}}">
  <view slot="content">
    <view class="picker-view">
      <view class="picker-view__pane">
        <text bindtap="close">取消</text>
      </view>
    </view>
    <button bindgetuserinfo="login" open-type="getUserInfo" type="primary">登陆</button>
  </view>
</pop-up>
// components/login/index.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    show:{
      type:Boolean,
      value:false
    }
  },
  // 监听属性值的变化
  observers:{
    'show':function(value){
      this.setData({
        visible:value
      })
    }
  },

  /**
   * 组件的初始数据
   */
  data: {
    visible:false
  },

  /**
   * 组件的方法列表
   */
  methods: {
    close(){

      this.setData({
        visible: false
      })
    },
    async login(e, retryNum = 0) {
      let {
        userInfo,
        encryptedData,
        iv
      } = e.detail

      // 本地token与微信服务器上的session要分别对待
      let tokenIsValid = false, sessionIsValid = false
      let res0 = await getApp().wxp.checkSession().catch(err => {
        // 清理登陆状态,会触发该错误
        // checkSession:fail 系统错误,错误码:-13001,session time out…d relogin
        console.log("err", err);
        tokenIsValid = false
      })
      console.log("res0", res0);
      if (res0 && res0.errMsg === "checkSession:ok") sessionIsValid = true
      let token = wx.getStorageSync('token')
      if (token) tokenIsValid = true

      if (!tokenIsValid || !sessionIsValid) {
        let res1 = await getApp().wxp.login()
        let code = res1.code
        console.log("code", code);

        let res = await getApp().wxp.request({
          url: 'http://localhost:3000/user/wexin-login2',
          method: 'POST',
          header: {
            'content-type': 'application/json',
            'Authorization': `Bearer ${token || ''}`
          },
          data: {
            code,
            userInfo,
            encryptedData,
            iv,
            sessionKeyIsValid: sessionIsValid
          }
        })

        if (res.statusCode == 500) {
          if (retryNum < 3) {
            this.login.apply(this, [e, ++retryNum])
          } else {
            wx.showModal({
              title: '登录失败',
              content: '请退出小程序,清空记录并重试',
            })
          }
          return
        }
        // Error: Illegal Buffer at WXBizDataCrypt.decryptData
        console.log('登录接口请求成功', res.data)
        token = res.data.data.authorizationToken
        wx.setStorageSync('token', token)
        console.log('authorization', token)
      }

      getApp().globalData.token = token
      wx.showToast({
        title: '登陆成功了',
      })
      this.close()
      this.triggerEvent('loginSuccess')
      getApp().globalEvent.emit('loginSuccess')

    },
  }
})

5.pages/api/index.json
6.components/api/index.wxml
在这里插入图片描述

{
  "usingComponents": {
    "LoginPanel":"../../components/login"
  }
}
<button bindtap="showLoginPanel" type="primary">手动开启登陆</button>

<LoginPanel show="{{showLoginPanel}}"></LoginPanel>


7.components/api/index.js
在这里插入图片描述

  data: {
    showLoginPanel:false
  },
  // 3.7 登陆按钮放在底部滑出的面板上
  showLoginPanel(e){
    this.setData({
      showLoginPanel:true
    });
  },

三、总结

这节课我们主要学习了EventChannel对象,
这个对象在页面跳转的时候,传递数据十分有用,
但是它却不能满足我们远距离传递事件的需要。
下节课我们继续实现上面三个步骤中的第二步。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值