zoukankan      html  css  js  c++  java
  • 前端神器avalonJS入门(三)

    本章将介绍如何使用avalon来实现前端路由功能。

    我们需要用到两个avalon路由配套模块—— mmHistory.js 和 mmRouter.js 。其中mmHistory是用于历史管理,它会劫持页面上所有点击链接的行为,当这些链接是以 #/ 、#!/ 开头,就尝试匹配路由规则,阻止页面刷新(通过hash方式或HTML5的replaceState方式)。mmRouter是给我们定义路由规则,路由规则可以更精细地指定每个参数(param)的匹配规则,如果符合就执行对应的回调,如果不符合,就进入error回调。

    关于该路由系统更具体的描述,可以查阅这里

    作为示例,我们打算制作一个网站的 “用户中心” 页面,其中左侧为导航列表,右侧为受左侧列表控制的内容显示区域:

    该“用户中心”页面有这么几个要求:

    ⑴ 页面不跳转,仅做局部(即内容区域部分)刷新;

    ⑵ 可以通过不同的url进入对应的页面(即内容区域显示对应的内容);

    ⑶ 浏览器能记住url状态,比如从“账户详情”点入“我要充值”页面,然后再点击浏览器返回按钮,可以正确回到“账户详情”页面。

    由于不是石器时代,自然不会再选择iframe这种内耗高、不友好的元素来架构页面(而且iframe也实现不了后面两个需求呀)。那么我们会很快联想到Ajax技术,这个想法很本质,不过单纯的Ajax也没办法达到我们的要求,所以才需要引入开头提到的两个avalon路由模块。

    我们可以先写出简单的页面原型:

    index.html:

    复制代码
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title>账户中心</title>
        <link rel="stylesheet" href="css/user.css">
        <script src="js/lib/require.js" type="text/javascript" data-main="js/page/user"></script>
    </head>
    <body ms-controller="user" class="ms-controller">
    <script type="text/javascript">
        //这里给后端提供数据接口
        var conf = {
            username: {"id": "11", "name": "VaJoy"}
        }
    </script>
    <header>
        <span>{{username.name}}你好,欢迎来到账户中心</span>
    </header>
    <nav>
        <ul>
            <li><a href="#!/index">我的首页</a></li>
            <li><a href="#!/detail">账户详情</a></li>
            <li><a href="#!/recharge">我要充值</a></li>
        </ul>
    </nav>
    <article>
        内容...
    </article>
    </body>
    </html>
    复制代码

    user.js:

    复制代码
    require.config({
        baseUrl: 'js/lib/', 
        paths:{   
            avalon: 'avalon',
            domReady:'domReady',
            mmHistory: 'mmHistory',
            mmRouter: 'mmRouter',
            jquery: 'jq'
        },
        shim:{
            avalon: { exports: "avalon" },
            mmHistory:{ deps: ['avalon']},
            mmRouter:{ deps: ['avalon']}
        }
    });
    
    require(['avalon',"domReady!"], function() {
        var vm = avalon.define({
            $id: "user",
            username:conf.username
        });
        avalon.scan();
    });
    复制代码

    user.css:

    复制代码
    body,html{padding: 0;margin:0;background: #EEE;}
    .ms-controller{visibility: hidden;}
    header{height: 50px;background: white;}
    header>span{display:block;padding: 16px;}
    nav{position: absolute;left:0;margin-top:50px; 200px;}
    nav>ul>li{margin-top: 12px;}
    nav>ul>li>a{text-decoration: none;color:blue;}
    nav>ul>li>a:hover{color:red;}
    article{padding: 15px;margin-left:200px;min-height: 600px;background: white;}
    复制代码

    运行结果如下:

    接着我们要新建三个页面——mine.html、detail.html 和 recharge.html ,分别对应“我的首页”、“账户详情” 和 “我要充值” 的右侧内容,咱在里面随便写点内容意思意思即可,比如mine.html我就写了一句话:

    接着我们默认先把mine.html引入到index.html中,这里我们借助avalon的 ms-include-src 接口,修改下index.html:

    复制代码
    <nav>
        <ul>
            <li><a href="#!/index">我的首页</a></li>
            <li><a href="#!/detail">账户详情</a></li>
            <li><a href="#!/recharge">我要充值</a></li>
        </ul>
    </nav>
    <article ms-include-src="pageUrl"> <!--这里使用ms-include-src接口,它会引入pageUrl属性所对应的文件-->
    </article>
    复制代码

    接着修改 user.js的部分:

    复制代码
    require(['avalon',"domReady!"], function() {
        var vm = avalon.define({
            $id: "user",
            username:conf.username,
            pageUrl:"mine.html"  //默认为mine.html
        });
        avalon.scan();
    });
    复制代码

    运行如下:

    接着是时候让 mmHistory.js 和 mmRouter.js 发挥它们的作用了,我们修改下user.js的部分代码:

    复制代码
    require(['mmHistory','mmRouter',"domReady!"], function() {
        var vm = avalon.define({
            $id: "user",
            username:conf.username,
            pageUrl:"mine.html"  //默认为mine.html
        });
        function callback() {
            if(this.path==="/index"){
                vm.pageUrl="mine.html";
            }else {
                var path_tail = this.path.replace(///, "");
                vm.pageUrl = path_tail + ".html";  //动态修改pageUrl属性值
            }
        }
        avalon.router.get("/*path", callback); //劫持url hash并触发回调
        avalon.history.start(); //历史记录堆栈管理
        avalon.scan();
    });
    复制代码

    注意由于在 require.config 的 shim 中我们已经定义了 mmHistory.js 和 mmRouter.js 是依赖于avalon的,故此处无须再引入avalon模块,requireJS执行该代码段之前会先加载好avalon的。

    我们通过这两行代码执行了路由和历史记录的管理:

        avalon.router.get("/*path", callback); //劫持url hash并触发回调
        avalon.history.start(); //历史记录堆栈管理

    其中router.get() 的第一个参数表示路由匹配规则,比如这里的“/*path”表示匹配全部路径,匹配到了就触发回调callback函数。

    更多的匹配规则我们可以直接在  mmRouter.js 中查看注释信息:

    router.get() 在触发callback前会生成一个this.path属性供callback调用(你也可以给回调函数定义一个参数,其默认值等同与path),其值为当前匹配到的路径,比如当url后缀变成 #!/recharge 的时候,this.path的值为匹配到的"/recharge" 。了解了这个之后,callback 函数也很好理解了:

    复制代码
        function callback() {
            if(this.path==="/index"){
                vm.pageUrl="mine.html"; //如果url后缀变成"#!/index",则pageUrl为“mine.html”
            }else {
                var path_tail = this.path.replace(///, ""); //去掉this.path值的第一个斜杠
                vm.pageUrl = path_tail + ".html";  //动态修改pageUrl属性值
            }
        }
    复制代码

    这时候的运行结果如下所示:

    自此便实现了我们的需求。但是这样还不够完美——每个页面的样式咋处理呢?

    我们可以直接在页面上写<style>标签,或者直接写个<link>引入外部样式文件,但前者不好维护,后者毕竟不是插入到head中的不太规范。那么我们能否也用requireJS模块化动态引入样式文件呢?答案是肯定的,不过得借助于其组件css.js

    以“账户详情”(detail.html)为例,我们创建一个detail.css文件,里面设置 .detail{color:red;}。

    先确保require.config中的paths里加上了该组件:

    复制代码
        paths:{   //这里配置的地址,都是相对于上方的baseUrl的
            avalon: 'avalon',
            domReady:'domReady',
            mmHistory: 'mmHistory',
            mmRouter: 'mmRouter',
            css: 'css'  //加上css.js
        }
    复制代码

    然后修改detail.html页面内容:

    复制代码
    <section ms-controller="detail" class="detail ms-controller">
        哟哟哟,这里是详情页面,{{username.name}}你好
    </section>
    <script>
        require(['avalon','css!../../css/detail.css'], function(){
        //下面的其实建议写成一个模块detail.js然后由require引入
            avalon.define({
                $id: "detail",
                username: conf.username
            });
            avalon.scan();
        })
    </script>
    复制代码

    “css!/XXX.css” 是css.js的写法,注意以"css!"开头即可。

    运行结果如下:

    以上便是avalon前端路由的简单实现,本章的示例代码可以从这里下载。

    后续章节可能会开始写一写avalon的API。共勉~

  • 相关阅读:
    GolandQuick编辑器快捷键
    GitStand
    高阶函数
    文本和字节序列
    元组用法
    映射的弹性键查询
    字典的setdefault()
    数组、内存视图、双向队列
    Python之random.seed()用法
    用bisect来管理已排序的序列
  • 原文地址:https://www.cnblogs.com/cymbidium/p/5341404.html
Copyright © 2011-2022 走看看