程序实现每个页面均已登陆的方法浅谈

why 186 2024-06-21

微信小程序如何确保每个页面都已经登陆?本篇文章给大家介绍一下小程序确保每个页面都登陆的方法,希望对大家有所帮助!

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

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

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

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

解决方案

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

1

2

3

4

5

6

7

8

9

10

11

const app = getApp()

Page({

  data: {

    logs: []

  },

  onLoad() {

    app.commonLogin(()=>{

        // 处理页页面请求

    })

  }

})

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

进一步解决方案

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

tool.js 相关代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

/**

   * 处理合并参数

   */

  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===&#39;my.name&#39;,此时nowData===data[&#39;my&#39;]===data.my,lastKey===&#39;name&#39;

      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===&#39;object&#39;(数组内数值变化也需要深度监听)

    if (deep && val != null && typeof val === &#39;object&#39;) {

      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;

      }

    })

  }

页面代码:

1

2

3

4

5

6

7

8

app.tool.newPage({

  data: {

    // noAutoLogin: false

  },

  onShow: function () {

    // 在这里写页面请求逻辑

  }

}

最后

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一次关于小程序购物车动画优化的实践记录
下一篇:小程序中运用 threejs 的方式浅析
相关文章

 发表评论

暂时没有评论,来抢沙发吧~