前端神器avalonJS入门(三)

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

我们需要用到两个avalon路由配套模块—— mmHistory.jsmmRouter.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;width: 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调用,其值为当前匹配到的路径,比如当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。共勉~

时间: 2024-12-24 07:12:49

前端神器avalonJS入门(三)的相关文章

前端神器avalonJS入门(一)

转自:http://www.cnblogs.com/vajoy/p/4063824.html avalonJS是司徒正美开发和维护的前端mvvm框架,可以轻松实现数据的隔离和双向绑定,相比angularJS等前端框架它有如下优势: 1.压缩后仅有60多kb,而angular的min版是100多kb: 2.兼容IE6+,符合天朝市场需求: 3.效率更高,跑起来比angular和knockout都要更快,在移动端上该优势会更大(avalon有移动端专版的avalon.modern.js).关于其性能

前端神器avalonJS入门(二)

本章开始搭配requireJS来使用avalon,开始之前,我们可以对avalon进行精简改造(注:新版的avalon已提供了shim版本,无需再做如下的精简了,直接点这里获取). avalon源码里有自己的AMD加载器和DOMReady模块,使用requireJS来加载各依赖脚本的话,使用其配套插件DOMReady来ready执行会更合适,而且avalon的AMD模块也多余了.故我们可以把这俩块代码咔嚓掉. 只需要在源码里搜索“AMD”和“DOMReady”就能找到位于尾部的这俩模块,删掉它们

迷你MVVM框架 avalonjs 入门教程(司徒正美)

迷你MVVM框架 avalonjs 入门教程 关于AvalonJs 开始的例子 扫描 视图模型 数据模型 绑定属性与动态模板 作用域绑定(ms-controller, ms-important) 模板绑定(ms-include) 数据填充(ms-text, ms-html) 类名切换(ms-class, ms-hover, ms-active) 事件绑定(ms-on,……) 显示绑定(ms-visible) 插入绑定(ms-if) 双工绑定(ms-duplex) 样式绑定(ms-css) 数据绑

4步带你从Web前端小白到入门!

Web前端开发怎么入门,主要都有哪些要素组成?Web前端开发是由网页制作演变而来的,主要由HTML.CSS.JavaScript三大要素组成.专业的Web前端开发入门知识也一定会包含这些内容,下面就给大家简单介绍一下. HTML,超文本标记语言,标准通用标记语言下的一个应用.包括"头"部分(Head).和"主体"部分(Body),其中"头"部提供关于网页的信息,"主体"部分提供网页的具体内容. CSS,层叠样式表,是一种用来表

Flex入门(三)——微架构之Cairngorm

大家都知道我们在开发后台的时候,都会使用MVC,三层等分层架构,使后台代码达到职责更为分明单一,高内聚低耦合,例如,Dao层只是进行和数据库打交道,负责处理数据:Service(B层)只是进行逻辑判断处理,而Action则进行后台和前台页面的交互等.从而使程序更加容易管理,更加灵活,更加容易扩展,更加容易维护.也就是大家比较熟悉的Struts(SpringMVC)+Spring+Hibernate(Mybatis)等. 而作为前台Flex处理,也提供了类似的处理功能,想要达到的效果,也是代码分层

Swift语法基础入门三(函数, 闭包)

Swift语法基础入门三(函数, 闭包) 函数: 函数是用来完成特定任务的独立的代码块.你给一个函数起一个合适的名字,用来标识函数做什么,并且当函数需要执行的时候,这个名字会被用于“调用”函数 格式: func 函数名称(参数名:参数类型, 参数名:参数类型...) -> 函数返回值 { 函数实现部分 } 没有参数没有返回值 可以写为 ->Void 可以写为 ->() 可以省略 Void.它其实是一个空的元组(tuple),没有任何元素,可以写成() func say() -> V

Thinkphp入门三—框架模板、变量(47)

原文:Thinkphp入门三-框架模板.变量(47) [在控制器调用模板] display()   调用当前操作名称的模板 display(‘名字’)  调用指定名字的模板文件 控制器调用模板四种方式: [在控制器给模板传递变量] 在smarty里边给模板传递变量信息 $smarty -> assign(变量名称,值); 在tp框架里边同样适用assign()给模板传递变量信息 ThinkPHP的模板引擎的左右标记: ThinkPHP/Lib/ Behavior/ ParseTemplateBe

Redbean:入门(三) - Exec 以及 Query 以及 ConvertToBeans

<?php //引入rb入口文件 include_once 'rb.php'; //定义dsn以及相关的数据 $dsn = 'mysql:host=localhost;dbname=hwibs_model'; $user = 'root'; $pass = ''; $table = 'link'; //链接数据库 R::setup($dsn,$user,$pass); //链接数据表 R::dispense($table); //exec::直接执行一条sql语句[不需要链接表即可使用][参数2

AppleWatch开发入门三——代码交互与控制器生命周期

AppleWatch开发入门三--代码交互与控制器生命周期 一.引言 在前两篇博客中,讨论了关于watch开发中框架与界面布局相关,然而主要的逻辑,终究还是要通过代码来实现的,在我们创建了项目之后,就会生成InterfaceController这个文件,它就是我们storyBoard中的入口视图控制器. 二.代码交互与控制器声明周期 storyBoard中的控件我们可以通过拖拽的方式关联到文件中,Action和Outlet两种关联方式基本可以达到我们修改控件和处理业务逻辑的需求. WKInter