发表于: 2017-06-12 23:36:41

2 1196


今天完成的事情:

今天终于完成了对Johnpapa的Angular1风格指南的学习,这篇指南或者叫代码规范内容非常非常多,github地址:https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md

翻译版本地址:http://www.reqianduan.com/1722.html

虽然以前也学过html和css的代码规范,但是AngularJS毕竟是做应用的框架,所以规范中对语法、约定、结构化、模块化的要求就更加丰富而具体,总之与之前初学时写代码的风格相差很大。

明天计划的事情:

按照学习的代码规范进行复盘项目登录和信息管理部分js文件的编写。

遇到的问题:

这两天学习这个规范,复盘项目进度没怎么推进,需要加班赶赶了。

收获:

总结一下规范中几个比较重要的点,

1. 定义module

(function() {

  angular

    .module('admin',[

    'ngAnimate',

    'ngRoute',

    'app.shared',

    'app.dashboard'

    ]);

})();

把Angular组件包装到一个立即调用函数表达式中(IIFE),这个之前讲过了,

有助于防止变量和函数声明比预期在全局作用域中有更长的生命周期,也有助于避免变量冲突。

不使用任何一个使用了setter语法的变量来定义modules,用简单的setter语法来代替。

因为在一个文件只有一个组件的条件下,完全不需要为一个模块引入一个变量。

2. Getter

/* 避免 */

var app = angular.module('app');

app.controller('SomeController', SomeController);

function SomeController() { }


/* 推荐 */

angular

  .module('app')

  .controller('SomeController', SomeController);

function SomeController() { }

使用module的时候,避免直接用一个变量,而是使用getter的链式语法。

为什么?:这将产生更加易读的代码,并且可以避免变量冲突和泄漏。

3. 回调函数使用命名函数,不要用匿名函数。

angular

  .module('app')

  .controller('Dashboard', Dashboard);

function Dashboard () { }

易读,方便调试,减少嵌套回调函数的数量。

4. controllerAs with vm

/* 避免 */

function Customer ($scope) {

  $scope.name = {};

  $scope.sendMessage = function() { };

}


/* 推荐,但后面那个更好 */

function Customer () {

  this.name = {};

  this.sendMessage = function() { };

}


/* 推荐 */

function Customer () {

  var vm = this;

  vm.name = {};

  vm.sendMessage = function() { };

}

使用controllerAs 语法代替直接用经典的$scope定义的controller的方式。

使用controllerAs 时,controller中的$scope被绑定到了this上。

使用controllerAs语法时把this 赋值给一个可捕获的变量,选择一个有代表性的名称,例如vm代表ViewModel。


为什么?:congtroller被构建的时候,就会有一个新的实例,controllerAs 的语法比经典的$scope语法更接近JavaScript构造函数。

为什么?:这促进在View中对绑定到“有修饰”的对象的使用(例如用customer.name 代替name),这将更有语境、更容易阅读,也避免了任何没有“修饰”而产生的引用问题。

为什么?:controllerAs 是$scope的语法修饰,你仍然可以绑定到View上并且访问 $scope的方法。

为什么?:避免在controller中使用 $scope,最好不用它们或是把它们移到一个factory中。factory中可以考虑使用$scope,controller中只在需要时候才使用$scope,例如当使用$emit, $broadcast,或者 $on来发布和订阅事件时,可以考虑把这些调用挪到factory当中,并从controller中调用。

为什么?:this在不同的地方有不同的语义(就是作用域不同),在controller中的一个函数内部使用this时可能会改变它的上下文。用一个变量来捕获this的上下文从而可以避免遇到这样的坑。

5. 可绑定成员放到顶部

function Sessions() {

  var vm = this;


  vm.gotoSession = gotoSession;

  vm.refresh = refresh;

  vm.search = search;

  vm.session = [];

  vm.title = 'Sessions';


  ////////////////


  function gotoSession() {

  /* */

  }

  function refresh() {

    /* */

  }

  function search() {

    /* */

  }

}

在可绑定成员下面定义函数(这些函数被提出来),把具体的实现细节放到下面,可绑定成员放到顶部,这会提高代码的可读性。

6. 手动依赖注入

/* avoid */

angular

  .module('app')

  .controller('Dashboard', 

      ['$location', '$routeParams', 'common', 'dataservice', 

          function Dashboard($location, $routeParams, common, dataservice) {}

      ]);      


/* recommended */

angular

  .module('app')

  .controller('Dashboard', Dashboard);

Dashboard.$inject = ['$location', '$routeParams', 'common', 'dataservice'];

function Dashboard($location, $routeParams, common, dataservice) {

}

避免创建内嵌的依赖,因为一个数组太长不利于阅读,此外,内嵌的方式也会让人感到困惑,比如数组是一系列的字符串,但是最后一个却是组件的function。

7. 在activate函数中解决controller的启动逻辑

(function() {

  angular

    .module('app')

    .controller('Avengers', Avengers);

  function Avengers(dataservice) {

    var vm = this;

    vm.avengers = [];

    vm.title = 'Avengers';

    activate();

    function activate() {

      return dataservice.getAvengers().then(function(data) {

        vm.avengers = data;

        return vm.avengers;

      });

    }

  }

})();

把启动逻辑放在一个controller中固定的位置可以方便定位、有利于保持测试的一致性,并能够避免controller中到处都是激活逻辑。

activate这个controller使得重用刷新视图的逻辑变得很方便,把所有的逻辑都放到了一起,可以让用户更快地看到视图,可以很轻松地对ng-view 或 ui-view使用动画,用户体验更好。


返回列表 返回列表
评论

    分享到