我们另一个系统是把angular用在单页面应用里,对angular做了一些定制,集成了seajs,没有用angular自己的模块管理。不过angular单独使用也是可以的,新开发的一个较小的系统,就没有使用前端js的模块管理,而是简单集成了ejs和angular,本文是一个简单的demo
首先是express的一个服务,用于跳转到ejs。该服务类似于struts2里的action类:
function myAccount(req, res, next){ res.render("binding_list", {layout:"storeadmin_layout", menu:"myAccount"}); }
<%- Loader().js('/weixin/weixin.js').done(config) %> <div ng-controller="WeixinController"> <span ng-if="hasBinding">已绑定</span> <span ng-if="!hasBinding">未绑定</span> </div>
<script src="/weixin/weixin.js?v=1407754967801"></script> <div ng-controller="WeixinController"> <span ng-if="hasBinding">已绑定</span> <span ng-if="!hasBinding">未绑定</span> </div>
function WeixinController($scope){ $scope.name = "kyfxbl"; $.get("/svc/weixin/checkBinding", function(res){ $scope.hasBinding = res.flag; $scope.$digest(); }); }
这时候,浏览器已经加载了angular.js和weixin.js,这2个文件里的代码,都是在浏览器里执行的,和服务端的express和ejs已经没有关系了 。后面就是angular在起作用,对html文件再次编译,得到的就是最终呈现给用户的界面
这个过程分为2个阶段,第一个阶段跑在node里,主要是ejs引擎起作用,把.ejs文件渲染成html文件,发响应给回浏览器。第二个阶段跑在浏览器里,主要是angular起作用,把html里的变量,替换为$scope中的模型。所以这里有2次变量替换的过程,在服务端是把<%= %>替换成render函数传递的模型;在客户端是把{{ }}替换成&scope上挂载的模型
主要容易混淆的地方在于,如果想在server端把值写到weixin.js里该怎么做
比如说,在.ejs里有这么一个表达式:
{{ name }}
$scope.name = "kyfxbl";
一种是把js嵌入到.ejs中(就不需要单独的weixin.js了):
<script> function WeixinController($scope){ $scope.name = "<%= name %>"; } </script> <div ng-controller="WeixinController"> {{ name }} </div>
1、把js代码直接嵌在html里,这种做法很不好。因为复杂一点的页面,<script>里的内容会变得很长,很难维护。而且js压缩工具,也不好处理这种情况。最佳实践是把js和html分离开
2、render传过来的name变量,还需要手工地加上"",否则的话就会报错。<script>里到处都需要这么处理,非常容易出错,定位起来也很麻烦
所以最好是采用第二种方式,还是把.ejs和weixin.js分离开,weixin.js里初始化angular controller的时候,再次去服务端请求需要的变量:
function WeixinController($scope){ $scope.name = "kyfxbl"; $.get("/svc/weixin/checkBinding", function(res){ $scope.hasBinding = res.flag; $scope.$digest(); }); }