知識
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!
泰羅小程序登錄能力賦能
發(fā)表時間:2021-4-30
發(fā)布人:葵宇科技
瀏覽次數(shù):64
問題
不是為了設計為設計,最初的設計是為了解決核心的四個問題,實現(xiàn)與登錄有關的邏輯收緊,與具體頁面或者組件解耦。
設想
基于登錄有關的邏輯進行抽離,進行統(tǒng)一設計。
以下涉及代碼的部分,都在小程序項目中Demo分支中,其中hoc的組件我們認為還是組件,所以在components中新建立了hoc的文件夾,而hook從官方定義來說,不一定是組件,更多的期望是可復用邏輯,所以目錄在于components并列新建了hooks文件夾。針對測試用的頁面建立在test文件夾。
設計思路
賦能頁面
頁面攔截器
大致我們可以思考到以下方向以及方案。
由于其他方式暫時不可用,目前我們采用跳轉方法增加攔截的方式實現(xiàn)的需求,但這種在直接跳轉的頁面是無法實現(xiàn)攔截的,針對這種頁面,我們需要使用針對頁面組件在頁面內增加相關的登錄賦能,實現(xiàn)登錄狀態(tài)的監(jiān)聽。
//路由跳轉攔截器
(function taroRouterIntercept(){
const {navigateTo,redirectTo}=Taro;
const noTokenWhiteList=['/login'];//沒有token能進的頁面 除去tab根頁面,因為已經(jīng)做適配
const noLoginWhiteList=noTokenWhiteList.concat(['/diary','/user']);//沒有token能進的頁面 除去tab根頁面,因為已經(jīng)做適配
function tokenIntercept(url){
return new Promise((resolve,reject)=>{
if(!UserManager.getToken())//進行token效驗
{
const needToken=!(noTokenWhiteList.some((val)=>{
return url.startsWith(val);
}));
if(needToken)//需要token
{
UserManager.initToken().then(()=>{
resolve();
}).catch(()=>{
reject();
Taro.showToast({ title: '授權失敗', icon: 'none' })//APP拒絕登錄
})
}else{
resolve();
}
}else{
resolve();
}
})
}
function loginIntercept(url){
return new Promise((resolve,reject)=>{
if(!UserManager.isLogin())
{
console.log('noLoginWhiteList',noLoginWhiteList)
const needLogin=!(noLoginWhiteList.some((val)=>{
return url.startsWith(val);
}));
if(needLogin)//需要登錄
{
reject();
UserManager.jumpToLogin();//這里之后可以改造成登錄之后繼續(xù)做跳轉
}else{
resolve();
}
}else{
resolve();
}
})
}
Taro.navigateTo=function(params){
const url=params.url;
tokenIntercept(url).then(()=>{
loginIntercept(url).then(()=>{
navigateTo(params);//攔截都過的時候再執(zhí)行跳轉
})
});
}
Taro.redirectTo=function(params){
const url=params.url;
tokenIntercept(url).then(()=>{
loginIntercept(url).then(()=>{
redirectTo(params);//攔截都過的時候再執(zhí)行跳轉
})
});
}
})();
復制代碼
后續(xù)的計劃,我們會提供中間件的寫法,讓方法重寫、中間件加入更加優(yōu)雅。
針對類組件的頁面
提供hoc的寫法,用反繼承的方式為組件提供類似生命周期的鉤子函數(shù),并提供注入isLogin的state狀態(tài)。 hoc的寫法 :
import Taro, {
Component,
} from "@tarojs/taro";
import UserManager from "../../utils/UserManager";
export default function withLoginStatus(WrappedComponent) {
// ...并返回另一個組件...
return class extends WrappedComponent {//不這么寫子組件生命周期不會執(zhí)行 且渲染有問題
hx_componentWillMount(){
//這樣寫后面能立即獲取到已經(jīng)塞入isLogin值的state
this.setState({
isLogin: !!UserManager.isLogin()
})
super.hx_componentWillMount();
}
componentDidMount() {
// 訂閱登錄登出動作
Taro.eventCenter.on('login',this.loginStatusChange.bind(this,true))
Taro.eventCenter.on('logout', this.loginStatusChange.bind(this, false))
super.componentDidMount();
}
/**
*
* @param {bool} isLogin 登錄狀態(tài)
*/
loginStatusChange = (isLogin) => {
this.setState({isLogin});
super.loginStatusChange && super.loginStatusChange(isLogin);
}
componentWillUnmount() {
Taro.eventCenter.off('login',this.loginStatusChange);
Taro.eventCenter.off('logout', this.loginStatusChange);
super.componentWillUnmount();
}
};
}
復制代碼
后續(xù)計劃: 1 是否登錄狀態(tài)能否寫入props中
其使用方式 :基本達到預期效果,對原代碼的侵入性很小。
import Taro, {
Component
} from "@tarojs/taro";
import ContainView from "../../../components/ContainView";
import withLoginStatus from "../../../components/HOCS/withLoginStatus";
@withLoginStatus
class Test extends Component {
state = {
data:1,
}
loginStatusChange(isLogin) {
console.log('進行數(shù)據(jù)更新')
if (isLogin) {
this.setState(state => {
data : state.data ++
} )
}
}
render() {
const {isLogin } = this.state
return<ContainView>
<View>
{isLogin ? '需要登錄' : `刷新之后的數(shù)據(jù):${data}`}
</View>
</ContainView>
}
}
export default Test
復制代碼
針對函數(shù)組件的頁面
針對函數(shù)組件,我們提供了兩種方式,先介紹第一種,在提供hook,并借助useEffect的情況下 。
hook的源碼:
import Taro, { useState } from '@tarojs/taro'
import UserManager from "../utils/UserManager";
/**
* @description 增加對事件的訂閱 其他事情不做
*/
function useLoginStatus(){
const [isLogin, setIsLogin] = useState(!!UserManager.isLogin())
function bindChange(flag) {
setIsLogin(flag)
}
Taro.eventCenter.on('login',bindChange)
Taro.eventCenter.on('logout', bindChange)
function offWatchLogin() {
console.log('停止監(jiān)聽')
Taro.eventCenter.off('login',bindChange)
Taro.eventCenter.off('logout',bindChange)
}
return [isLogin,setIsLogin,offWatchLogin]
}
export default useLoginStatus
復制代碼
函數(shù)組件的使用方式:
注意事項: 1 增加對獲取到的isLogin的 useEffect的監(jiān)聽,執(zhí)行需要執(zhí)行的函數(shù) 2 在組件銷毀時,執(zhí)行取消監(jiān)聽函數(shù) offWatchLogin
import Taro, {
Component,useEffect,useState,useDidHide
} from "@tarojs/taro";
import ContainView from "../../../components/ContainView";
import withLoginStatus from "../../../hooks/withLoginStatus ";
function Demo() {
const [isLogin,setIsLogin,offWatchLogin] = withLoginStatus();
const [hasGet,setHasGet]= useState(false)
const [data, setData] = useState(0);
function getData() {
setData(data+1 )
}
useEffect(() => {
getData();
},[])
// 增加一個useEffect 判斷是否需要更新
useEffect(() => {
console.log(3333)
console.log('change',isLogin)
if (isLogin && !hasGet) {
console.log('需要更新數(shù)據(jù)')
getData()
setHasGet(true)
} else {
setHasGet(false)
}
}, [isLogin]);
function leave() {
Taro.navigateTo({
url:'/topic/pages/index/index'
})
}
useDidHide(() => {
console.log('銷毀執(zhí)行');
offWatchLogin()
})
return <ContainView>{!isLogin ? '需要登錄' : `刷新之后的數(shù)據(jù):${data}`}
<View onClick={leave}>離開測試</View>
</ContainView>
}
export default Demo
復制代碼
賦能組件
針對類組件
與上面賦能頁面組件相同,不再贅述
針對函數(shù)組件
與上面賦能頁面組件相同,不再贅述。這里重點介紹下可能會變化的設計細節(jié): 1 需要導出的非數(shù)組,而是對象,那么可用性更加靈活 2 針對一些 其他的針對登錄可以抽取的邏輯,可使用hook的方式實現(xiàn),然后針對本來要執(zhí)行的函數(shù),使用高級函數(shù)的方式包裹。比如判斷沒有登錄,需要先跳轉登錄;如果已經(jīng)登錄,直接執(zhí)行函數(shù)。 3 使用非useEffect的方式,而是提供綁定函數(shù)的方式
另外一種hook的寫法,代碼如下:
import Taro, { useState } from '@tarojs/taro'
import UserManager from "../utils/UserManager";
/**
* @description 增加對事件的訂閱 其他事情不做
*/
function useLoginStatus(){
const [isLogin, setIsLogin] = useState(!!UserManager.isLogin());
let callBack = null;
function bindChange(flag) {
setIsLogin(flag)
if (callBack && typeof callBack === 'function') {
callBack(flag)
}
}
function initWatchLogin() {
Taro.eventCenter.on('login',()=>bindChange(true))
Taro.eventCenter.on('logout', ()=>bindChange(false))
}
initWatchLogin()
const mockLogin = setInterval(() => {
const flag = Math.random() - 0.5 > 0 ? 'login' : 'logout';
console.log(flag)
Taro.eventCenter.trigger(flag)
console.log(111111)
}, 4000)
// const mockLogin1 = setTimeout(() => {
// Taro.eventCenter.trigger('logout')
// }, 2000)
function offWatchLogin() {
console.log('停止監(jiān)聽')
Taro.eventCenter.off('login',bindChange)
Taro.eventCenter.off('logout',bindChange)
}
// 追加綁定事件
function loginStatusChangeBind(cb) {
callBack =cb
}
useDidHide(() => {
console.log('銷毀執(zhí)行');
offWatchLogin()
})
function judgeLogin(cb,...rest) {
// 沒有登錄的情況下跳轉登錄
console.log('current', isLogin)
if (!isLogin) {
Taro.navigateTo({
url:'/login/pages/login/index'
})
}
return cb(rest)
}
return { isLogin, setIsLogin, offWatchLogin,loginStatusChangeBind,judgeLogin }
}
export default useLoginStatus
復制代碼
函數(shù)式組件內的使用:
import Taro, {
Component,useState
} from "@tarojs/taro";
import withLoginStatus from "../../../hooks/withLoginStatusObj";
/**
*
* @param {*} props
*/
function DemoButton(props) {
const { } = props;
const [text,setText] = useState('未登錄')
const { isLogin,offWatchLogin, loginStatusChangeBind,judgeLogin } = withLoginStatus();
loginStatusChangeBind(dataChangeByFlag)
/**
* @description 根據(jù)登錄狀態(tài)需要執(zhí)行的函數(shù)
* @param {*} flag
*/
function dataChangeByFlag(flag){
setText(`${!!!flag ? '未':''}登錄`)
}
function test(args) {
console.log('執(zhí)行功能',args)
}
return <View style={{ border: '1px solid blue' }} onClick={(args)=>judgeLogin(test,args,1) }>
權限按鈕({text})
</View>
}
export default DemoButton
復制代碼
小結
本文主要介紹與登錄賦能有關的教程以及基本使用,除了頁面攔截方法已經(jīng)在使用,其他方法還未具體實踐,有任何問題歡迎隨時反饋。
本文中涉及到的一些設計思想和使用方式可以大家可以更大程度的發(fā)散,以后遇到其他類似場景能夠舉一反三。
相關案例查看更多
相關閱讀
- 報廢車拆解系統(tǒng)
- 云南網(wǎng)站建設招商
- 前端
- 云南小程序開發(fā)制作公司
- 報廢車回收管理系統(tǒng)
- 云南軟件公司
- 網(wǎng)絡營銷
- 高端網(wǎng)站建設公司
- 小程序技術
- 企業(yè)網(wǎng)站
- 網(wǎng)站建設開發(fā)
- 小程序公司
- 汽車報廢拆解管理系統(tǒng)
- 海報插件
- Web開發(fā)框架
- 百度人工排名
- 云南網(wǎng)站建設公司
- 云南軟件定制公司
- 搜索引擎優(yōu)化
- 云南網(wǎng)站制作哪家好
- 文山小程序開發(fā)
- 小程序密鑰
- 網(wǎng)站建設服務公司
- 智慧農(nóng)貿市場
- 網(wǎng)站建設首選
- 報廢車管理
- 網(wǎng)絡公司哪家好
- web開發(fā)技術
- 昆明網(wǎng)站建設公司
- 云南小程序設計