この記事の例では、AngularJS で HTML を動的にバインドする方法について説明します。参考までに皆さんと共有してください。詳細は次のとおりです:
Web フロントエンド開発では、特にコンテンツにおいて、バックエンドからの HTML 文字列の動的バインドやページの DOM 表示への動的スプライシングの必要性によく遭遇します。管理システム(CMS:Content Management Systemの略)、そのようなニーズはどこにでもあります。
angular の読者はまず ngBindHtml を思い浮かべるでしょう。そうです、angular は HTML を動的にバインドするためのこの命令を提供します。これは、innerHTML を使用して計算された式の結果を DOM にバインドします。しかし、問題はそれほど単純ではありません。 Web セキュリティにおいて、XSS (クロスサイト スクリプティング、スクリプト インジェクション攻撃) は、Web アプリケーションにおける典型的なコンピュータ セキュリティ脆弱性です。 XSS 攻撃とは、実行可能なクライアント コードを Web ページに挿入し、ブラウザで実行して攻撃の目的を達成することを指し、攻撃が成功すると、ユーザーの機密情報が取得される可能性があります。 XSS 攻撃は、ユーザー エクスペリエンスを低下させ、ユーザーやその他の違法な行為を誘発することがあります。XSS 攻撃は、サーバーやデータベースへの SQL インジェクション攻撃、クリック ハイジャック、相対リンク ハイジャックなどの他の攻撃手法と組み合わせてフィッシングを実行する場合もあります。その被害は甚大です。そしてそれは、セキュリティの最大の敵である Web でもあります。 Web セキュリティの問題の詳細については、ウィキ https://en.wikipedia.org/wiki/Cross-site_scripting%E3%80%82 を参照してください。 Angular では、デフォルトでは追加された HTML コンテンツを信頼しません。 HTML コンテンツを追加するには、まず $sce.trustAsHtml を使用して、これが信頼できる HTML コンテンツであることを Angular に伝える必要があります。そうしないと、$sce:unsafe 例外エラーが発生します。
エラー: [$sce:unsafe] 安全なコンテキストで安全でない値を使用しようとしています。
これは、単純な Angular リンクをバインドするデモです:
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 href="https://angular.io/">angular</a></p>'; vm.html = $sce.trustAsHtml(html); return vm; }]);
単純な静的 HTML の場合、この問題は解決されます。ただし、複雑な HTML の場合、ここでの複雑さは、Angular の式と命令を含む HTML テンプレートを指します。これらの場合、大きな DOM 表示をバインドするだけでなく、Angular の強力な双方向バインディング メカニズムを取得することも期待されます。 ngBindHhtml は、双方向バインディングの $scope に関連付けられません。HTML に ngClick、ngHref、ngSHow、ngHide などの angular 命令がある場合、これらのボタンをクリックしても、バインディングの式は何も反応しません。式は更新されません。たとえば、最後のリンクを ng-href="demo.link" に変更しようとすると、リンクは解析されず、元の HTML 文字列が DOM に表示されたままになります。
Angular のすべての命令を有効にするには、コンパイルにプレリンクとポストリンクが含まれており、動作する前に特定の動作に接続される必要があります。ほとんどの場合、コンパイルは angular の起動時に自動的にコンパイルされます。ただし、動的に追加されたテンプレートの場合は、手動でコンパイルする必要があります。 Angular は、この関数を実装するための $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>'; }; }]);
dy-compile というディレクティブがここで作成され、最初にバインドされた属性の HTML 値をリッスンします。変更すると、HTML コンテンツが存在する場合、最初にサブスコープの作成が試行され、次に $compile サービスを使用して受信 HTML に動的に接続し、現在の DOM ノードを置き換えます。ここでサブスコープを作成する理由は、破棄する際の各処理を容易にするためです。初めて DOM を作成する場合は、スコープを簡単に破棄し、HTML コンパイルによってもたらされるウォッチャー関数を削除し、最後の親スコープが破棄されたときにスコープの破棄を試みることができます。
上記のコンパイルと接続により、ngHref 命令が有効になります。ここでは、動的コンパイル Angular モジュールの例を示します。具体的な実装方法については、具体的なディレクティブを宣言する方法を参照してください。
この記事が AngularJS プログラミングに携わるすべての人に役立つことを願っています。
AngularJS の HTML を動的にバインドする方法の詳細な分析については、PHP 中国語 Web サイトに注目してください。