其中第一个 identifierForController 会中controller属性为字符串时(controller: 'SomeCtrl as something'), 提取 as 后边的名字,源码如下:
var CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/;
function identifierForController(controller, ident) {
if (ident && isString(ident)) return ident;
if (isString(controller)) {
var match = CNTRL_REG.exec(controller);
if (match) return match[3];
}
}
this.component = function registerComponent(name, options) {
var controller = options.controller || function() {};
function factory($injector) {
function makeInjectable(fn) {
if (isFunction(fn) || isArray(fn)) {
return function(tElement, tAttrs) {
return $injector.invoke(fn, this, {$element: tElement, $attrs: tAttrs});
};
} else {
return fn;
}
}
var template = (!options.template && !options.templateUrl ? '' : options.template);
var ddo = {
controller: controller,
controllerAs: identifierForController(options.controller) || options.controllerAs || '$ctrl',
template: makeInjectable(template),
templateUrl: makeInjectable(options.templateUrl),
transclude: options.transclude,
scope: {},
bindToController: options.bindings || {},
restrict: 'E',
require: options.require
};
// Copy annotations (starting with $) over to the DDO
forEach(options, function(val, key) {
if (key.charAt(0) === '$') ddo[key] = val;
});
return ddo;
}
// TODO(pete) remove the following `forEach` before we release 1.6.0
// The component-router@0.2.0 looks for the annotations on the controller constructor
// Nothing in Angular looks for annotations on the factory function but we can't remove
// it from 1.5.x yet.
// Copy any annotation properties (starting with $) over to the factory and controller constructor functions
// These could be used by libraries such as the new component router
forEach(options, function(val, key) {
if (key.charAt(0) === '$') {
factory[key] = val;
// Don't try to copy over annotations to named controller
if (isFunction(controller)) controller[key] = val;
}
});
factory.$inject = ['$injector'];
return this.directive(name, factory);
};
Angular 1.5 引入了
.component()
辅助方法, 它的定义比.directive()
更简单。.component()
允许开发者以更接近Angular2的方式写Angular1的代码,方便以后无痛地升级到Angular2。.component()
比.directive()
使用了更加简洁抽象的语法。从
.directive()
到.component()
以下是它们的语法差异:
先用Angular 1.4.x 写一个简单的计数器,下边再用 v1.5.0 重构它。
jsfiddle : https://jsfiddle.net/toddmotto/avdezer7/
方法名改变,并且Function 参数变为 Object
开始自上而下重构这个示例:
.directive
中本质上需要返回一个函数,而.component
只需要传一个对象了scope
和bindToController
变为bindings
Controller
和controllerAs
的变化在定义controller的方式上倒没有什么变化,唯一一点不同就是
controllerAs
多了一个默认值:$ctrl
在1.4中直接定义 controller
或者在别的地方定义,此处引用
又或者用
controllerAs
起别名然后就可以在模板中使用
other.prop
之类来访问Controller实例。在
.component()
中就不会那么麻烦了,在我们没明确指定Controller实例别名时,它会自动用3种方式创建controllerAs
属性,Angular中相关源码如下:其中第一个
identifierForController
会中controller属性为字符串时(controller: 'SomeCtrl as something'
), 提取as
后边的名字,源码如下:第二个
controllerAs
用于当controller属性为function时的情况。第三个 '$ctrl' 默认值让我们可以忽略掉
controllerAs
了说了那么多,终于可以在重构中把
controllerAs
干掉了:用
require
继承单向绑定
用新的表达式语法创建独立作用域:
参见:One-way data-binding in Angular 1.5
Lifecycle hooks
Each component has a well-defined set of lifecycle hooks, read the full article here. 每个组件都预定义了一组 Lifecycle hooks(生命周期钩子):
参见:Comprehensive dive into Angular 1.5 lifecycle hooks
关闭独立作用域
Component 始终都会创建独立作用域,相关源码部分如下:
无状态的components
参见:Stateless Angular components
基本上我们可以只用
template
和bindings
:源码比较
https://github.com/angular/angular.js/blob/v1.5.7/src/ng/compile.js#L1112-L1165
升级到Angular 2
用这种方式写组件很容易地升级到Angular 2。用 ECMAScript 5 和新模板语法写的示例: