界面实现
无论是WEX还是BEX,开发各种客观题模块都是最常见的。但是,最近在利用业余时间想开发一个学生使用的小型客观题系统时遇到了麻烦。首先,在论坛上搜索到了大量相似问题。问题或者过于简单,或者过于特殊。且看一下本人提供的客观题界面,我相信这种设计思路还是与大多数应用需求相一致的。
这是单选题界面和多选题界面。
注意:我每一个小题旁边放置的按钮是便于学生自我测试时看参考答案时使用的。这个小功能设计比较简单(我使用的是PopOver组件,其内的span对应的bind-text令其等于 $model.singleData.val("fAnswer")类似的内容即可实现即时地查看对应小题的答案)。
问题
在开发类似于上面的系统时注意到不少像我这样的初学者存在与我十分类似的困惑。
(补注:这样人可能以前有JAVA,C#,VB等UI开发经验,但遗憾的是,这些软件开发思路与X5中的H5开发思想发生了重大变化--不知大伙与我意见一致否?)
归纳起来,问题有:
1,list组件的onClick 事件中 如何得到 list某一行的id? 地址:http://doc.wex5.com/comps-list/。
2,如何在list组件中放置radio组件或者radioGroup组件实现类似于我实现的上述选择题界面?
3,在上面界面前提下,在用户做过好几个小题后,如果对比答案(比较库中正确与错误的答案,检查其做题效果如何)?
补充
由于我上述小系统比较简单,所以暂时只考虑使用本地json方式存储试题内容,单选,多选,判断等都各自对应一个JSON文件。例如,单选题文件singleData.json类似于如下结构:
[
{"fCode":"0401",
"fTrunk":"在数据库表格中唯一标识一条记录的是( )。",
"fChoiceA":"A.主键",
"fChoiceB":"B.候选键",
"fChoiceC":"C.索引",
"fChoiceD":"D.关键字",
"fAnswer":"A"
},
{"fCode":"0402",
"fTrunk":"下列哪一种不属于ACCESS 2010的数据类型( )。",
"fChoiceA":"A.数字",
"fChoiceB":"B.文本",
"fChoiceC":"C.附件",
"fChoiceD":"D.插件",
"fAnswer":"D"
},
{"fCode":"0403",
"fTrunk":"下列哪一种不属于ACCESS 2010的关系表达式中的逻辑运算符( )。",
"fChoiceA":"A.And",
"fChoiceB":"B.Not",
"fChoiceC":"C.Or",
"fChoiceD":"D.Else",
"fAnswer":"D"
},
{"fCode":"0404",
"fTrunk":"ACCESS 2010六大对象不可以( )。",
"fChoiceA":"A.删除",
"fChoiceB":"B.隐藏",
"fChoiceC":"C.创建",
"fChoiceD":"D.创建快捷方式",
"fAnswer":"D"
},
............
]
多选题文件结构类似于:
[
{"fCode":"0401",
"fTrunk":"数据库管理系统主要包含以下功能( )。",
"fChoiceA":"A.数据定义",
"fChoiceB":"B.数据操纵",
"fChoiceC":"C.数据库运行管理",
"fChoiceD":"D.数据库建立和维护",
"fChoiceE":"E.数据通信功能",
"fAnswer":"ABCDE"
},
{"fCode":"0402",
"fTrunk":"数据库管理系统的简称是( )。",
"fChoiceA":"A.DB",
"fChoiceB":"B.DBMS",
"fChoiceC":"C.ORDBS",
"fChoiceD":"D.RDBS",
"fChoiceE":"E.DDL",
"fAnswer":"B"
},
{"fCode":"0403",
"fTrunk":"关系是具有如下特征的二维表( )。",
"fChoiceA":"A.行存储实体数据",
"fChoiceB":"B.列存储实体属性",
"fChoiceC":"C.每列具有唯一名称且数据类型一致",
"fChoiceD":"D.列的顺序任意,行的顺序也任意",
"fChoiceE":"E.任意两行内容不能完全重复",
"fAnswer":"ABCDE"
},
{"fCode":"0404",
"fTrunk":"ACCESS 2010六大对象包括( )。",
"fChoiceA":"A.表",
"fChoiceB":"B.查询",
"fChoiceC":"C.窗体",
"fChoiceD":"D.宏",
"fChoiceE":"E.模块",
"fAnswer":"ABCDE"
},
{"fCode":"0405",
"fTrunk":"ACCESS 2010中查询分为两大类型,它们是( )。",
"fChoiceA":"A.选择查询",
"fChoiceB":"B.删除查询",
"fChoiceC":"C.操作查询",
"fChoiceD":"D.生成表查询",
"fChoiceE":"E.SQL查询",
"fAnswer":"AC"
}
]
加载上述试题内容的方式官方DEMO中大量提供类似代码,直接使用即可(下面是我加载单选内容的代码):
Model.prototype.singleDataCustomRefresh = function(event){
var singleData = event.source;
$.ajax({
type: "GET",
url: require.toUrl('./json/singleData.json'),
dataType: 'json',
async: false,
cache: false,
success: function(data){
singleData.loadData(data);//将返回的数据加载到data组件
},
error: function(){
throw justep.Error.create("加载数据失败");
}
});
};
至于设置单选题对应数据组件singleData的limit等属性小问题及radio和radioGroup组件的常见属性设置在此小不赘述了(我使用的是radioGroup组件设计单选题界面)。
真正的问题
可能受到以前UI设计思路的影响,很可能大家的问题都集中在前面列举的问题1上,即“list组件的onClick 事件中 如何得到 list某一行的id”。但是,看X5的UI组件设计思想,这种想法本身可以理解,但是在X5 UI编程中是不能考虑的(即它无法支持)。
例如,无论在官方‘文档中心’的list组件介绍或者‘如何主动定位到行’(http://bbs.wex5.com/forum.php?mod=viewthread&tid=117208&highlight=list%E7%BB%84%E4%BB%B6)帖子中,都提供类似于这样的描述:
“
数据再多也是遍历!
wex5开发项目,准守的一个原则就是面向数据变成,面向data组件编程!
页面一切操作都是直接操作数据组件的!”
如果上面这个问题1解决了,那么其他相应问题便迎刃而解!不知官方权威开发朋友对此是如何解释的(因为那个‘文档中心’的问题贵方并没有给予解释)。
我遇到的一个具体问题
在上面以单选题为代表的设计下,我很自然地想到了radioGroup的onChanged事件,于是添加了如下代码:
Model.prototype.radioGroupSingleChange = function(event){
var crow = this.comp('singleData').getCurrentRow();//start from 0
//var id1 = this.comp('singleData').getRowID(crow);
console.log('Current row index: '+" "+crow.index());
//var context=event.bindingContext;
//var span1=this.comp('outputSingle');
//console.log("No: "+span1.innerText);
//debugger;
var data=this.comp('singleData');
var v = data.getValue('fCode');
console.log("fCode: "+v);
//get question seqCode
var i=data.val("fCode").substring(3);
//怎么总是输出相同的第1题,选择A
//store the user select
console.log('第'+i+'题');
//获取radioGroup的值
var val = this.comp("radioGroupSingle").val();
console.log('select: '+val);
//data.next();
//var confirmRefresh = data.confirmRefresh;
//强制刷新数据
//data.refreshData();
// try{
// data.confirmRefresh = false;
// data.refreshData();
// }finally{
// data.confirmRefresh = confirmRefresh;
// }
//data.refresh();
};
上面的注释内容我添加了又删除,删除了又添加,反复试验多次,结果只有一个:并不输出当前题号,即只是显示list中第一项,即数据组件第一行中对应内容!
一种勉强的解决办法
一下找不到那个帖子了,他是在每一个界面中只显示一个题(无论是单选还是多选),然后下面放置类似于‘第一个’‘下一个’‘最后一个’‘最开始’等常见导航按钮,这样设置界面的话问题简单得多了,即使用类似于上面的radioGroup的onChanged事件中,调用数据组件的next,prev等方法即可实现每一小题的实时定位。这种方案容易多了!
但是,想一下,如今的智能手机屏幕越来越大,不考虑使用scrollView与list组件(其中放置每道试题相关内容)结合,每一页中显示N道题,显然是不友好的设计。即上述设计方案存在片面性,而不是更为一般的方案。
我目前想到的针对我的上面设计的另一种尚未试验的方案是,在DATA组件设计中,再添加一个答案列。上面的fAnswer这一列对应于正确的标准答案,可以再添加一个用户本人选择答案的存储列,例如称为fUserAnswer。我们不去考虑类似于上面onChanged事件中准确定位每一题的题号的问题,而只是关注用户做题结束后通过对应上面的两个列,让用户知道他做对了哪些?做错了哪些即可。另外,有了上面的即时提示按钮,他当时做第X小题的正确与否情况问题也解决了。不知各位看法如何?
我抓紧试验一下,结果将会一并提交于下面。