#yyds干货盘点#愚公系列2023年02月 微信小程序-Page页面扩展

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#yyds干货盘点#愚公系列2023年02月 微信小程序-Page页面扩展相关的知识,希望对你有一定的参考价值。

前言

在小程序日常开发中,有些功能是所有页面都需要使用的,所以就需要对每个page页面进行扩展,在小程序中Page 的作用相当于构造函数, Page 会初始化页面对象然后将配置参数中的属性 merge 到页面对象上。

一、Page页面扩展

1.组件的封装和引用

extend-page.js


const extendPage = Page => 
  return object => 
    // 登录面板开头
    if (!object.data) object.data = 
    object.data.showLoginPanel = false 

    // method
    object.hi = function(name)
      console.log(`hi $name`);
    

    // 派发一个等待处理,需要有代码处理的事件
    // 但这个方法没有什么用
    object.triggerWaitingEvent = function (type, data = )
      return new Promise((resolve,reject)=>
        let eventCallback = res => resolve(res)
        Object.assign(data, 
          eventCallback
        )
        this.triggerEvent(type, data)
      )
    

    return Page(object)
  


const originalPage = Page
Page = extendPage(originalPage)

app.js中引入扩展页面

require("./lib/extend-page")

2.页面使用

<button bindtap="extendPage" type="primary">请求</button>
<LoginPanel show="showLoginPanel"></LoginPanel>
  async extendPageTest()
    this.hi(weapp)
    // 使用request3
    let res4 = await wx.wxp.request4(
      url: http://localhost:3000/user/home,
    )
    if (res4) console.log(res4, res4)
  ,

3.效果

二、其他相关封装

1.pop-up组件


Component(
  options: 
    multipleSlots: true // 在组件定义时的选项中启用多slot支持
  ,
  /**
   * 组件的属性列表
   */
  properties: 
    visible: 
      type: Boolean,
      value: false
    
  ,

  /**
   * 组件的初始数据
   */
  data: ,

  ready()
    this.triggerEvent(ready)
  ,

  /**
   * 组件的方法列表
   */
  methods: 
    popPreventTouchmove()  ,
    popPreventTouchmove2()  ,
    popPreventTouchmove3()  ,
    cityChange()  ,
    close() 
      this.triggerEvent(close)
    ,
    handleClickMask(e) 
      // console.log(e)
      if (e.target.dataset.type !== unclose) this.close()
    
  
)

<view catchtouchmove="popPreventTouchmove">
  <view class="q-pp-mask   visible ? q-pp-mask-show :   ptp_exposure" bindtap="handleClickMask" catchtouchmove="popPreventTouchmove">
    <view class=" q-pp  visible ? q-pp-show :  " catchtouchmove="popPreventTouchmove">
      <slot name="content" data-type="unclose"></slot>
    </view>
  </view>
</view>
.q-pp 
  position: fixed;
  width: 100%;
  box-sizing: border-box;
  left: 0;
  right: 0;
  bottom: 0;
  background: #f7f7f7;
  transform: translate3d(0, 100%, 0);
  transform-origin: center;
  transition: all 0.2s ease-in-out;
  z-index: 900;
  visibility: hidden;


.q-pp-show 
  transform: translate3d(0, 0, 0);
  visibility: visible;


.q-pp-mask 
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  z-index: 900;
  transition: all 0.2s ease-in-out;
  opacity: 0;
  visibility: hidden;


.q-pp-mask-show 
  opacity: 1;
  visibility: visible;


2.LoginPanel组件

<pop-up visible="visible">
	<view slot="content">
		<view class="picker-view">
			<view class="picker-view__pane">
				<text bindtap="close">取消</text>
			</view>
			<view style="font-size:17px;font-weight:bold;line-height:30px;border-bottom:1px solid #f2f2f2;padding: 0px 0 20px;width: 100%;color:#353535;text-align: center;">微信授权登录</view>
			<image style="width: 40px;height: 40px;padding-top: 20px;" src="../../components/custom-tab-bar/component-on.png"></image>
			<view style="font-size:17px;font-weight:400;color:#353535;line-height: 40px;">小程序将申请获取以下权限</view>
			<view style="font-size:11px;color:#b2b2b2;border-bottom:1px solid #f2f2f2;width: 100%;padding: 0px 0 40px;text-align: center;">● 获得你的公开信息(昵称、头像、地区及性别)</view>
			<view style="height:80px;padding-top: 20px;">
				<button bindgetuserinfo="login" open-type="getUserInfo" type="primary">登陆</button>
			</view>
		</view>
	</view>
</pop-up>

.picker-view 
  width: 100%;
  display: flex;
  background-color: #fff;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  bottom: 0rpx;
  left: 0rpx;


.picker-item 
  line-height: 70rpx;
  margin-left: 5rpx;
  margin-right: 5rpx;
  text-align: center;


.picker-view__pane 
  height: 100rpx;
  width: 100%;
  padding: 20rpx 32rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
  box-sizing: border-box;


.picker-view__pane text
  color: #00cc88;
  font-size: 30rpx;


.pick-view__group 
  width: 96%;
  height: 450rpx;



Component(
  options: 
    multipleSlots: false
  ,
  properties: 
    show: 
      type: Boolean,
      value: false
    
  ,
  observers: 
    show: function (value) 
      console.log(value);

      this.setData(
        visible: value
      )
    
  ,
  data: 
    visible: false
  ,
  ready() ,
  methods: 
    close(e) 
      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)

    ,
    login2(e) 
      let 
        userInfo,
        encryptedData,
        iv
       = e.detail
      // console.log(userInfo, userInfo);

      const requestLoginApi = (code) => 
        //发起网络请求
        wx.request(
          url: http://localhost:3000/user/wexin-login2,
          method: POST,
          header: 
            content-type: application/json
          ,
          data: 
            code: code,
            userInfo,
            encryptedData,
            iv
          ,
          success(res) 
            console.log(请求成功, res.data)
            let token = res.data.data.authorizationToken
            wx.setStorageSync(token, token)
            onUserLogin(token)
            console.log(authorization, token)
          ,
          fail(err) 
            console.log(请求异常, err)
          
        )
      

      const onUserLogin = (token) => 
        getApp().globalData.token = token
        wx.showToast(
          title: 登陆成功了,
        )
        this.close()
        this.triggerEvent(loginSuccess)
        getApp().globalEvent.emit(loginSuccess)
      

      const login = () => 
        wx.login(
          success(res0) 
            if (res0.code) 
              requestLoginApi(res0.code)
             else 
              console.log(登录失败! + res0.errMsg)
            
          
        )
      

      wx.checkSession(
        success() 
          //session_key 未过期,并且在本生命周期一直有效
          console.log(在登陆中);
          let token = wx.getStorageSync(token)
          if (token) 
            onUserLogin(token)
           else 
            // session会重复,需要处理
            login()
          
        ,
        fail() 
          // session_key 已经失效,需要重新执行登录流程
          login()
        
      )

    
  
)

  "component": true,
  "usingComponents": 
    "pop-up": "../pop-up/index"
  

3.LoginPanel组件

//app.js
require("./lib/extend-page")
// import Event from ./lib/event
import Event from ./lib/event2
import wxp from ./lib/wxp

// getApp().globalEvent
App(
  wxp: (wx.wxp = wxp),
  globalData: (wx.globalData = ),
  globalEvent: (wx.globalEvent = new Event()),
  onLaunch: async function () 
    if (!wx.cloud) 
      console.error(请使用 2.2.3 或以上的基础库以使用云能力)
     else 
      wx.cloud.init(
        // env 参数说明:
        //   env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
        //   此处请填入环境 ID, 环境 ID 可打开云控制台查看
        //   如不填则使用默认环境(第一个创建的环境)
        env: default-98491d,
        traceUser: true,
      )
    

    this.globalData = 
  ,
import 
  promisifyAll
 from miniprogram-api-promise;

const wxp = 
promisifyAll(wx, wxp)

// compatible usage
// wxp.getSystemInfo(success(res) console.log(res))

wxp.request2 = function (args) 
  let token = wx.getStorageSync(token)
  if (token) 
    if (!args.header) args.header = 
    args.header[Authorization] = `Bearer $token`
  
  return wxp.request(args).catch(function (reason) 
    console.log(reason, reason)
  )


// 
wxp.request3 = function(args)
  let token = wx.getStorageSync(token)
  if (!token)
    return new Promise((resolve, reject)=>
      let pageStack = getCurrentPages()
      if (pageStack && pageStack.length > 0) 
        let currentPage = pageStack[pageStack.length-1]
        currentPage.setData(
          showLoginPanel2:true
        )
        getApp().globalEvent.once("loginSuccess", ()=>
          wxp.request2(args).then(res=>
            resolve(res)
          , err=>
            console.log(err, err);
            reject(err)
          )
        )
      else
        reject(page valid err)
      
    )
  
  return wxp.request2(args)


wxp.request4 = function (args) 
  let token = wx.getStorageSync(token)
  if (!token) 
    let pages = getCurrentPages()
    let currentPage = pages[pages.length - 1]
    // 展示登陆浮窗
    currentPage.setData(
      showLoginPanel: true
    )
    return new Promise((resolve, reject) => 
      getApp().globalEvent.once(loginSuccess, function (e) 
        wxp.request2(args).then(function (result) 
          resolve(result)
        ).catch(function (reason) 
          console.log(reason, reason);
        )
      )
    )
  
  return wxp.request2(args).catch(function (reason) 
    console.log(reason, reason);
  )


export default wxp

以上是关于#yyds干货盘点#愚公系列2023年02月 微信小程序-Page页面扩展的主要内容,如果未能解决你的问题,请参考以下文章

#yyds干货盘点#愚公系列2023年02月 微信小程序-电商项目-商品详情页面的标题及价格功能实现

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-程序运行计时的总结

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-区块链概念和实现

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-List转成字符串的总结

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-EF Core性能优化之显示编译

#yyds干货盘点#愚公系列2023年02月 .NET/C#知识点-List对象去重的方法总结