概述
Angular JS為很多屬性實(shí)現(xiàn)了對(duì)應(yīng)的directive。通過[ng-]開頭的屬性實(shí)現(xiàn)對(duì)應(yīng)的屬性與scope數(shù)據(jù)進(jìn)行綁定支鸡。如:ng-disabled='enabled'就會(huì)把scope.enabled與元素的disabled屬性進(jìn)行綁定。改變scope.enabled的值昏翰,元素的disabled屬性的值也會(huì)變化苍匆。
支持的屬性
第一類總共有12個(gè)屬性刘急,如下:
屬性 | ng屬性 |
---|---|
selected | ng-selected |
checked | ng-checked |
disabled | ng-disabled |
readOnly | ng-readonly |
required | ng-required |
open | ng-open |
minlength | ng-minlength |
maxlength | ng-maxlength |
min | ng-min |
max | ng-max |
pattern | ng-pattern |
step | ng-step |
在這一類中棚菊,directive會(huì)去利用$scope的watcher方法監(jiān)控?cái)?shù)據(jù)模型,如果有變動(dòng)叔汁,就會(huì)設(shè)置屬性值统求。需要注意的是ng-checked和ng-module綁定了相同的值,ng-checked將會(huì)失效据块。
第二類總共有3個(gè)码邻,如下:
屬性 | ng屬性 |
---|---|
src | ng-src |
srcset | ng-srcset |
href/xlink:href | ng-href |
在這一類中,directive會(huì)利用attr的$observe方法監(jiān)控ng屬性值的變化另假,然后再去設(shè)置屬性值像屋,同時(shí)還會(huì)把值寫入元素的property中去。需要注意的是ng-href實(shí)現(xiàn)了普通元素和SVG元素的統(tǒng)一處理边篮。
實(shí)現(xiàn)細(xì)節(jié)
第一類ng屬性有兩種實(shí)現(xiàn)方式己莺,其實(shí)現(xiàn)本質(zhì)上是一樣的奏甫,關(guān)鍵代碼:
forEach(BOOLEAN_ATTR, function(propName, attrName) {
// binding to multiple is not supported
if (propName === 'multiple')
return;
function defaultLinkFn(scope, element, attr) {
cope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) {
attr.$set(attrName, !!value);
});
}
var normalized = directiveNormalize('ng-' + attrName);
var linkFn = defaultLinkFn;
if (propName === 'checked') {
linkFn = function(scope, element, attr) {
// ensuring ngChecked doesn't interfere with ngModel when both are set on the same input
if (attr.ngModel !== attr[normalized]) {
defaultLinkFn(scope, element, attr);
}
};
}
ngAttributeAliasDirectives[normalized] = function() {
return {
restrict: 'A',
priority: 100,
link: linkFn
};
};
});
// aliased input attrs are evaluatedforEach(ALIASED_ATTR, function(htmlAttr, ngAttr) {
ngAttributeAliasDirectives[ngAttr] = function() {
return {
priority: 100,
link: function(scope, element, attr) {
//special case ngPattern when a literal regular expression value
//is used as the expression (this way we don't have to watch anything).
if (ngAttr === 'ngPattern' && attr.ngPattern.charAt(0) === '/') {
var match = attr.ngPattern.match(REGEX_STRING_REGEXP);
if (match) {
attr.$set('ngPattern', new RegExp(match[1], match[2]));
return;
}
}
scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
attr.$set(ngAttr, value);
});
}
};
};
});
其中最為關(guān)鍵的是directive中的link函數(shù)里的內(nèi)容:
scope.$watch(attr[ngAttr], function ngAttrAliasWatchAction(value) {
attr.$set(ngAttr, value);
});
在這里實(shí)現(xiàn)了對(duì)數(shù)據(jù)的監(jiān)控,以及變化時(shí)的處理凌受。
第二類在實(shí)現(xiàn)的時(shí)候和第一種大同小異阵子,有區(qū)別的也是directive的link函數(shù):
link: function(scope, element, attr) {
var propName = attrName,
name = attrName;
if (attrName === 'href' && toString.call(element.prop('href')) === '[object SVGAnimatedString]') {
name = 'xlinkHref';
attr.$attr[name] = 'xlink:href';
propName = null;
}
attr.$observe(normalized, function(value) {
if (!value) {
if (attrName === 'href') {
attr.$set(name, null);
}
return;
}
attr.$set(name, value);
// on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist
// then calling element.setAttribute('src', 'foo') doesn't do anything, so we need
// to set the property as well to achieve the desired effect.
// we use attr[attrName] value since $set can sanitize the url.
if (msie && propName) element.prop(propName, attr[name]);
});
這里面實(shí)現(xiàn)的功能稍微多一點(diǎn)點(diǎn),首先會(huì)針對(duì)href屬性進(jìn)行SVG的兼容胜蛉,然后通過attr的$observe方法監(jiān)控屬性值的變化挠进。在屬性值發(fā)生變化時(shí)首先會(huì)設(shè)置到attr中去,然后會(huì)根據(jù)需要設(shè)置到element的property中去誊册。
使用樣例
<!DOCTYPE html><html lang="en" ng-app="app">
<!--<html>-->
<head>
<title>Test</title>
</head>
<body ng-controller="testCtrl">
<div>
<input ng-readonly="enable" ng-model="data">
<input type="button" value="click" ng-click="enable=!enable">
</div>
<div>
<a ng-href="{{data}}">link</a>
</div>
</body>
<script src="./node_modules/angular/angular.js" type="text/javascript"></script>
<script>
angular.module("app",[]).controller("testCtrl",["$scope",function($scope){
$scope.enable = false;
$scope.data = "";
}]);
</script>
</html>
在這個(gè)樣例中實(shí)現(xiàn)了點(diǎn)擊按鈕禁用或啟用輸入框领突,在輸入框中輸入數(shù)據(jù)會(huì)改變a標(biāo)簽的href屬性值。
從中可以看到解虱,對(duì)于第一類ng屬性可以直接寫數(shù)據(jù)名稱攘须,而對(duì)于第二類ng屬性則需要使用雙花括號(hào)括起來。