@zongwu
2017-06-15T11:01:05.000000Z
字数 3757
阅读 380
内部资料
优惠券项目(新)基于原生JS的MVC架构
项目内置的依赖项目有:
* 模板渲染引擎 --- nunjucks.js, 原先是template.js 废弃它的主要原因是它只支持对字符串的模板渲染。而 HTML本身缺乏类似于Node中 include 或 require 的能力,template.js
不能切割模板文件,这会导致代码的可维护性与复用性均会有较大幅度的降低,故而采用nunjucks.js
来避免该问题。
* 内置jquery.js。
* 内置 require.js--- 用于模拟node
暴露成员方法。
项目基于mvc框架,项目的目录分为:
* app/controller
--- 控制器
* app/extend
--- 存放扩展的js工具类 , 目前存放的 environment.js
* app/public
--- 存放静态文件,诸如:css、image、第三方 js等资源
* app/service
--- 存放网络请求类
* app/view/components
--- 存放模板文件 此处的文件不允许通过链接直接访问
* app/view/
--- 存放html文件此处的文件允许通过链接访问(不包括components文件夹)
* app/router.js
--- 路由管理类,因为原生不具备拦截href的能力,所以选择使用hash作路由管理。原则上页面中不允许出现非路由管理的操作,考虑到框架的易用性允许jquery.js
对dom
做简单的处理。复杂的逻辑一定要配置到controller中,并通过router管理!!!
以展示优惠券首页的列表举例
Router.fn.extend({
register: function () {
// 配置访问路径:/home/coupon/list --> 指向控制器方法 home.coupon.list
router.mapping('/home/coupon/list', 'home.coupon.list');
},
ajax: function (path, param) {
if (router.contains(path))
router.callbackImpl(path, param);
else
throw new Error('Must register router uri first before use.');
},
});
Controller.fn.extend({
'home.coupon.list': function () {
// 通过require 函数拆分js模块 ,这样做的目的主要是为了工程化的管理。
// 所以允许在这里编写一些“足够简单”的实现,比如:页面重定向。
require('../controller/home/coupon.js').list();
}
});
require.register('../controller/home/coupon.js', function (module, exports, require) {
// 首页 - 优惠券列表
module.exports.list = function list() {
// 检查登录态
if (!window.iPuDong.checkLogin()) {
window.location.href = 'wxRedirect.html';
return;
}
var user = $._cookies_model.getUser();
// 执行接口请求
iPuDong.post({
_api: 'pd.coupon.search',
_v: '6.0',
_se: user.getSessionId(),
},
'#id-coupon',// 成功情况下的容器id
'./components/coupon.html',// 成功情况下的渲染模板
'#id-coupon',// 失败情况下容器id
'./components/dialog/warn.html');// 失败情况下的渲染模板
};
});
模板文件代码:
{% for coupon in model %}
{% if coupon.status == 0 %}<!--预热券-->
{% include "/components/coupon/coupon-preheating.html" %}
{% elif coupon.status == 1 %}<!--去领取-->
{% include "/components/coupon/coupon-gain.html" %}
{% elif coupon.status == 2 %}<!--请使用-->
{% include "/components/coupon/coupon-use.html" %}
{% elif coupon.status == 3 %}<!--已使用-->
{% include "/components/coupon/coupon-used.html" %}
{% elif coupon.status == 4 %}<!--已失效-->
{% include "/components/coupon/coupon-lapsed.html" %}
{% elif coupon.status == 5 %}<!--已结束-->
{% include "/components/coupon/coupon-end.html" %}
{% endif %}
{% endfor %}
以上有6种模板情况,此下只列举一种作为示意:
<div class="coupon-item coupon bg-postload"
value={{coupon.status}}
data-id={{coupon.id}}
data-promoCode="{{coupon.promoCode}}"
data-contain-img={{coupon.isProduct}}
data-type={{coupon.category}}>
<div class="content">
<div class="title_info">
<div class="price font-title-disable"><span>{{coupon.num}}</span></div>
</div>
<div class="linelapse"></div>
<div class="down">
<div class="left">
<img src="{{coupon.couponIcon}}" width="64px" height="64px">
</div>
<div class="right">
<div class="content_up">{{coupon.detail}}</div>
<div class="content_down">{{coupon.productName}}</div>
<div class="startTime">{{coupon.className}}</div>
</div>
</div>
</div>
<div class="icon-ended"></div>
</div>
到这里页面就可以渲染出来了。这里有一些约定需要补充一下。
1)router下配置的页面uri,和控制器方法 要求一一对应。
router.mapping('/home/coupon/list', 'home.coupon.list');
// 所以这里是 /home/coupon/list --> home.coupon.list 而不是其它(比如:home.coupon.xxx)。
2)控制器的方法home.coupon.list
要求与文件目录一一对应。
以显示某个优惠券的详情为例:
方法1,假设访问该页面的url如下:
http://www.domain.com/detail.html?couponId=232&status=2&isProduct=1
则下面 JS 代码表示 表示从url中获取参数并渲染该页面
router.ajax('/home/coupon/detail', [{
couponId: $._href.get('couponId'),
userCouponId: $._href.get('userCouponId')
}]);
方法2:访问以下连接同样可以渲染页面
http://www.domain.com/detail.html#/home/coupon/detail?couponId=232&status=2&isProduct=1
虽然看起来很多此一举
,但在Ajax
局部刷新时它会非常实用。
如下方代码:查看商品详情
,对于 HTML 页面我的原则是尽量保持它干净。
<a href="#/home/page/product?couponId={{model.id}}&status={{model.status}}&isProduct={{model.isProduct}}&promoCode={{model.promoCode}}">
<div id="lookdetail" class="checkask">查看详情</div>
</a>