在web開發中我們經常需要將動態拼接的html字符串綁定到頁面DOM上。
AngularJS中我們可以使用指令ng-bind-html
來綁定動態Html,它會將計算出來的表達式結果用innerHtml
綁定到html。
但是AngularJS默認是不相信添加的html內容的,所以我們需要調用$sce
(Strict Contextual Escaping)服務來解決問題。
$sce is included by default starting with angular 1.2
<!DOCTYPE html>
<html ng-app ="myApp">
<head>
<meta charset="utf-8">
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
<style>
body{
border: 5px solid #FF851B;
padding: 10px;
}
.info{
color:#0074D9;
}
.age{
color:#FF4136;
}
</style>
</head>
<body ng-controller="myCtrl">
<div ng-bind-html="html"></div>
<script>
angular.module('myApp', [])
.controller("myCtrl", ["$scope","$sce",function($scope,$sce) {
$scope.myage = 16;
$scope.myInfo = {
name:"chenjy"
};
var html ="<div>my name:<span class='info'>chenjy</span>,my age:<span class='age'>16</span></div>";
$scope.html = $sce.trustAsHtml(html);
}]);
</script>
</body>
</html>
對於靜態html這就夠了,但是我們如果需要用到AngularJS強大的雙向數據綁定能力
var html ="<div>my name:<span class='info'>{{myInfo.name}}</span>,my age:<span class='age'>{{myage}}</span></div>";
ng-bind-html
並不會和$scope
雙向綁定,並且ng-click
等指令也不會得到compile
- 我們可以借助
$compile
編譯html
<body ng-controller="myCtrl">
<script>
angular.module('myApp', [])
.controller("myCtrl", ["$scope","$compile",function($scope,$compile) {
$scope.myage = 16;
$scope.myInfo = {
name:"chenjy"
};
var template ="<div>my name:<span class='info'>{{myInfo.name}}</span>,my age:<span class='age'>{{myage}}</span></div>";
var ele = $compile(template)($scope);
angular.element(document.body).append(ele);
}]);
</script>
</body>
但是AngularJS中我們最好直接寫在directive
的link
中,此時編譯階段已經結束我們可以手動編譯html。
.directive("myDir", ["$compile",function($compile) {
return {
restrict: "E",
link: function(scope, iElement, iAttrs) {
var template = "<div>my name:<span class='info'>{{myInfo.name}}</span>,my age:<span class='age'>{{myage}}</span></div><input type='text' ng-model='myage' />";
var ele = $compile(template)(scope);
iElement.append(ele);
}
};
}]);
下面貼一個網上看到的比較通用的compile
例子
<!DOCTYPE html>
<html ng-app ="myApp">
<head>
<meta charset="utf-8">
<script src="http://cdn.static.runoob.com/libs/angular.js/1.4.6/angular.min.js"></script>
<style>
body{
border: 5px solid #FF851B;
padding: 10px;
}
.info{
color:#0074D9;
}
.age{
color:#FF4136;
}
</style>
</head>
<body ng-controller="myCtrl">
<html-compile html='{{html}}'></html-compile>
<script>
angular.module('myApp', [])
.controller("myCtrl", ["$scope","$sce",function($scope,$sce) {
$scope.myage = 16;
$scope.myInfo = {
name:"chenjy"
};
$scope.changeAge = function(){
$scope.myage ++;
};
$scope.html ="<button ng-click='changeAge()'>change</button><div>my name:<span class='info'>{{myInfo.name}}</span>,my age:<span class='age'>{{myage}}</span></div>";
}]).directive("htmlCompile", ["$compile", function($compile) {
return {
replace: true,
restrict: 'EA',
link: function(scope, elm, iAttrs) {
var DUMMY_SCOPE = {
$destroy: angular.noop
},
root = elm,
childScope,
destroyChildScope = function() {
(childScope || DUMMY_SCOPE).$destroy();
};
// 監聽html值
iAttrs.$observe("html", function(html) {
/**
* 當傳入html的時候 先嘗試銷毀子scope,然后創建一個子scope,compile當前html,替換掉當前DOM
**/
if (html) {
destroyChildScope();
childScope = scope.$new(false);
var content = $compile(html)(childScope);
root.replaceWith(content);
root = content;
}
// 在父scope銷毀的時候,銷毀該子scope
scope.$on("$destroy", destroyChildScope);
});
}
};
}]);
</script>
</body>
</html>