微信小程序如何保證每個(gè)頁(yè)面都已經(jīng)登陸詳解
現(xiàn)狀
一個(gè)微信小程序中,有首頁(yè),有個(gè)人頁(yè)面,還有一些列表頁(yè)面,詳情頁(yè)面等等,這些頁(yè)面大部分是可以分享的。當(dāng)分享出去的頁(yè)面被一個(gè)另一個(gè)用戶(hù)打開(kāi)的時(shí)候,這個(gè)頁(yè)面怎么確保這個(gè)用戶(hù)已經(jīng)登陸了呢?
網(wǎng)上有很多方案是在請(qǐng)求封裝里面加一道攔截,如果沒(méi)有token,就先調(diào)用登陸請(qǐng)求獲取token后,再繼續(xù)。
這種方案沒(méi)毛病,只要注意一點(diǎn),當(dāng)一個(gè)頁(yè)面有多個(gè)請(qǐng)求同時(shí)觸發(fā)時(shí),當(dāng)所有請(qǐng)求攔截后,放到一個(gè)數(shù)組里面,在獲取token成功后,遍歷數(shù)組一個(gè)個(gè)請(qǐng)求就行。
但這個(gè)需求再?gòu)?fù)雜一點(diǎn),比如連鎖便利店小程序,大部分頁(yè)面都需要有一個(gè)門(mén)店(因?yàn)樾枰鶕?jù)門(mén)店獲取當(dāng)前門(mén)店商品的庫(kù)存、價(jià)格等),這個(gè)門(mén)店是根據(jù)當(dāng)前的定位來(lái)調(diào)用后臺(tái)接口獲得的,這個(gè)時(shí)候如果在請(qǐng)求里進(jìn)行封裝就太麻煩了。
解決方案
首先,我們注意到,登陸,獲取定位與我們的頁(yè)面請(qǐng)求是異步的,我們需要保證頁(yè)面請(qǐng)求是在登陸和獲取定位之后,但要是我們每個(gè)頁(yè)面都寫(xiě)一個(gè)遍,可維護(hù)性就太差了。所以我們可以抽離出一個(gè)方法來(lái)做這件事。
所以代碼就這樣了:
const app = getApp()
Page({
data: {
logs: []
},
onLoad() {
app.commonLogin(()=>{
// 處理頁(yè)頁(yè)面請(qǐng)求
})
}
})
做到這里好像是解決我們的問(wèn)題,但再想一想,如果還想做更多的事,比如說(shuō)每個(gè)頁(yè)面的onShareAppMessage統(tǒng)一處理,但我又不想在每個(gè)頁(yè)面再寫(xiě)一遍,另外,我又想自己對(duì)每個(gè)頁(yè)面實(shí)現(xiàn)一個(gè)watch,怎么做?
進(jìn)一步解決方案
我們可以看到微信小程序,每個(gè)頁(yè)面是一個(gè)Page(),那么我們可以給這個(gè)Page外面加一層殼子,我們可以有一個(gè)MyPage來(lái)替換這個(gè)Page,廢話(huà)不多說(shuō),上代碼:
tool.js 相關(guān)代碼
/**
* 處理合并參數(shù)
*/
handlePageParamMerge(arg) {
let numargs = arg.length; // 獲取被傳遞參數(shù)的數(shù)值。
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
}
/***
* 合并頁(yè)面方法以及數(shù)據(jù), 兼容 {data:{}, methods: {}} 或 {data:{}, a:{}, b:{}}
*/
mergePage() {
return this.handlePageParamMerge(arguments)
}
/**
* 處理組件參數(shù)合并
*/
handleCompParamMerge(arg) {
let numargs = arg.length; // 獲取被傳遞參數(shù)的數(shù)值。
let data = {}
let options = {}
let properties = {}
let methods = {}
let comp = {}
for (let ix in arg) {
let item = arg[ix]
// 合并組件的初始數(shù)據(jù)
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的頁(yè)面
*/
newPage() {
let options = this.handlePageParamMerge(arguments)
let that = this
let app = getApp()
//增加全局點(diǎn)擊登錄判斷
if (!options.publicCheckLogin){
options.publicCheckLogin = function (e) {
let pages = getCurrentPages()
let page = pages[pages.length - 1]
let dataset = e.currentTarget.dataset
let callback = null
//獲取回調(diào)方法
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)
//頁(yè)面埋點(diǎn)
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)
}
/**
* 設(shè)置監(jiān)聽(tīng)器
*/
setWatcher(page) {
let data = page.data;
let watch = page.watch;
Object.keys(watch).forEach(v => {
let key = v.split('.'); // 將watch中的屬性以'.'切分成數(shù)組
let nowData = data; // 將data賦值給nowData
for (let i = 0; i < key.length - 1; i++) { // 遍歷key數(shù)組的元素,除了最后一個(gè)!
nowData = nowData[key[i]]; // 將nowData指向它的key屬性對(duì)象
}
let lastKey = key[key.length - 1];
// 假設(shè)key==='my.name',此時(shí)nowData===data['my']===data.my,lastKey==='name'
let watchFun = watch[v].handler || watch[v]; // 兼容帶handler和不帶handler的兩種寫(xiě)法
let deep = watch[v].deep; // 若未設(shè)置deep,則為undefine
this.observe(nowData, lastKey, watchFun, deep, page); // 監(jiān)聽(tīng)nowData對(duì)象的lastKey
})
}
/**
* 監(jiān)聽(tīng)屬性 并執(zhí)行監(jiān)聽(tīng)函數(shù)
*/
observe(obj, key, watchFun, deep, page) {
var val = obj[key];
// 判斷deep是true 且 val不能為空 且 typeof val==='object'(數(shù)組內(nèi)數(shù)值變化也需要深度監(jiān)聽(tīng))
if (deep && val != null && typeof val === 'object') {
Object.keys(val).forEach(childKey => { // 遍歷val對(duì)象下的每一個(gè)key
this.observe(val, childKey, watchFun, deep, page); // 遞歸調(diào)用監(jiān)聽(tīng)函數(shù)
})
}
var that = this;
Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: function (value) {
if (val === value) {
return
}
// 用page對(duì)象調(diào)用,改變函數(shù)內(nèi)this指向,以便this.data訪(fǎng)問(wèn)data內(nèi)的屬性值
watchFun.call(page, value, val); // value是新值,val是舊值
val = value;
if (deep) { // 若是深度監(jiān)聽(tīng),重新監(jiān)聽(tīng)該對(duì)象,以便監(jiān)聽(tīng)其屬性。
that.observe(obj, key, watchFun, deep, page);
}
},
get: function () {
return val;
}
})
}
頁(yè)面代碼:
app.tool.newPage({
data: {
// noAutoLogin: false
},
onShow: function () {
// 在這里寫(xiě)頁(yè)面請(qǐng)求邏輯
}
}
最后
代碼是在線(xiàn)上跑了很久的,tool里的newPage封裝,你可以根據(jù)自己的需求進(jìn)行添加??傊疫@里是提供一種思路,如有更佳,歡迎分享。
到此這篇關(guān)于微信小程序如何保證每個(gè)頁(yè)面都已經(jīng)登陸的文章就介紹到這了,更多相關(guān)微信小程序保證頁(yè)面登陸內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
BootStrap下拉框在firefox瀏覽器界面不友好的解決方案
BootStrap下拉框在firefox瀏覽器界面很不友好,在firefix瀏覽器打開(kāi)鏈接就會(huì)發(fā)現(xiàn)里面有個(gè)小容器,怎么處理呢,下面看下小編給大家分享的有關(guān)這個(gè)問(wèn)題的處理方案2016-08-08
boostrapTable的refresh和refreshOptions區(qū)別淺析
在使用bootstrapTable時(shí),刷新數(shù)據(jù)有兩個(gè)方法refresh、refreshOptions,在其用法上有點(diǎn)區(qū)別,接下來(lái)通過(guò)本文給大家分享boostrapTable的refresh和refreshOptions的區(qū)別,需要的朋友可以參考下2017-01-01
JS計(jì)算網(wǎng)頁(yè)停留時(shí)間代碼
這篇文章主要介紹了JS計(jì)算網(wǎng)頁(yè)停留時(shí)間的具體實(shí)現(xiàn),需要的朋友可以參考下2014-04-04
Javascript中async與await的捕捉錯(cuò)誤詳解
這篇文章主要為大家詳細(xì)介紹了Javascript中async與await的捕捉錯(cuò)誤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
JS字符串分割方法整理匯總示例講解(3種截取方法和6個(gè)輔助方法)
JavaScript在開(kāi)發(fā)中常常會(huì)需要截取字符串,而JS提供了slice()?、substring()、substr()?3種方法實(shí)現(xiàn)截取操作。另外還有字符串相關(guān)的6種輔助方法:indexOf()、lastIndexOf()、split()、join()、concat()、charAt()?。2023-02-02
手機(jī)端實(shí)現(xiàn)Bootstrap簡(jiǎn)單圖片輪播效果
這篇文章主要為大家詳細(xì)介紹了基于Bootstrap的簡(jiǎn)單輪播圖的手機(jī)實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10
JS實(shí)現(xiàn)在狀態(tài)欄顯示打字效果完整實(shí)例
這篇文章主要介紹了JS實(shí)現(xiàn)在狀態(tài)欄顯示打字效果的方法,涉及JavaScript中字符遍歷結(jié)合時(shí)間函數(shù)對(duì)狀態(tài)欄顯示進(jìn)行操作的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11

