使用DOM模板创建组件
[任务]
上节练习中,函数onAddItem里,直接使用了拼接html的方式动态创建列表项,当组件复杂时可读性和可维护性很差。
我们将使用示例应用自带的weui样式库美化列表项,并用DOM模板的方法重写创建组件过程,让代码更清晰。
一般情况下,不建议直接拼接html,而是通过模板及mvvm等技术来创建,这里给大家推荐开源的超轻量的jquery-dataview库,可在github中下载:
https://github.com/skyshore2001/jquery-dataview
或用这个git仓库:http://dacatec.com/git/jquery-dataview.git
。
下载后只需要jquery-dataview.min.js一个文件即可,把它复制到server/lib
目录下,在H5应用index.html中引用:
<script src="lib/jquery-dataview.min.js"></script>
然后在页面中定义列表项的模板,我们使用示例应用自带的weui界面样式库:(page/orders2.html)
<div mui-initfn="initPageOrders2" mui-script="orders2.js">
...
<div class="bd">
<div id="lst1" class="weui_cells weui_cells_access" data-ac="Ordr.query"></div>
</div>
<script id="tplOrder" type="text/template">
<div class="weui_cell" dv-on="li_click">
<div class="weui_cell_hd">
<i class="icon icon-dscr"></i>
</div>
<div class="weui_cell_bd weui_cell_primary">
<p><b name="dscr"></b></p>
<p>订单号: <span name="id"></span></p>
</div>
<div class="weui_cell_ft" name="status"></div>
</div>
</script>
</div>
上例中:
- 用script标签定义了id为
tplOrder
的html模板,要动态赋值的地方用name="xxx"
的方式标明,要处理事件的组件用dv-on
属性指定。
注意:H5标签template在现阶段的兼容性还够好,谨慎使用。 - 使用weui样式库美化列表。在列表”lst1”上添加了”weui_cells”等CSS类, 在列表每一项上用了”weui_cell”类,详细用法可查阅weui文档。
- 列表每项前用
<i class="icon icon-dscr"></i>
放置了一个名为icon-dscr
的图标。
在JS中(page/orders2.js),我们重写onAddItem函数,使用这个模板clone出每一项:
function initPageOrders2()
{
var jpage = this;
...
// 列表项模板
var jtplOrder_ = $(jpage.find("#tplOrder").html());
function onAddItem(jlst, itemData)
{
var ji = jtplOrder_.clone().dataview(itemData, {
events: {
li_click: li_click
}
}).appendTo(jlst);
}
...
}
jquery-dataview在做事件绑定时,会自动将数据绑定到事件上。
例中,在li_click(ev)
回调函数中,可以通过ev.data
拿到绑定的数据,因而刚好li_click
函数不用修改,取订单id可以用var id = ev.data.id
。
刷新分页列表
[任务]
控制刷新分页列表。
列表一旦显示后,每次回到该逻辑页时,不会重新请求数据或刷新,除非用户自己下拉刷新列表,这样保证了应用有良好的性能。
但有时需要在程序内控制列表刷新,考虑这样的需求:当一个订单在其它页面被修改了(例如取消订单),再回到订单列表页时希望能刷新列表。
initPageList
可以很简单地实现这一需求。
先为逻辑页定义一个接口:
var PageOrders2 = {
refresh: null,
}
在初始化列表时,添加一个pageItf选项(page interface缩写):
var listItf = initPageList(jpage, {
pageItf: PageOrders2,
...
});
在取消订单操作时,只要赋值:
PageOrders2.refresh = true;
这样下次进入orders2页时,就会刷新列表,并把PageOrders2.refresh置回false。可以在浏览器控制台上操作试试看。
如果想要立刻刷新列表,也可以用listItf.refresh()
操作。
listItf
是initPageList
返回值,是一个操作列表的接口,类似的操作还有显示下一页listItf.loadMore()
,详见参考文档。
列表用于选择
[任务]
(choose-from-list)在首页上加一个“选择订单”按钮,点击后进入订单列表页,选择一项后返回首页,并显示订单内容。
还是用”orders2”页,我们在index.js中定义页面接口如下(主要是choose方法和onChoose回调):
var PageOrders2 = {
...
// PageOrders2.choose(onChoose)
// onChoose(order={id,dscr,...})
choose: function (onChoose) {
this.chooseOpt_ = {
onChoose: onChoose
}
MUI.showPage('orders2');
},
chooseOpt_: null // {onChoose}
};
在页面orders2中:
- 点击一个列表项时,调用onChoose回调
- 页面隐藏时,清空chooseOpt_参数。
示例:
function initPageOrders2()
{
...
var pageItf_ = PageOrders2;
jpage.on("pagehide", onPageHide);
function li_click(ev)
{
var order = ev.data;
if (pageItf_.chooseOpt_) {
pageItf_.chooseOpt_.onChoose(order);
return false;
}
// 正常点击操作
...
}
function onPageHide()
{
pageItf_.chooseOpt_ = null;
}
}
我们回到首页,在浏览器控制台中模拟调用:
PageOrders2.choose(function (order) {
// 处理order
app_alert('选择了订单: id=' + order.id);
history.back(); // 由于进入列表选择时会离开当前页面,这时应返回
});
进入页面orders,选择一项后返回并继续操作。