AngularJS動態(tài)綁定HTML的方法分析
本文實例講述了AngularJS動態(tài)綁定HTML的方法。分享給大家供大家參考,具體如下:
在Web前端開發(fā)中,我們經常會遇見需要動態(tài)的將一些來自后端或者是動態(tài)拼接的HTML字符串綁定到頁面DOM顯示,特別是在內容管理系統(tǒng)(CMS:是Content Management System的縮寫),這樣的需求,更是遍地皆是。
對于對angular的讀者肯定首先會想到ngBindHtml,對,angular為我們提供了這個指令來動態(tài)綁定HTML,它會將計算出來的表達式結果用innerHTML綁定到DOM。但是,問題并不是這么簡單。在Web安全中XSS(Cross-site scripting,腳本注入攻擊),它是在Web應用程序中很典型的計算機安全漏洞。XSS攻擊指的是通過對網(wǎng)頁注入可執(zhí)行客戶端代碼且成功地被瀏覽器執(zhí)行,來達到攻擊的目的,形成了一次有效XSS攻擊,一旦攻擊成功,它可能會獲取到用戶的一些敏感信息、改變用戶的體驗、誘導用戶等非法行為,有時XSS攻擊還會合其他攻擊方式同時實施比如SQL注入攻擊服務器和數(shù)據(jù)庫、Click劫持、相對鏈接劫持等實施釣魚,它帶來的危害是巨大的,也是web安全的頭號大敵。更多的Web安全問題,請參考wiki https://en.wikipedia.org/wiki/Cross-site_scripting%E3%80%82
在angular中默認是不相信添加的HTML內容,對于添加的HTML內容,首先必須利用$sce.trustAsHtml,告訴angular這是可信的HTML內容。否則你將會得到$sce:unsafe的異常錯誤。
Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.
下面是一個綁定簡單的angular鏈接的demo:
HTML:
<div ng-controller="DemoCtrl as demo"> <div ng-bind-html="demo.html"></div> </div>
JavaScript:
angular.module("com.ngbook.demo", []) .controller("DemoCtrl", ["$sce", function($sce) { var vm = this; var html = '<p>hello <a ; vm.html = $sce.trustAsHtml(html); return vm; }]);
對于簡單的靜態(tài)HTML,這個問題就解決了。但對于復雜的HTML,這里的復雜是指帶有angular表達式、指令的HTML模板,對于它們來說,我們不僅希望綁定大DOM顯示,同時還希望得到angular強大的雙向綁定機制。ngBindHhtml并不會和$scope關聯(lián)雙向綁定,如果在HTML中存在ngClick、ngHref、ngSHow、ngHide等angular指令,它們并不會被compile,點擊這些按鈕,也不會發(fā)生任何反應,綁定的表達式也不會在更新。例如嘗試將上次的鏈接變?yōu)椋簄g-href=“demo.link”,鏈接并不會被解析,在DOM看見的仍然會是原樣的HTML字符串。
在angular中的所有指令要生效,都需要經過compile,在compile中包含了pre-link和post-link,連接上特定行為,才能工作。大部分情況下compile,是會在angular啟動時,自動compile的。但如果是對于動態(tài)添加的模板,則需要手動的compile。angular中為我們提供了$compile服務來實現(xiàn)這一功能。下面是一個比較通用的compile例子:
HTML:
<body ng-controller="DemoCtrl as demo"> <dy-compile html="{{demo.html}}"> </dy-compile> <button ng-click="demo.change();">change</button> </body>
JavaScript:
angular.module("com.ngbook.demo", []) .directive("dyCompile", ["$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(); }; iAttrs.$observe("html", function(html) { if (html) { destroyChildScope(); childScope = scope.$new(false); var content = $compile(html)(childScope); root.replaceWith(content); root = content; } scope.$on("$destroy", destroyChildScope); }); } }; }]) .controller("DemoCtrl", [function() { var vm = this; vm.html = '<h2>hello : <a ng-href="{{demo.link}}">angular</a></h2>'; vm.link = 'https://angular.io/'; var i = 0; vm.change = function() { vm.html = '<h3>change after : <a ng-href="{{demo.link}}">' + (++i) + '</a></h3>'; }; }]);
這里創(chuàng)建了一個叫dy-compile的指令,它首先會監(jiān)聽綁定屬性html值的變化,當html內容存在的時候,它會嘗試首先創(chuàng)個一個子scope,然后利用$compile服務來動態(tài)連接傳入的html,并替換掉當前DOM節(jié)點;這里創(chuàng)建子scope的原因,是方便在每次銷毀DOM的時,也能容易的銷毀掉scope,去掉HTML compile帶來的watchers函數(shù),并在最后的父scope銷毀的時候,也會嘗試銷毀該scope。
因為有了上邊的compile的編譯和連接,則ngHref指令就可以生效了。這里只是嘗試給出動態(tài)compile angular模塊的例子,具體的實現(xiàn)方式,請參照你的業(yè)務來聲明特定的directive。
希望本文所述對大家AngularJS程序設計有所幫助。
相關文章
Angular 多級路由實現(xiàn)登錄頁面跳轉(小白教程)
這篇文章主要介紹了Angular 多級路由實現(xiàn)登錄頁面跳轉(小白教程),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11AngularJS中的$parse服務與$eval服務用法實例
這篇文章主要介紹了AngularJS中的$parse服務與$eval服務用法,結合實例形式分析了AngularJS中$parse服務與$eval服務的功能、使用方法與相關注意事項,需要的朋友可以參考下2023-05-05