Angular.JS 之 全局对象变更的实时响应
AngularJS是一款来自Google的前端JS框架,体积非常小,但是设计理念和功能却非常强大。
教程
问题
在一款Web应用中,虽然我们尽可能的避免无节制地使用全局变量,但有时确实需要一些全局变量的存在已保证在所有页面中都能处理某些事件。
在本文的例子中,该应用需要在安卓平台上接收手机短信并实时响应(此处先撇开具体的实现插件,接收和发送短信都用控制台来模拟),为此我们定义了一个JavaScript的全局对象如下:
1 var native_accessor = { 2 //发送短信函数 3 send_sms: function (phone, message) { 4 //通过控制台模拟 5 console.log(phone, message); 6 //实际插件调用 7 //native_access.send_sms({"receivers":[{"name":‘name‘, "phone":phone}]}, {"message_content":message}); 8 }, 9 10 //接收短信函数 11 receive_message: function (json_message) { 12 if (typeof this.process_received_message === ‘function‘) { 13 this.process_received_message(json_message); 14 } 15 }, 16 17 //处理短信函数 18 process_received_message: function (json_message) { 19 Message.received_new_item(json_message); 20 } 21 } 22 23 //接收短信时自动调用的函数 24 function notify_message_received(message_json) { 25 native_accessor.receive_message(message_json); 26 }
上面的代码中设立了一个Javascript的全局对象native_accessor和一个全局函数notify_message_received(message_json),其中native_accessor由三个不同功能函数组成。当系统接收到短信时,将会自动触发notify_message_received(message_json)函数。
在本例中,有一个活动报名页面,其中需要显示所有已报名者的电话,收到有效的报名短信后要自动对页面进行更新。(当然,即便不在活动报名页面还是依然要能够接收短信的。)活动报名页面的相关html代码如下:
1 <div id="detail_scope"> 2 <ul class="list-group"> 3 <li class="list-group-item" ng-repeat="message in message_list | orderBy:‘-name‘"> 4 {{message.name}} 5 <span class="pull-right">{{message.phone}}</span> 6 </li> 7 </ul> 8 </div>
上面的代码中,我们创建了一个显示“姓名”和“号码”的列表,姓名在左号码在右。其中,为了能够在外部访问这个AngularJS模板,我们在这个div中增加了一个id标签,内容可以任意(在该控制器内的任意元素上使用该id标签均可)。
接下来,由于在上面的代码中我们在收到短信时调用了Message.received_new_item(json_message)这个方法,现在我们来考虑相关的实现代码:
1 //这部分可以忽略,直接看Message.refresh_ui_list() 2 Message.received_new_item = function(message_json) { 3 var message_text = message_json.messages[0].message; 4 var message_phone = message_json.messages[0].phone; 5 var header_is_right = message_text.substring(0,2).toUpperCase() == ‘BM‘; 6 //检查短格式信是不是为“BM”打头 7 if(header_is_right) { 8 var message_name = message_text.substring(2).replace(‘ ‘, ‘‘); 9 //检查当前的活动状态是否允许报名 10 var activity_status = localStorage.getItem("activity_status") || "prepare"; 11 if(activity_status == "prepare") { 12 Message.sendback_info(message_phone, "early"); 13 } 14 else if(activity_status == "over") { 15 Message.sendback_info(message_phone, "late"); 16 } 17 else { 18 var message_list = Message.get_all_items(); 19 //检查该人员是否重复报名 20 if(!Message.check_if_repeat(message_phone)) { 21 var activity_name = Activity.get_current_item(); 22 message_list.splice(0,0,{name:message_name, phone:message_phone, activity:activity_name}); 23 Message.save_all_items(message_list); 24 //这里才是调用的页面刷新函数 25 Message.refresh_ui_list(); 26 Message.sendback_info(message_phone, "success"); 27 } 28 } 29 } 30 }; 31 32 33 //实现页面自动刷新的函数 34 Message.refresh_ui_list = function () { 35 //将页面部分的scope提取出来作为变量 36 var detail_scope = angular.element("#detail_scope").scope(); 37 //如果应用不在该页面,该变量为undefined,继续执行控制台会报错(不过依然可以执行) 38 if(detail_scope) { 39 //需要特别注意的$apply方法 40 detail_scope.$apply(function () { 41 detail_scope.update_when_receive(); 42 }); 43 } 44 };
在上面的代码中,为了能够在全局中调用对用controller的scope内的函数,我们通过angular.element("#element_id").scope()的方法从AngularJS中提取出该scope,此时可以把该scope看作一个的JavaScript对象。接着就可以使用调用对象函数的方法来调用scope内的函数了。
需要注意的是,直接调用该方法时,虽然对应的数据能够发生更新,但是并不会直接影响页面,不知道是不是非UI线程不能直接修改UI元素的道理。为此,我们需要通过调用$apply方法,而将所需函数作为该方法的参数,这样就能实现页面的同步更新了。
顺便贴一下被调用的局部方法:
1 $scope.update_when_receive = function () { 2 $scope.message_list = Message.read_all_items($scope.activity_name); 3 if($scope.message_list.length != 0) { 4 $scope.member_count = "(".concat($scope.message_list.length.toString()).concat("人)"); 5 } 6 else { 7 $scope.member_count = ""; 8 } 9 };
这里的方法中实现了更新列表和统计人数的功能,鉴于在本文中确实不重要,此处稍稍略过,完整带项目代码请见https://github.com/trotyl/party_bid
如对于本文中的任何内容有疑问或者想要提供一些意见或建议,都可以在下方评论或者私信联系~
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。