5

我们以下使用的angular的版本是1.3.x,完整的代码在文章的最后面,在线的例子demo
注意,我下面给出的代码示例只是截取了一部分,完整的部分在文章的最后面

1.首先我们最常使用的一个绑定表达式的指令是ngBind,比如在一个div标签中我们可以这样使用:

    <div ng-bind="vm.info"></div>

这样就把控制器中的vm.info的值绑定到这个div标签里面了,使用这个指令还有一个好处就是在页面还没有完全渲染好的情况下,是不会出现Angular的{{}}解析符号的,它隐藏了Angular解析表达式的过程。如果你使用了下面的方法,

    <div>{{vm.info}}</div>

在网速不是很好的情况下,就会出现{{}}解析符号,给用户带来不好的体验。

2.下一个绑定表达式的指令就是ngBindTemplate了,这个指令与上一个指令的最大不同之处是:ngBindTemplate可以绑定多个表达式,这样就有一个好处,在一些元素中,比如titleoption是不可以包含sapn元素的,这时候如果需要多个变量的话,ngBindTemplate就是很必须的。

    <div ng-bind-template="{{vm.info}} {{vm.msg}}"></div>

还要注意一点就是,这个指令的用法,多个模型变量是用{{}}括起来的。

3.接下来的一些是关于模板的绑定,第一个比较常用的是ngBindHtml,从指令的名字就可以看出来,这个指令是绑定一段html的,那么这个指令该如何使用呢?我们来研究一下,首先,我们需要在控制器定义一段html代码,如下所示:

    vm.html = '<div class="container">\
            <div class="title">{{vm.info}}</div>\
            <div class="content">content</div>\
            </div>';

然后我们就会很自然地想到按照下面的方法去使用这个指令:

    <div ng-bind-html="vm.html"></div>

但是当你在浏览器上运行的时候,却发现浏览器给你报了一个错误,如下所示:

图片描述

说你在一个安全的上下文中使用了不安全的值,怎么解决这个问题呢?我们可以手动的将我们定义的那段html代码,变成Angular信任的值,具体的方法是在控制器定义一个方法如下所示:

    function trust_my_html(str){
            return $sce.trustAsHtml(str);
        }

然后在html中可以这样使用:

    <div ng-bind-html="vm.trust_my_html(vm.html)"></div>

4.上面的方法在一定程度上解决了模板的绑定问题,但是,还有一个小问题,就是模板中的表达式并没有被解析,你可以看看我写的那个demo,所以要想解决这个问题,就是有两个办法,首先就是你自己写一个指令,当绑定模板的时候,将模板中的表达式也给解析了,第二个办法就是使用别人的插件,我看到一个比较好的插件,名字叫做angular-bind-html-compile,我们在我们的主模块中注入这个依赖就可以使用这个指令了,使用方法如下:

    <div bind-html-compile="vm.html"></div>

这样一来,我们模块中的表达式也可以被解析了。还有需要注意,使用这个指令就不需要我们手动的将那段html片段变成Angular信任的值了。

5.当我们仔细看了看上面所说的那个指令,发现也不是那么的难,还不如我们自己写一个呢,不然还要引入他的文件,太费事了,具体的代码如下:

    function compileBindHtml($compile){
        var directive = {
            restrict: 'AE',
            link:linkFunc
        };
        return directive;

        function linkFunc(scope, elements, attrs){
            var func = function(){
                return scope.$eval(attrs.compileBindHtml);
            };
            scope.$watch(func, function(newValue){
                elements.html(newValue);
                $compile(elements.contents())(scope);
            })
        }
    }

我们来看看这个指令,在链接函数中,我们使用$watch监测func函数的返回值,func函数的返回值是一个被$eval的属性值,也就是我们的模板值,然后当检测到有变化的时候,就将我们的模板值放置到含有这个指令的html标签中,然后在使用$compile服务将我们的模板给编译了。看看其实也不是那么难的。

6.最后一个可以用来绑定模板的指令是ngInclude,这个指令使用的频率相对来说比较高一点,那么这个指令怎么使用呢?我们一起来研究一下。

  • 方法一,将模板写在html文件中,这个过程要通过使用script指令来实现,如下所示的一个例子:

    <script type="text/ng-template" id="template-1">
        <div class="container">
            <div class="title">{{vm.info}}</div>
            <div class="content">content</div>
        </div>
    </script>

这里来讲解一下怎么使用这个script指令,首先它的type属性值必须是ng-template,然后id值是它的一个标记或者索引,当你需要在html中使用它的时候就要使用这个id的值来引用这段模板。

  • 方法二,将模板写在js文件中,通过使用$templateCache服务,来写我们的模板,具体的用法如下:

    function configFuc($templateCache){
        var template = '<div class="container">\
            <div class="title">{{vm.info}}</div>\
            <div class="content">content</div>\
            </div>';
        $templateCache.put('template-2', template);
    }

我们的模板的索引是template-2,具体的内容就是template变量里面的内容。

html里面使用的方法如下所示:

    <div ng-include="'template-1'"></div>
    <div ng-include="'template-2'"></div>

使用ngInclude的另一个好处就是模板里面的表达式是会被解析的。

完整的代码:

  • index.html

    <body ng-controller="MyController as vm">

    <script type="text/ng-template" id="template-1">
        <div class="container">
            <div class="title">{{vm.info}}</div>
            <div class="content">content</div>
        </div>
    </script>


    <h1 class="title">ngInclude <span>VS</span> ngBindHtml <span>VS</span> ngBind <span>VS</span> ngBindTemplate</h1>
    <hr/>
    <h3>ngBind</h3>
    <div ng-bind="vm.info"></div>
    <hr/>
    <h3>ngBindTemplate</h3>
    <div ng-bind-template="{{vm.info}} {{vm.msg}}"></div>
    <hr/>

    <h3>ngBindHtml</h3>
    <!-- 这里需要加上这个trust函数 不然会被当做不安全的html 然后会报错-->
    <div ng-bind-html="vm.trust_my_html(vm.html)"></div>

    <!-- 下面的不需要在外层加上那个trust函数 ,不然会报错-->
    <div compile-bind-html="vm.html"></div>

    <!--可以使用别人写好的一个插件-->
    <!--https://github.com/incuna/angular-bind-html-compile-->
    <div bind-html-compile="vm.html"></div>

    <hr/>
    <h3>ngInclude</h3>
    <!-- 加载的模板第一种方法是通过`$templateCache`服务 -->
    <div ng-include="'template-1'"></div>

    <!-- 加载模板的第二种方法是通过`script`指令 -->
    <div ng-include="'template-2'"></div>


</body>
  • index.js

    (function(){
    angular.module('MyApp', ['angular-bind-html-compile'])
        .run(configFuc)
        .controller('MyController', MyController)
        .directive('compileBindHtml', compileBindHtml);

    configFuc.$inject = ['$templateCache'];
    MyController.$inject = ['$sce'];
    compileBindHtml.$inject = ['$compile'];

    function configFuc($templateCache){
        var template = '<div class="container">\
            <div class="title">{{vm.info}}</div>\
            <div class="content">content</div>\
            </div>';
        $templateCache.put('template-2', template);
    }

    function MyController($sce){
        var vm = this;
        vm.info = 'Hello,World';
        vm.msg = 'Thank You!';
        vm.html = '<div class="container">\
            <div class="title">{{vm.info}}</div>\
            <div class="content">content</div>\
            </div>';
        vm.trust_my_html = trust_my_html;
        vm.get_trust_html = get_trust_html;

        function trust_my_html(str){
            return $sce.trustAsHtml(str);
        }

        function get_trust_html(str){
            return $sce.getTrustedHtml(str);
        }

    }

    function compileBindHtml($compile){
        var directive = {
            restrict: 'AE',
            link:linkFunc
        };
        return directive;

        function linkFunc(scope, elements, attrs){
            var func = function(){
                return scope.$eval(attrs.compileBindHtml);
            };
            scope.$watch(func, function(newValue){
                elements.html(newValue);
                $compile(elements.contents())(scope);
            })
        }
    }
})();
  • style.css

    h1.title{
    text-align: center;
}
h1.title span{
    color: #CCC;
}

.container{
    width: 100%;
    height: 60px;
}
.container .title{
    height: 20px;
    background-color: #b3d4fc;
    font-size: 20px;
    line-height: 20px;
    text-align: center;
}
.container .content{
    height: 40px;
    background-color: #0000FF;
    font-size: 15px;
    line-height: 40px;
    text-align: center;
}

h3{
    text-align: center;
    color: #FF0000;
}
div{
    text-align: center;
}

参考的资料:How to make ng-bind-html compile angularjs code


dreamapplehappy
6.6k 声望5.9k 粉丝

引用和评论

0 条评论