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欢迎指正。

HBuilder mui登录和访问控制教程--转载的更多相关文章

  1. 跨平台移动APP开发进阶(二)HTML5+、mui开发移动app教程

    前端开发APP,从HBuilder开始~ 序 通过 HTML5 开发移动App 时,会发现HTML5 很多能力不具备.为弥补HTML5 能力的不足,在W3C 中国的指导下成立了www.HTML5Plu ...

  2. GJM : Taurus.MVC 2.0 开源发布:WebAPI开发教程 [转载]

    Taurus.MVC 2.0 开源发布:WebAPI开发教程 转载自http://www.cnblogs.com/cyq1162/p/6069020.html 因是新手  粘贴时有一个版权问题 本文原 ...

  3. iOS: 学习笔记, Swift与Objective-C混用简明教程(转载)

    Swift与Objective-C混用简明教程 转载自:https://github.com/lifedim/SwiftCasts/tree/master/000_mix_swift_objc 我想很 ...

  4. CAS单点登录(SSO)完整教程

    转:http://blog.csdn.net/frinder/article/details/7969925 CAS单点登录(SSO)完整教程(2012-02-01更新) 一.教程说明 前言 教程目的 ...

  5. WEKA使用教程(经典教程转载)

    http://blog.csdn.net/yangliuy/article/details/7589306 WEKA使用教程(经典教程转载) 标签: lift算法csv数据挖掘class任务 2012 ...

  6. HBuilder/Mui开发ios使用上拉刷新导致滚动条无法使用的解决方法

    HBuilder/Mui开发的APP使用上拉刷新,当滚动到底部是会触发上拉刷新,加载更多数据.但是ios上确是一个坑,导致滚动条无法滚动. 解决方法 放弃Mui的上拉刷新,自己使用JS实现. var ...

  7. 移动 App 接入 QQ 登录/分享 图文教程

    移动 App 接入 QQ 登录/分享 图文教程 这里先要提两个平台,腾讯开放平台和 QQ 互联平台: (一)腾讯开放平台 官网地址:https://open.tencent.com/ 介绍:腾讯开放平 ...

  8. RHEL 6.3安装(超级详细图解教程)[转载]

        附:RHEL6.3下载地址 32位:http://rhel.ieesee.net/uingei/rhel-server-6.3-i386-dvd.iso 64位:http://rhel.iee ...

  9. SSO之CAS单点登录详细搭建教程

    本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...

随机推荐

  1. java-HttpGetPost-图片字节流上传

    在java程序开发中经常用到与服务端的交互工作,主要的就是传递相应的参数请求从而获取到对应的结果加以处理 可以使用Get请求与Post请求,注意!这里的Get请求不是通过浏览器界面而是在程序代码中设置 ...

  2. preg_replace 以及弃用的e

    preg_replace (PHP 4, PHP 5) preg_replace — 执行一个正则表达式的搜索和替换 说明¶ mixed preg_replace ( mixed $pattern , ...

  3. Linux学习—导航文件系统

    与windows相同,Linux操作系统也是以被称之为分层目录结构的方式来组织文件的.这意味着文件是以树形结构的目录中进行组织的,该树形结构目录可能包含文件和其他目录.文件系统的第一个目录叫做根目录, ...

  4. oracle selinux 问题

    Error: cannot restore segment prot after reloc: Permission Denied http://www.oracledistilled.com/ora ...

  5. lintcode-450-K组翻转链表

    450-K组翻转链表 给你一个链表以及一个k,将这个链表从头指针开始每k个翻转一下. 链表元素个数不是k的倍数,最后剩余的不用翻转. 样例 给出链表 1->2->3->4->5 ...

  6. lintcode-65-两个排序数组的中位数

    65-两个排序数组的中位数 两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n)). 样例 给出数组A = [1,2,3,4,5,6] B = [ ...

  7. erlang中检查内存泄露

    最近项目内存占用过多,检查一下erlang的内存使用情况. 1. 通过etop可以很方便得出erlang内存使用的情况 spawn(fun() -> etop:start([{output, t ...

  8. 201621123037 《Java程序设计》第6周学习总结

    作业06-接口.内部类 1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图或相关笔记,对面向对象思想进行一个总结. 注1:关键词与内容不求多 ...

  9. mysql中变量

    mysql中的变量: mysql中,有两种变量形式: 普通变量: 不带“@”符号: 定义形式: declare  变量名  类型名   [default  默认值]: //普通变量必须先这样定义 赋值 ...

  10. Delphi实现DBGrid Shift+鼠标左键单击 多选

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...