AngularJS动态绑定HTML的方法分析


Posted in Javascript onNovember 07, 2016

本文实例讲述了AngularJS动态绑定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安全问题,请参考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 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。

希望本文所述对大家AngularJS程序设计有所帮助。

Javascript 相关文章推荐
仅用[]()+!等符号就足以实现几乎任意Javascript代码
Mar 01 Javascript
javascript实现的一个带下拉框功能的文本框
May 08 Javascript
JavaScript中指定函数名称的相关方法
Jun 04 Javascript
理解Javascript文件动态加载
Jan 29 Javascript
javascript html5移动端轻松实现文件上传
Mar 27 Javascript
vue.js实现仿原生ios时间选择组件实例代码
Dec 21 Javascript
Vuejs入门教程之Vue生命周期,数据,手动挂载,指令,过滤器
Apr 19 Javascript
AngularJS实现的生成随机数与猜数字大小功能示例
Dec 25 Javascript
vue实现模态框的通用写法推荐
Feb 26 Javascript
element ui 对话框el-dialog关闭事件详解
Feb 26 Javascript
vue打包使用Nginx代理解决跨域问题
Aug 27 Javascript
vue实现表单未编辑或未保存离开弹窗提示功能
Apr 08 Javascript
基于JS分页控件实现简单美观仿淘宝分页按钮效果
Nov 07 #Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 #Javascript
jquery文字填写自动高度的实现方法
Nov 07 #Javascript
JS 全屏和退出全屏详解及实例代码
Nov 07 #Javascript
easyui tree带checkbox实现单选的简单实例
Nov 07 #Javascript
vue.js初学入门教程(2)
Nov 07 #Javascript
AngularJS递归指令实现Tree View效果示例
Nov 07 #Javascript
You might like
php实现微信公众平台账号自定义菜单类
2015/10/11 PHP
PHP使用socket发送HTTP请求的方法
2016/02/14 PHP
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
js中parseInt函数浅谈
2013/07/31 Javascript
可选择和输入的下拉列表框示例
2013/11/05 Javascript
js字符串截取函数substr substring slice使用对比
2013/11/27 Javascript
JS小功能(操作Table--动态添加删除表格及数据)实现代码
2013/11/28 Javascript
javascript中parseInt()函数的定义和用法分析
2014/12/20 Javascript
jQuery 常用代码集锦(必看篇)
2016/05/16 Javascript
原生JS实现首页进度加载动画
2016/09/14 Javascript
BACKBONE.JS 简单入门范例
2017/10/17 Javascript
JavaScript封装的常用工具类库bee.js用法详解【经典类库】
2018/09/03 Javascript
vue如何解决循环引用组件报错的问题
2018/09/22 Javascript
Vue+webpack项目配置便于维护的目录结构教程详解
2018/10/14 Javascript
JavaScript数据结构与算法之二叉树实现查找最小值、最大值、给定值算法示例
2019/03/01 Javascript
vue中实现弹出层动画效果的示例代码
2020/09/25 Javascript
flask框架中勾子函数的使用详解
2018/08/01 Python
python调试神器PySnooper的使用
2019/07/03 Python
Python 旋转打印各种矩形的方法
2019/07/09 Python
twilio python自动拨打电话,播放自定义mp3音频的方法
2019/08/08 Python
Python facenet进行人脸识别测试过程解析
2019/08/16 Python
python实现回旋矩阵方式(旋转矩阵)
2019/12/04 Python
更新升级python和pip版本后不生效的问题解决
2020/04/17 Python
Python如何实现线程间通信
2020/07/30 Python
Python3基于plotly模块保存图片表格
2020/08/03 Python
python 制作本地应用搜索工具
2021/02/27 Python
html5 datalist 选中option选项后的触发事件
2020/03/05 HTML / CSS
英国领先的名牌服装折扣零售商:Brown Bag Clothing
2019/01/08 全球购物
初二生物教学反思
2014/02/03 职场文书
个性发展自我评价
2014/02/11 职场文书
学校实习推荐信
2015/03/27 职场文书
家长会感言
2015/08/01 职场文书
2016元旦文艺汇演主持词(开场白+结束语)
2015/12/03 职场文书
使用GO语言实现Mysql数据库CURD的简单示例
2021/08/07 Golang
Windows 11要来了?微软文档揭示Win11太阳谷 / Win10有两个不同版本
2021/11/21 数码科技
Python Pandas读取Excel日期数据的异常处理方法
2022/02/28 Python