Angular模板與表達式的綁定

咱們如下使用的angular的版本是1.3.x,完整的代碼在文章的最後面,在線的例子demo
注意,我下面給出的代碼示例只是截取了一部分,完整的部分在文章的最後面css

1.首先咱們最常使用的一個綁定表達式的指令是ngBind,好比在一個div標籤中咱們能夠這樣使用:html

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

這樣就把控制器中的vm.info的值綁定到這個div標籤裏面了,使用這個指令還有一個好處就是在頁面尚未徹底渲染好的狀況下,是不會出現Angular的{{}}解析符號的,它隱藏了Angular解析表達式的過程。若是你使用了下面的方法,git

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

在網速不是很好的狀況下,就會出現{{}}解析符號,給用戶帶來很差的體驗。angularjs

2.下一個綁定表達式的指令就是ngBindTemplate了,這個指令與上一個指令的最大不一樣之處是:ngBindTemplate能夠綁定多個表達式,這樣就有一個好處,在一些元素中,好比titleoption是不能夠包含sapn元素的,這時候若是須要多個變量的話,ngBindTemplate就是很必須的。github

<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>';

而後咱們就會很天然地想到按照下面的方法去使用這個指令:app

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

可是當你在瀏覽器上運行的時候,卻發現瀏覽器給你報了一個錯誤,以下所示:函數

圖片描述

說你在一個安全的上下文中使用了不安全的值,怎麼解決這個問題呢?咱們能夠手動的將咱們定義的那段html代碼,變成Angular信任的值,具體的方法是在控制器定義一個方法以下所示:this

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

相關文章
相關標籤/搜索