1. 程式人生 > 程式設計 >微信小程式如何保證每個頁面都已經登陸詳解

微信小程式如何保證每個頁面都已經登陸詳解

目錄
  • 現狀
  • 解決方案
  • 進一步解決方案
  • 最後

現狀

一個微信小程式中,有首頁,有個人頁面,還有一些列表頁面,詳情頁面等等,這些頁面大部分是可以分享的。當分享出去的頁面被一個另一個使用者開啟的時候,這個頁面怎麼確保這個使用者已經登陸了呢?

網上有很多方案是在請求封裝裡面加一道攔截,如果沒有token,就先呼叫登陸請求獲取token後,再繼續。

這種方案沒毛病,只要注意一點,當一個頁面有多個請求同時觸發時,當所有請求攔http://www.cppcns.com截後,放到一個數組裡面,在獲取token成功後,遍歷陣列一個個請求就行。

但這個需求再複雜一點,比如連鎖便利店小程式,大部分頁面都需要有一個門店(因為需要根據門店獲取當前門店商品的庫存、價格等),這個門店是根據當前的定位來呼叫後臺介面獲得的,這個時候如果在請求裡進行封裝就太麻煩了。

解決方案

首先,我們注意到,登陸,獲取定位與我們的頁面請求是非同步的,我們需要保證頁面請求是在登陸和獲取定位之後,但要是我們每個頁面都寫一個遍,可維護性就太差了。所以我們可以抽離出一個方法來做這件事。

所以程式碼就這樣了:

const app = getApp()
Page({
  data: {
    logs: []
  },onLoad() {
    app.commonLogin(()=>{
        // 處理頁頁面請求
    })
  }
})

做到這裡好像是解決我們的問題,但再想一想,如果還想做更多的事,比如說每個頁面的onShareAppMessage統一處理,但我又不想在每個頁面再寫一遍,另外,我又想自己對每個頁面實現一個watch,怎麼做?

進一步解決方案

我們可以看到微信小程式,每個頁面是一個Page(),那麼我們可以給這個Page外面加一層殼子,我們可以有一個MyPage來替換這個Page,廢話不多說,上程式碼:

tool. 相關程式碼

/**
   * 處理合並引數
   */
  handlePageParamMerge(arg) {
    let numargs = arg.length; // 獲取被傳遞引數的數值。
    let data = {}
    let page = {}
    for (let ix in arg) {
      let item = arg[ix]
      if (item.data && typeof (item.data) === 'object') {
        data = Object.assign(data,item.data)
      }
      if (item.methods && typeof (item.methods) === 'object') {
        page = Object.assign(page,item.methods)
      } else {
        page = Object.assign(page,item)
      }
    }
    page.data = data
    return page
  }

  /***
   * 合併頁面方法以及資料,相容 {data:{},methods: {}} 或 {data:{},a:{},b:{}}
   */
  mergePage() {
    return this.handlePageParamMerge(arguments)
  }

  /**
   * 處理元件引數合併
   */
  handleCompParamMerge(arg) {
    let numargs = arg.length; // 獲取被傳遞引數的數值。
    let data = {}
    let options = {}
    let properties = {}
    let methods = {}
    let comp = {}
    for (let ix in arg) {
      let item = arg[ix]
      // 合併元件的初始資料
      if (item.data && typeof (item.data) === 'object') {
        data = Object.assign(data,item.data)
      }
      // 合併元件的屬性列表
      if (item.properties && typeof (item.properties) === 'object') {
        properties = Object.assign(properties,item.properties)
      }
      // 合組件的方法列表
      if (item.methods && typeof (item.methods) === 'object') {
        methods = Object.assign(methods,item.methods)
      }
      if (item.options && typeof (item.options) === 'object') {
        options = Object.assign(options,item.options)
      }
      comp = Object.assign(comp,item)
    }
    comp.data = data
 www.cppcns.com
comp.options = options comp.properties = properties comp.methods = methods return comp } /** * 元件混合 {properties: {},options: {},data:{},methods: {}} */ mergeComponent() { return this.handleCompParamMerge(arguments) } /*** * 合成帶watch的頁面 */ newPage() { let options = this.handlePageParamMerge(arghttp://www.cppcns.comuments) let that = this let app = getApp() //增加全域性點選登入判斷 if (!options.publicCheckLogin){ options.publicCheckLogin = function (e) { let pages = getCurrentPages() let page = pages[pages.length - 1] let dataset = e.currentTarget.dataset let callback = null //獲取回撥方法 if (dataset.callback && typeof (page[dataset.callback]) === "function"){ callback = page[dataset.callback] } // console.log('callback>>',callback,app.isRegister()) //判斷是否登入 if (callback && app.isRegister()){ callback(e) } else{ wx.navigateTo({ url: '/pages/login/login' }) } } } const { onLoad } = options options.onLoad = function (arg) { options.watch && that.setWatcher(this) onLoad && onLoad.call(this,arg) } const { onShow } = options options.onShow = function (arg) { if (options.data.noAutoLogin || app.isRegister()) { onShow && onShow.call(this,arg) //頁面埋點 app.ga({}) } else { wx.navigateTo({ url: '/pages/login/login' }) } } return Page(options) } /** * 合成帶watch等的元件 */ newComponent() { let options = this.handleCompParamMerge(arguments) let that = this const { ready } = options options.ready = function (arg) { options.watch && that.setWatcher(this) ready && ready.call(this,arg) } return Component(options) } /** * 設定監聽器 */ setWatcher(page) { let data = page.data; let watch = page.watch; Object.keys(watch).forEach(v => { let key = v.split('.'); // 將watch中的屬性以'.'切分成陣列 let nowData = data; // 將data賦值給nowData for (let i = 0; i < key.length - 1; i++) { // 遍歷key陣列的元素,除了最後一個! nowData = nowData[key[i]]; // 將nowData指向它的key屬性物件 } let lastKey = key[key.length - 1]; // 假設key==='my.name',此時nowData===data['my']===data.my,lastKey==='name' let watchFun = watchwww.cppcns.com[v].handler || watch[v]; // 相容帶handler和不帶handler的兩種寫法 let deep = watch[v].deep; // 若未設定deep,則為undefine this.observe(nogTopKqKjbwData,lastKey,watchFun,deep,page); // 監聽nowData物件的lastKey }) } /** * 監聽屬性 並執行監聽函式 */ observe(obj,key,page) { var val = obj[key]; // 判斷deep是true 且 val不能為空 且 typeof val==='object'(陣列內數值變化也需要深度監聽) if (deep && val != null && typeof val === 'object') { Object.keys(val).forEach(childKey => { // 遍歷val物件下的每一個key this.observe(val,childKey,page); // 遞迴呼叫監聽函式 }) } var that = this; Object.defineProperty(obj,{ configurable: true,enumerable: true,set: function (value) { if (val === value) { return } // 用page物件呼叫,改變函式內this指向,以便this.data訪問data內的屬性值 watchFun.call(page,value,val); // value是新值,val是舊值 val = value; if (deep) { // 若是深度監聽,重新監聽該物件,以便監聽其屬性。 that.observe(obj,page); } },get: function () { return val; } }) }

頁面程式碼:

app.tool.newPage({
  data: {
    // noAutoLogin: false
  },onShow: function () {
    // 在這裡寫頁面請求邏輯
  }
}

最後

程式碼是在線上跑了很久的,tool裡的newPage封裝,你可以根據自己的需求進行新增。總之,我這裡是提供一種思路,如有更佳,歡迎分享。

到此這篇關於微信小程式如何保證每個頁面都已經登陸的文章就介紹到這了,更多相關微信小程式保證頁面登陸內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!