• HBuilder mui登录和访问控制教程--转载


    HBuilder mui登录和访问控制教程

    mui中提供了登录的模板页,但是对于登录后各个页面的访问控制,刷新等并没有官方的推荐方案。我在这里简单说一种初级的解决方案吧,肯定有不足指出,欢迎批评指正。

    第一节中创建移动APP项目的时候选择的是"mui项目",只引入了默认的js和css等文件,没有登录模板。要使用默认登录模板,可以创建的时候选择"mui登录模板"。现在创建一个名为muiLogin的"mui登录模板"项目:

    这里写图片描述

    可以看到这次多了不少东西。通过manifest.json可以发现,入口文件时login.html,我们就从login.html开始。

    从plusReady函数开始看起。

    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
    <code><code><code><code>$.plusReady(function() {
        plus.screen.lockOrientation("portrait-primary");
        var settings = app.getSettings();
        var state = app.getState();
        var mainPage = $.preload({
            "id": 'main',
            "url": 'main.html'
        });
        var main_loaded_flag = false;
        mainPage.addEventListener("loaded",function () {
            main_loaded_flag = true;
        });
        var toMain = function() {
            //使用定时器的原因:
            //可能执行太快,main页面loaded事件尚未触发就执行自定义事件,此时必然会失败
            var id = setInterval(function () {
                if(main_loaded_flag){
                    clearInterval(id);
                    $.fire(mainPage, 'show', null);
                    mainPage.show("pop-in");
                }
            },20);
        };
        //检查 "登录状态/锁屏状态" 开始
        if (settings.autoLogin && state.token && settings.gestures) {
            $.openWindow({
                url: 'unlock.html',
                id: 'unlock',
                show: {
                    aniShow: 'pop-in'
                },
                waiting: {
                    autoShow: false
                }
            });
        } else if (settings.autoLogin && state.token) {
            toMain();
        } else {
            app.setState(null);
            //第三方登录
            var authBtns = ['qihoo', 'weixin', 'sinaweibo', 'qq']; //配置业务支持的第三方登录
            var auths = {};
            //...
        }
    }
    </code></code></code></code>

    先通过.preload预加载了main.html(就是mui,这是个闭包函数,mui作为参数$传进来的,详情百度JavaScript 闭包)。

    toMain跳转主页面更新用户信息

    然后是一个跳转到主页面的toMain函数,可以看到这里监听了main页面的loaded事件,当main加载完毕后,这里就将标志向量main_loaded_flag置为true,toMain中循环判断这个变量,当这里为true时,触发main的show事件,然后在main中,show事件的响应函数从app.getState()中读取用户名,显示在界面。这就完成了用户登录后主界面的用户名显示。

    app.getState和app.setState

    上面用到了app.getState(),这是定义在js/app.js中的,不妨去看下都做了什么。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <code><code><code><code><code>/**
     * 获取当前状态
     **/
    owner.getState = function() {
        var stateText = localStorage.getItem('$state') || "{}";
        return JSON.parse(stateText);
    };
     
    /**
     * 设置当前状态
     **/
    owner.setState = function(state) {
        state = state || {};
        localStorage.setItem('$state', JSON.stringify(state));
    };
    </code></code></code></code></code>

    可以看到这两个是对localStorage的存取做了封装,是一个字典对象,这是个很不错的想法,可以将用户登录后的所有状态信息记录在state里面,包括用户信息,是否自动登录,用户余额,订单列表页的最新和最旧ID等都保存下来,用户注销后直接把state置为null就可以了,再次登录后再设置state。

    上面的登录就是这样做的,登录成功后保存用户信息在state里面,然后触发涉及用户的main页面的事件,main页面里自定义事件的响应函数可以从state里读取信息并更新。

    登录部分

    登录这里先判断了是否运行自动登录以及是否设置了手势解锁。然后按情况决定是手势解锁还是直接登录或者显示登录界面。

    点击登录按钮后,会调用app的login函数验证登录信息,验证正确就会调用toMain跳转到主页面。

    访问控制

    登陆部分很明了,但是大部分app是允许用户在不登录的情况下浏览部分页面的,如果用户访问的页面需要登录再自动跳转到登录页面。

    这里就需要对登录验证做个封装,毕竟每次验证页面的时候,都从state里面判断一下用户是否登录了,以及是否允许自动登录,自动登录是否成功,是否显示登录界面是件很麻烦的事。

    我们希望达到这种效果,如果用户点击"我的"页面,通过以下代码自动进行访问控制:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <code><code><code><code><code><code><code>mui('#my')[0].addEventListener('tap',function(){
        app.loginRequired(function(){
            mui.openWindow({
                url:'my.html',
                id:'my'
            });
        });
    });
    </code></code></code></code></code></code></code>

    只多了一行:app.loginRequired,如果某个页面需要登录才能访问,就把登录后执行的代码作为回调函数传给app.loginRequired,由它进行自动登录和登录不成功的跳转。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <code><code><code><code><code><code><code><code><code><code>/**
     * 要求登陆后才能执行回调函数
     * @param {Object} callback 已登录或自动登录成功执行,否则跳转到登录界面
     */
    owner.loginRequired=function(callback){
        var state=owner.getState();
        if(state.isLogin){//已登录,直接执行
            callback();
        }else{
            owner.tryAutoLogin(function(data){
                if(data.Code==1){//自动登录成功则执行回调函数
                    callback();
                }else{//自动登录失败,显示登录页面
                    var v=plus.webview.getWebviewById('login');
                    if(!v){
                        mui.toast('error:cannot find login');
                    }else{
                        v.show('slide-in-right',300);
                    }
                }
            });
        }
    };
    </code></code></code></code></code></code></code></code></code></code>

    为了确保上面能找到登录页面,需要先预加载login页面,由于主页面是main,不再是login了,可以在main里面预加载login.html,然后这里就会找到login的webview

    看到里面调用了一个tryAutoLogin的自动登录函数,这个函数尝试用保存在state中的上次登录信息自动ajax请求服务器登录。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <code><code><code><code><code><code><code><code><code><code><code><code>/**
     * 尝试自动登录
     * @param {Function} callback 回调函数,接收一个字典参数data,data.Code>0表示登录成功
     */
    owner.tryAutoLogin=function (callback){
        var state=owner.getState();
        if(state.isLogin){
            callback({Code:1});
            return;
        }
        var user=JSON.parse(localStorage.getItem('$user'));
        //需要在登录或注册成功时将用户信息保存在localStorage中
        var settings=owner.getSettings();
        if (settings.autoLogin&&user&&user.name) {
            owner.login(user,callback);
        }else{
            callback({Code:-1});
        }
    }
    </code></code></code></code></code></code></code></code></code></code></code></code>

    tryAutoLogin的主要工作就是判断是否允许自动登录,如果允许就调用login方法尝试登录,并将回调函数也传递过去。

    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
    <code><code><code><code><code><code><code><code><code><code><code><code><code>/**
     * 用户登录
     **/
    owner.login = function(loginInfo, callback) {
        callback = callback || $.noop;
        loginInfo.Method='Login';//告诉服务器执行哪个函数
        $.ajax(owner.server,{//服务器地址
            data:loginInfo,
            success:function(data){
                if(data.Code==1){
                    plus.nativeUI.toast('登录成功');
                    var state=owner.defaultState;//登录后用默认State覆盖现有的State
                    state.isLogin=true;//标记已登录
                    state.user=data.Data;//保存用户信息
                    owner.setState(state);
                    //保存登录信息
                    localStorage.setItem('$user', JSON.stringify(loginInfo));
     
                    //通知资金变动页面刷新
                    var moneyChange=plus.webview.getWebviewById('moneyChange');
                    if(moneyChange){
                        mui.fire(moneyChange,'show');
                    }
                    //通知其他用户相关页面更新
                }
                callback(data);
            },
            error:function(msg){
                callback({
                    Code:-3,
                    Msg:'无法连接到服务器'
                });
            }
        });
    };
    </code></code></code></code></code></code></code></code></code></code></code></code></code>

    login函数中有一句是defaultState,这个就是存储的默认用户状态,用户注销再次登录后就应该用这个替换上次用户的状态。防止信息错乱。

    通过以上三个函数,就完成了页面登录的自动验证和访问控制,使得整体逻辑比较清晰,代码如有bug欢迎指正。

  • 相关阅读:
    java基础之二:取整函数(Math类)
    springboot:读取application.yml文件
    java基础之一:基本数据类型
    git操作之四:git branch(本地仓库)
    git操作之三:git reset
    git操作之二:git restore
    git操作之一:git add/commit/init
    Kubernetes 教程:在 Containerd 容器中使用 GPU
    Kubernetes 使用 Kubevirt 运行管理 Windows 10 操作系统
    在 macOS 中使用 Podman
  • 原文地址:https://www.cnblogs.com/xiangxinhouse/p/7519135.html
Copyright © 2020-2023  润新知