• 技术文章 >微信小程序 >小程序开发

    浅谈小程序确保每个页面都已登陆的方法

    青灯夜游青灯夜游2021-12-27 10:23:54转载322
    微信小程序如何确保每个页面都已经登陆?本篇文章给大家介绍一下小程序确保每个页面都登陆的方法,希望对大家有所帮助!

    一个微信小程序中,有首页,有个人页面,还有一些列表页面,详情页面等等,这些页面大部分是可以分享的。当分享出去的页面被一个另一个用户打开的时候,这个页面怎么确保这个用户已经登陆了呢?

    网上有很多方案是在请求封装里面加一道拦截,如果没有token,就先调用登陆请求获取token后,再继续。 这种方案没毛病,只要注意一点,当一个页面有多个请求同时触发时,当所有请求拦截后,放到一个数组里面,在获取token成功后,遍历数组一个个请求就行。

    但这个需求再复杂一点,比如连锁便利店小程序,大部分页面都需要有一个门店(因为需要根据门店获取当前门店商品的库存、价格等),这个门店是根据当前的定位来调用后台接口获得的,这个时候如果在请求里进行封装就太麻烦了。

    解决方案

    首先,我们注意到,登陆,获取定位与我们的页面请求是异步的,我们需要保证页面请求是在登陆和获取定位之后,但要是我们每个页面都写一个遍,可维护性就太差了。所以我们可以抽离出一个方法来做这件事。 所以代码就这样了:

    const app = getApp()
    Page({
      data: {
        logs: []
      },
      onLoad() {
        app.commonLogin(()=>{
            // 处理页页面请求
        })
      }
    })

    做到这里好像是解决我们的问题,但再想一想,如果还想做更多的事,比如说每个页面的onShareAppMessage统一处理,但我又不想在每个页面再写一遍,另外,我又想自己对每个页面实现一个watch,怎么做?

    进一步解决方案

    我们可以看到微信小程序,每个页面是一个Page(),那么我们可以给这个Page外面加一层壳子,我们可以有一个MyPage来替换这个Page,废话不多说,上代码:

    tool.js 相关代码

    /**
       * 处理合并参数
       */
      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
        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(arguments)
        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 = watch[v].handler || watch[v]; // 兼容带handler和不带handler的两种写法
          let deep = watch[v].deep; // 若未设置deep,则为undefine
          this.observe(nowData, lastKey, watchFun, deep, page); // 监听nowData对象的lastKey
        })
      }
    
      /**
       * 监听属性 并执行监听函数
       */
      observe(obj, key, watchFun, deep, 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, watchFun, deep, page); // 递归调用监听函数
          })
        }
        var that = this;
        Object.defineProperty(obj, key, {
          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, key, watchFun, deep, page);
            }
          },
          get: function () {
            return val;
          }
        })
      }

    页面代码:

    app.tool.newPage({
      data: {
        // noAutoLogin: false
      },
      onShow: function () {
        // 在这里写页面请求逻辑
      }
    }

    最后

    代码是在线上跑了很久的,tool里的newPage封装,你可以根据自己的需求进行添加。总之,我这里是提供一种思路,如有更佳,欢迎分享。

    【相关学习推荐:小程序开发教程

    以上就是浅谈小程序确保每个页面都已登陆的方法的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金社区,如有侵犯,请联系admin@php.cn删除
    专题推荐:小程序 页面登陆
    上一篇:浅析小程序中要怎么用threejs 下一篇:记录一次实践,看看小程序购物车动画怎么优化
    Web大前端开发直播班

    相关文章推荐

    • 小程序怎么查看base64图片• 微信公众号/小程序怎么跳转外链?方法介绍• 浅谈小程序如何实现tab卡片切换功能• 浅谈小程序怎么实现列表滚动上下联动效果• 聊聊微信小程序中的wxs模块,介绍使用方法• 浅谈怎么使用小程序实现一个变速大转盘
    1/1

    PHP中文网