1.回顾第一张卡的一些遗漏知识
在第一张卡中,我们将新建的活动存储在localStorage中,因为并在这个过程中除了有活动名称外我们不知道其他的数据,因此就在localStorage中的活动列表中只是存储了每一个活动名称的一个列表,为了能够在活动列表页面有序的显示,我们将若干活动名称的一个数组存在localStorage中的一个键值对中。
var activity_name = $scope.activity_name;
var get_activity_list = JSON.parse(localStorage['activities');
get_activity_list.push(activity_name);
localStorage['activities'] = JSON.stringify(activity_list);
这里我们首先通过$scope.activity_name来获取页面用户输入的活动名称,然后从localStorage中读出之前存入的活动列表并且通过JSON的parse方法将其转化为原本的数据类型,接着使用数组的push方法将新的活动名称加入到活动列表的末尾(当然是在判断了活动名称不重复之后。。)。还有需要说明的一点就是在使用localStorage读取数据的时候,如果这个键不存在,那么JSON.parse()方法就会报错(经过测试如果不加在localStorage外面JSON.parse方法就不会报错)如下:
SyntaxError: Unexpected token u
at Object.parse (native)
......
2.根据新的需求,发现重构的必要
第二张卡的加入了活动报名的需求,但是在我们存储的活动列表里边只有一个名字,就没有办法在某一个活动正在进行的时候,返回活动列表,正在进行的活动显示黄色的背景。因此这个时候我们可以为每一个活动保存一个活动报名状态的属性。这个时候一个活动就有了两个属性,活动名称和活动报名状态(状态包括报名未开始,正在报名中,报名已结束)。很显然活动就成为我们这个项目中的一个model,代码如下
function Activity(activity_name, activity_sign_status) {
this.name = activity_name;
this.sign_status = activity_sign_status; //表示活动报名的不同状态,’0'表示未开始,‘1'表示正在报名,’2'表示活动已结束
}
以后的有关活动相关的数据操作或者其他操作都要集中在Activity这个model里边,以实现与控制层的分离。重构当然不仅仅存在与数据存储的方面,一旦发现之前的结构无法应对新的需求变化或者处理起来明显效率低的时候,就是应该进行重构的时候了。
3.通过传参数的方式跳转页面
当我们在点击活动列表的任意一个活动的时候,都会跳转到活动报名页面。显然根据点击的活动的不一样在活动报名页面不一样的只是显示的数据,在报名页面显示的报名信息要与我们当前点击的活动相对应。在第一张卡的时候我使用current_activity来存储点击的活动,然后通过读其中的值来找到对应报名的信息,然后显示。现在发现如果要给正在报名的活动显示黄色那还需要一个新的item来存储,如果页面类似跳转足够多那么就会有很多很多类似的item,这想想都是一种很低效率的做法,然后知道了可以通过传参数来很好的解决这个问题,而且可以在url中看到我们条转的是那个对应的页面,这看起来就漂亮多了。
首先我们需要知道我们点击的是哪一个活动,页面上代码如下:
<li class = "clearfix btn-default" ng-repeat="activity in activities " ng-click="click_event(activity)">
<h3 class="{{ activity.sign_status==1 || activity.name==current_biding_activity}}">
{{activity.name}} <i class="icon-angle-right"></i>
</h3>
</li>
这里我们注意ng-click="click_event(activity)",通过向这个函数传递一个参数activity来让后台获得当前点击的活动的名称,然后在controller里边代码如下:
$scope.click_event = function (value1) {
var p_temp = new Activity(value1.name, value1.sign_status);
if (!Activity.has_activity_signing() ) {
Activity.set_current_activity(p_temp);
}
$location.path('/activity_sign_up/' + p_temp.name);
}
只有当没有活动开始报名的时候才可以将当前活动的信息传递给current_activity。
注意到click_event()函数最后一句,在location.path里边加入了一个当前点击活动的活动名,这样就可以在页面跳转的时候将参数传递到目标页面吗?显然不是,因为angular的页面跳转都需要经过路由的指引,所以我们还必须给这个中间人进行一些必要的配置,代码如下:
.when('/activity_sign_up/:activity_name',{
templateUrl:'views/activity_sign_up.html',
controller:'activitySignUpCtrl'
})
这就是活动列表点击跳转至活动报名页面的路由配置,当目标页面需要传参数的时候,就是在.when中的第一个参数中后面加上 /:param_name。当这样设置了之后,以后所有的跳转至这个目标页面的path都必须带上参数,否则就要报错。。。
然后还差一个就是参数的接收,就像信件一样能够寄了,也有人送信,当然少不了收信的。在目标页面是如何接收参数的呢?代码如下:
var current_activity_name = $routeParams.activity_name;
同时还需要在controller的函数上加上参数$routeParams,即:
angular.module('partyBidApp')
.controller('activitySignUpCtrl',function($scope,$location,$routeParams){
...
});
4.开始报名之后按钮变成结束,结束后变成开始
通过各种设置状态量存储在localStorage中以及各种if {} else{} 来实现固然也可以实现,但是这些逻辑必然只能在controller中实现,而这这按钮的切换明显是显示层的东西,要硬塞给控制层肯定是比较违背MVC的设计思想的,在angular中我们有一个东西叫ng-switch,如其它ng系列的指令一样是放在页面的标签中的,然后在子标签中使用ng-switch-when和ng-switch-default来确定显示哪一个。这跟java这样的语言中的switch还是很相通的。
页面中的代码如下:
<div ng-switch="button_name">
<button class="btn btn-primary header-right" ng-click="start_sign_up()" ng-disabled="is_button_enable" ng-switch-when="start">开始</button>
<button class="btn btn-primary header-right" ng-click="end_sign_up()" ng-disabled="is_button_enable" ng-switch-when="end">结束</button>
</div>
在controller中我们还是要进行一定的控制,代码如下:
/*这段是当我们进入这个页面的时候,对按钮应该显示的样子进行一个初始化*/
if (current_activity_sign_status==1 ){
$scope.button_name = 'end';
}
else {
$scope.button_name = 'start';
}
/*这是当按钮显示开始的时候,点击的事件*/
$scope.start_sign_up = function() {
$scope.button_name = 'end';
Activity.activity_sign_start();
}
/*当点击结束按钮的时候,点击事件*/
$scope.end_sign_up = function() {
if (confirm('确定要结束此次报名吗?')){
current_activity_sign_status = 2;
Activity.activity_sign_end();
$location.path('/biding_list/'+current_activity_name);
}
else{
$scope.buttonName = 'end';
}
}
需要说明一下confirm(‘some conform information’),它会弹出一个确认窗口,如果点击OK则返回true,如果点击cancel则返回false。
5.短信报名
首先是我们通过在控制台调用notify_message_received(json_message)来模拟发短信,然后调用一个native_accessor中的send_sms 和 process_received_message方法来发送反馈信息和处理接收到的短信。这部分我们需要搞清楚的就是这个sms.js文件中的几个函数之间的调用关系,以及何时调用。
然后我们需要具体实现的就是处理短信部分的实现。
*判断接收的短信是否以正确的字符开头
*判断活动报名是否已经开始
*判断是否重复报名(也就是判断是不是同一个电话号码重复发送短信)
*如果成功报名,回复成功报名的信息
因为这里就是一下判断然后调用native_accessor的send_sms方法来在控制台模拟发短信,所以代码就不晒了。 send_sms 方法的代码如下:
<pre name="code" class="javascript">send_sms: function (phone, message) {
native_access.send_sms({"receivers":[{"name":'name', "phone":phone}]}, {"message_content":message});
// console.log('phone:'+phone);
// console.log('message:'+message);
},
如果在电脑上模拟就使用下面两个console,如果要打包安装到手机上,就使用上面一个方法native_access.send_sms。