ホームページ  >  記事  >  ウェブフロントエンド  >  HTMLを動的にバインドする方法

HTMLを動的にバインドする方法

高洛峰
高洛峰オリジナル
2017-03-08 15:49:531242ブラウズ

Web フロントエンド開発では、特にコンテンツ管理システム (CMS: Content Management System の略称) などで、バックエンドからの HTML 文字列を動的にバインドしたり、ページ DOM 表示に動的スプライシングしたりする必要に遭遇することがよくあります。ニーズはどこにでもあります。

angular の読者はまず ngBindHtml を思い浮かべるでしょう。そうです、angular は HTML を動的にバインドするためのこの命令を提供します。これは、innerHTML を使用して計算された式の結果を DOM にバインドします。しかし、問題はそれほど単純ではありません。 Web セキュリティにおいて、XSS (クロスサイト スクリプティング、スクリプト インジェクション攻撃) は、Web アプリケーションにおける典型的なコンピュータ セキュリティ脆弱性です。 XSS 攻撃とは、実行可能なクライアント側コードを Web ページに挿入し、ブラウザーによって実行されて攻撃の目的を達成することを指し、攻撃が成功すると、ユーザーの機密情報が取得される可能性があります。ユーザー エクスペリエンスを変更し、ユーザーやその他の違法な行為を誘発し、場合によっては XSS 攻撃を、サーバーやデータベースへの SQL インジェクション攻撃、クリック ハイジャック、相対リンク ハイジャックなどの他の攻撃方法と組み合わせてフィッシングを実行することで、被害がもたらされます。巨大で、Web セキュリティの最大の敵でもあります。 Web セキュリティの問題の詳細については、ウィキ https://en.wikipedia.org/wiki/Cross-site_scripting%E3%80%82 を参照してください。 Angular では、デフォルトでは追加された HTML コンテンツを信じません。 HTML コンテンツを追加するには、まず $sce.trustAsHtml を使用して、これが信頼できる HTML コンテンツであることを Angular に伝える必要があります。そうしないと、$sce:unsafe 例外エラーが発生します。

Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.

これは、単純な 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 = &#39;<p>hello <a href="https://angular.io/">angular</a></p>&#39;;
        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: &#39;EA&#39;,
            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 = &#39;<h2>hello : <a ng-href="{{demo.link}}">angular</a></h2>&#39;;

        vm.link = &#39;https://angular.io/&#39;;
        var i = 0;
        vm.change = function() {
            vm.html = &#39;<h3>change after : <a ng-href="{{demo.link}}">&#39; + (++i) + &#39;</a></h3>&#39;;
        };
    }]);

dy-compile と呼ばれるディレクティブがここで作成されます。これは、HTML コンテンツが存在するときに、最初にバインディング属性の HTML 値の変更をリッスンします。 . の場合、最初にサブスコープを作成し、次に $compile サービスを使用して受信 HTML を動的に接続し、現在の DOM ノードを置き換えようとします。ここでサブスコープを作成する理由は、DOM の作成を容易にするためです。スコープを簡単に破棄するには、HTML コンパイルによってもたらされるウォッチャー関数を削除します。最後の親スコープが破棄されると、スコープも破棄されます。

上記のコンパイルと接続により、ngHref 命令が有効になります。ここでは、動的コンパイル Angular モジュールの例を示します。具体的な実装方法については、具体的なディレクティブを宣言する方法を参照してください。

以上がHTMLを動的にバインドする方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。