动态绑定HTML

在Web前端开发中,我们经常会遇见需要动态的将一些来自后端或者是动态拼接的HTML字符串绑定到页面DOM显示,特别是在内容管理系统(CMS:是Content Management System的缩写),这样的需求,更是遍地皆是。

对于对angular的读者肯定首先会想到ngBindHtml,对,angular为我们提供了这个指令来动态绑定HTML,它会将计算出来的表达式结果用innerHTML绑定到DOM。但是,问题并不是这么简单。在Web安全中XSS(Cross-site scripting,脚本注入攻击),它是在Web应用程序中很典型的计算机安全漏洞。XSS攻击指的是通过对网页注入可执行客户端代码且成功地被浏览器执行,来达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可能会获取到用户的一些敏感信息、改变用户的体验、诱导用户等非法行为,有时XSS攻击还会合其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,也是web安全的头号大敌。更多的Web安全问题,请参考wikihttps://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 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指令,它们并不会被compile,点击这些按钮,也不会发生任何反应,绑定的表达式也不会在更新。例如尝试将上次的链接变为:ng-href=“demo.link”,链接并不会被解析,在DOM看见的仍然会是原样的HTML字符串。

在angular中的所有指令要生效,都需要经过compile,在compile中包含了pre-link和post-link,连接上特定行为,才能工作。大部分情况下compile,是会在angular启动时,自动compile的。但如果是对于动态添加的模板,则需要手动的compile。angular中为我们提供了$compile服务来实现这一功能。下面是一个比较通用的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内容存在的时候,它会尝试首先创个一个子scope,然后利用$compile服务来动态连接传入的html,并替换掉当前DOM节点;这里创建子scope的原因,是方便在每次销毁DOM的时,也能容易的销毁掉scope,去掉HTML compile带来的watchers函数,并在最后的父scope销毁的时候,也会尝试销毁该scope。

因为有了上边的compile的编译和连接,则ngHref指令就可以生效了。这里只是尝试给出动态compile angular模块的例子,具体的实现方式,请参照你的业务来声明特定的directive。

作者:破  狼 
出处:http://www.cnblogs.com/whitewolf/ 
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。该文章也同时发布在我的独立博客中-个人独立博客博客园--破狼51CTO--破狼。http://www.cnblogs.com/whitewolf/p/angular-dynamic-bind-html-to-dom.html

时间: 2024-12-24 03:56:06

动态绑定HTML的相关文章

java-Java动态绑定,对象已经向上转型了,为何优先使用的方法依然是子类的方法。

问题描述 Java动态绑定,对象已经向上转型了,为何优先使用的方法依然是子类的方法. 情况如下,我写了个测试类. son类 public class son extends father { public son() { fs=""new son""; } public void say() { System.out.println(""son say()""); } father类 public class father {

ajax的异步请求-我用dropdownlist动态绑定数据,用ajax实现数据获取,第一遍遍历之后,不再刷新

问题描述 我用dropdownlist动态绑定数据,用ajax实现数据获取,第一遍遍历之后,不再刷新 我数据放在returndata.aspx的datatable中,第一次执行是可以的,当选择dropdownlist中不同的option会返回不同的信息,但是当遍历完datatable中的所有rows之后,dropdownlist的onchange事件失效了,获取的内容不再更新. 1. Defalut.aspx <script type=""text/javascript"

C++中的继承(inheritance) 和动态绑定(dynamic binding) 简介

继承(inheritance)和动态绑定(dynamic binding) 是面向对象的重要组成部分, 即继承(inheritance)和多态(polymorphism), 可以使 派生类(derived class)拥有 基类(base class) 的接口(interface); 派生类可以覆写(override)基类的虚函数(virtual function), 符合特定的功能; 派生类可以隐式地转换为基类 (derived-to-base conversion), 但不可逆, 因为派生类

C++的静态绑定和动态绑定概述

C++在面向对象编程中,存在着静态绑定和动态绑定的定义,本节即是主要讲述这两点区分. 我是在一个类的继承体系中分析的,因此下面所说的对象一般就是指一个类的实例. 首先我们需要明确几个名词定义: 静态类型:对象在声明时采用的类型,在编译期既已确定: 动态类型:通常是指一个指针或引用目前所指对象的类型,是在运行期决定的: 静态绑定:绑定的是静态类型,所对应的函数或属性依赖于对象的静态类型,发生在编译期: 动态绑定:绑定的是动态类型,所对应的函数或属性依赖于对象的动态类型,发生在运行期: 从上面的定义

动态绑定

在doStuff()的代码里,最让人吃惊的是尽管我们没作出任何特殊指示,采取的操作也是完全正确和恰当的.我们知道,为Circle调用draw()时执行的代码与为一个Square或Line调用draw()时执行的代码是不同的.但在将draw()消息发给一个匿名Shape时,根据Shape句柄当时连接的实际类型,会相应地采取正确的操作.这当然令人惊讶,因为当Java编译器为doStuff()编译代码时,它并不知道自己要操作的准确类型是什么.尽管我们确实可以保证最终会为Shape调用erase(),为

动态绑定事件(java AWT)

新AWT事件模型给我们带来的一个好处就是灵活性.在老的模型中我们被迫为我们的程序动作艰难地编写代码.但新的模型我们可以用单一方法调用增加和删除事件动作.下面的例子证明了这一点:   //: DynamicEvents.java // The new Java 1.1 event model allows you to // change event behavior dynamically. Also // demonstrates multiple actions for an event.

关于动态绑定的理解

在子类和父类里面有同名函数的时候,如果生成一个子类的对象,并在子类的对象里面调用这个函数,那么到底会是调用的是谁的函数呢?例如 class Base{ int i=47; int f(){ return g(); } int g(){ return i; } } class Dervied extends Base{ int i=27; int g(){ file://override父类里面的方法 return i; } } public class test { public static

php动态绑定变量的用法

 本文实例讲述了php动态绑定变量的用法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 private function bindVars($stmt,$params) { if ($params != null) { $types = ''; //initial sting with types foreach($params a

关于innerHTML后丢失动态绑定的EVENT问题

 用innerHTML取出一段内容后再innerHTML回去,那么原来动态绑定的事件就会丢失,如: html: 代码如下: <body><div id='d1'>点击</div></body> script: 代码如下: document.getElementById('d1').onclick=function(){alert(1)}; var html=document.body.innerHTML; document.body.innerHTML=ht

Chrome扩展页面动态绑定JS事件提示错误

 开发Chrome扩展时,页面的popup.html中需要js的时候,直接将JS写在动态绑定JS事件会提示错误,下面有个不错的解决方法,大家可以参考下 问题描述:    当开发Chrome扩展时,页面的popup.html中需要js的时候,直接将JS写在动态绑定JS事件会提示:    Refused to execute inline script because it violates the following Content Security Policy directive: "scri