国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Angular directive 實例詳解

Jiavan / 2718人閱讀

摘要:方法三使用調用父作用域中的函數實例地址同樣采用了缺省寫法,運行之后,彈出窗口布爾值或者字符,默認值為這個配置選項可以讓我們提取包含在指令那個元素里面的內容,再將它放置在指令模板的特定位置。

準備代碼,會在實例中用到

var app = angular.module("app", []);

angular指令定義大致如下

app.directive("directiveName", function() {
  return {
    // config
  }
})

其中return返回的配置對象包含很多參數,如下一一說明。

1. restrict

值為字符串,可選參數,指明指令在DOM中以什么形式被聲明





默認值為restrict: "EA",表示可以在DOM里面可以用元素形式和屬性形式被聲明。一般來說,如果你想創建一個自己模板的組件時,則使用元素形式,但是僅僅是為已有元素添加功能的話,就使用屬性名。

如果想要支持IE8,則最好使用屬性和類形式來定義,另外從angular 1.3.X開始,已經放棄支持IE8了。

2. priority

數字,可選參數,致命指令的優先級,若在單個DOM元素上有多個指令,則優先級高的先執行。

當然,設置指令的優先級不太常用,但是比較特殊的例子是,內置指令ng-repeat的優先級為1000,而ng-init的優先級為 450。

3. terminal

布爾型,可選參數,可以被設置為true或者false,若設置為true,則優先級低于此指令的其他指令則無效,不會被調用優先級相同任然會執行。

4. template

字符串或者函數,可選參數。

可以是一段html文本

app.directive("hello", function() {
  return {
    template: "

Hello, world!

" } })

使用如下

渲染結果為


  

Hello, world!

也可以是一個函數,可接受兩個參數Element與Attrs

其中Element是指使用此指令的元素,而Attrs則是實例的屬性,它是由一個元素上所有屬性組成的集合,形如

{
  title: "test",
  id: "testDiv",
  class: "demo",
  input: "text",
  ...
}

下面讓我們看看template是一個函數時的情況

app.directive("hello", function() {
  return {
    template: function(element, attrs) {
      return "
"+ attrs.title +"
" } }; });

html代碼

渲染結果


  
message

實例地址

5. replace

布爾型,默認值為false,設置為true的時候,表示可以用模板內容替換自定義的元素標簽。

在template的例子中,我們發現渲染結果中包含有自定義的元素,很顯然,這并不是我們想要的渲染結果,因此將replace設置為true之后,hello標簽將會消失

app.directive("hello", function() {
  return {
    replace: true,
    template: function(element, attrs) {
      return "
"+ attrs.title +"
" } }; });

渲染結果如下,hello標簽消失不見

message
6. templateUrl

字符串或者函數,可選參數

可以使一個代表html文件路徑的字符串,也可以是一個函數,大致意思與template一樣。

在本地開發時,需要運行一個服務器,不然使用templateUrl會報錯

Cross origin request script(cors)

由于加載html模板是通過異步加載,若加載大量的模板會拖慢網站的速度,這里有一個技巧,就是先緩存模板,你可以先在你的index頁面加載好,將下列代碼作為你頁面的一部分包含在內

這里的id屬性就是被設置在templateUrl上用的

另外一種方法緩存如下

app.run(function($templateCache) {
  $templateCache.put("template.html", "
template
"); })
7. scope

布爾值或者對象,可選參數,默認值為false,表示繼承父級作用域。

如果值為true,表示繼承父作用域,并創建自己的作用域(子作用域)

如果為對象,{},則表示創建一個全新的隔離作用域。

首先我們需要來了解一下scope的繼承機制。我們使用ng-controller這個指令來舉例。我們都知道ng-controller可以從父作用域中繼承并創建一個新的子作用域。如下:

parentNode: {{aaa}}
childrenNode: {{aaa}}
angular.module("app", [])
.controller("demoController", function($scope) {
    $scope.aaa = "children";
})

實例地址

這時頁面的顯示結果為

parentNode: parent
childrenNode: children

當時當我們并沒有在demoController的作用域中給aaa賦值,也就是在上例中刪除這一句$scope.aaa = "children";,那么執行結果就為

parentNode: parent
childrenNode: parent

注意:如果一個元素上有多個指令都使用了隔離作用域,那么只有其中一個可以生效,只有指令模板中的根元素才能獲得一個新的作用域,這時候,scope就被設置為true了。

parentNode: {{aaa}}
childrenNode: {{aaa}}
lastNode: {{aaa}}
angular.module("app", [])
.controller("demoController01", function($scope) {
    $scope.aaa = "children";
})
.controller("demoController02", function($scope) {
    $scope.aaa = "last"
})

實例地址

接下來,我們通過一個簡單明了的例子來說明scope取值的不同差別

parent: {{ name }}
angular.module("app", [])
.controller("mainController", function($scope) {
    $scope.name = "Jake";
})
.directive("myDirective", function() {
    return {
        restrict: "EA",
        scope: false,
        replace: true,
        template: "" +
            "
" + "childNode: {{ name }} " + "
" + "" + "
" } })

實例地址

點擊上面的實例地址,我們可以依次改變scope的值為false, true, {},結果發現

false:兒子繼承父親的值,改變父親的值,兒子的值也隨著改變,反之亦然,這就是繼承且不隔離

true:兒子繼承父親的值,改變父親的值,兒子的值也隨著改變,但是改變兒子的值,父親的值并沒有改變,這就是繼承但是隔離

{}:沒有繼承父親的值,所以兒子的值為空,改變任何一方的值都不會影響另一方,這就是不繼承且隔離

當想要創建一個可重用的組件時,隔離作用域是一個很好的選擇,通過隔離作用域,我們可以確保指令是獨立的,并且可以輕松的插入到任何HTML APP中,并且這種做法防止了父作用域被污染。

隔離作用域可以通過綁定策略來訪問父作用域的屬性

我們來看一個例子

angular.module("app", [])
.controller("mainController", function($scope) {
})
.directive("helloWorld", function() {
    return {
        restrict: "EA",
        scope: false,
        replace: true,
        template: "

Hello world!

" } })

運行上面的代碼,我們在input中輸入顏色值,比如red,那么hello world一行的背景就會變成紅色。動手試試!

實例地址

但是,當我們將scope的值設置為{}時,再次運行代碼就發現頁面并不能成功的完整顯示了.這是因為{}讓helloWorld指令產生了隔離作用域,沒辦法從父級作用域中繼承到color的值了。

所以在template中的{{color}}變成了依賴于自己的作用域,而不是依賴于父級作用域。因此我們需要一些辦法來讓隔離作用域能夠讀取父級作用域的屬性,這個方法就是綁定策略。

下面我們來探索設置這種綁定策略的幾種方法

方法一 使用@來進行單向文本(字符串)綁定
angular.module("app", [])
.controller("mainController", function($scope) {
})
.directive("helloWorld", function() {
    return {
        restrict: "EA",
        scope: {
            color: "@colorAttr"
        },
        replace: true,
        template: "

Hello world!

" } })

實例地址

這種辦法只能單向,通過在運行的指令DOM上設置color-attr屬性,并且采用{{}}綁定某個模型值。當然,我們也可以直接在這里綁定字符串的顏色值,如color-attr="red"

因此當表達式的值發生變化時,屬性color-attr的值也會發生變化,通過單向綁定該值,就可以改變隔離作用域中的屬性color.

如果綁定的隔離作用域屬性名與元素的屬性名相同,則可以采用缺省寫法

// html


// js
app.directive("helloWorld", function() {
   return {
       scope: { color: "@" },
       ...
   }
})
方法二、使用"="進行雙向綁定

{{ color }}
angular.module("app", [])
.controller("mainController", function($scope) {
    $scope.color = "red";
})
.directive("helloWorld", function() {
    return {
        restrict: "EA",
        scope: {
            color: "="
        },
        replace: true,
        template: "

" + "Hello world!" + "

" + "
" } })

實例地址

此處也采用了類似的缺省寫法。

這里需要注意的是,我們要直接在指令元素設置屬性時,是直接將實際的作用域模型復制給該屬性

這樣一個雙向綁定被建立了,改變任何一個input值都會改變另外一個值。

方法三、使用"&"調用父作用域中的函數

{{ name }}
angular.module("app", [])
.controller("mainController", function($scope) {
    $scope.name = "yangbo";
    $scope.say = function() {
        alert("hello!");
    }
})
.directive("helloWorld", function() {
    return {
        restrict: "EA",
        scope: {
            name: "@",
            say: "&"
        },
        replace: true,
        template: ""
    }
})

實例地址

同樣采用了缺省寫法,運行之后,彈出窗口!

8. transclude

布爾值或者字符element,默認值為false

這個配置選項可以讓我們提取包含在指令那個元素里面的內容,再將它放置在指令模板的特定位置。當我們開啟transclude之后,我們就可以使用ng-transclude來指明應該在什么地方放置transclude的內容

china

{{name}}
angular.module("app", [])
.controller("mainController", function($scope) {
    $scope.name = "yangbo5207";
})
.directive("helloWorld", function() {
    return {
        restrict: "EA",
        scope: {},
        replace: true,
        transclude: true,
        template: "
你看不見我
" } })

運行上面的代碼,輸出

china
yangbo5207

我們查看渲染出來的html,結果為

china

yangbo5207

另外當開啟transclude時,會創建一個新的transclude空間,并且繼承父作用域(也就是scope設置的隔離作用域)

從上面例子我們知道,當transclude的值被設置為true時,嵌入的內容為{{name}},但是如果將它的值設置為element呢,我們可以在上例的基礎上進行一個簡單的修改,發現,嵌入內容為整個元素

{{name}}

查看渲染結果

china

yangbo5207

注意:在一個指令的模板中,只能聲明一次ng-transclude

那么問題來了,如果我們想要把嵌入內容多次放入我們的模板中怎么辦?

可以使用$transclude,后面會講到!也可以使用complie函數中,里面的transcludeFn參數,后面會講到!或者使用link連接函數

9. controller

可以是一個字符串或者函數。

若為字符串,則將字符串當做控制器的名字,來查找注冊在應用中的控制器的構造函數

angular.module("app", [])
.directive("myDirective", function() {
    return {
        restrict: "EA",
        replace: true,
        transclude: true,
        
        // 會查找模塊中其他被名為targetController的控制器
        controller: "targetController"
    }
})
.controller("targetController", function($scope, $element, $attrs, $transclude) {
    // 控制器邏輯放在這里
})

當然,也可以直接在指令內部定義為匿名函數,同樣可以注入任何服務

angular.module("app", [])
.directive("myDirective", function() {
    return {
        restrict: "EA",
        replace: true,
        transclude: true,
        controller: function($scope, $element, $attrs, $transclude) {
            // 控制器邏輯
        }
    }
})

另外還有一些特殊的服務可以注入,

$scope 與指令元素相關聯的作用域

$element 當前指令對應的元素

$attrs 當前元素的屬性組成的對象

$transclude 嵌入鏈接函數,實際被執行用來克隆元素和操作DOM中的函數(除非是用來定義一些可復用的行為,否則一般不推薦在這使用)

指令的控制器和link函數(后面會講到)可以進行互換。區別在于,控制器主要用來提供可在指令間復用的行為,可對外提供與外部交互的接口,但是link鏈接只能在當前指令內部中定義行為,且無法在指令間復用。

外面的世界很精彩。
angular.module("app", [])
.directive("testDirective", function() {
    return {
        transclude: true,
        replace: true,
        controller: function($scope, $element, $attrs, $transclude, $log) {
            $transclude(function(clone) {
                var a = angular.element("");
                a.attr("href", $attrs.url);
                a.text(clone.text());
                $element.append(a);
            });
        }
    }
})

實例地址

$transclude 可以接受兩個參數,第一個是$scope,第二個是才有參數clone的回調函數。

而這個clone實際上就是嵌入的內容。可以在根據它做很多DOM操作。

它還有最簡單的用法

angular.module("app", [])
.directive("testDirective", function() {
    return {
        transclude: true,
        replace: true,
        controller: function($scope, $element, $attrs, $transclude, $log) {
            
            // 這里的$transclude就是嵌入的內容
            var a = $transclude();
            $element.append(a);
        }
    }
})

但是我們要注意,使用$transclude會生成一個新的作用域。默認情況下,如果我們簡單使用$transclude(),那么其作用域就是$transclude 生成的作用域。但是如果我們使用$transclude($scope, function(clone) {}),那么作用域就是directive的作用域了。

當然問題又來了,如果我們想使用父級作用域呢?

$scope.$parent
炒美股,上老虎2
angular.module("app", [])
.controller("parentController", function($scope) {
    $scope.title = "PARENT TIGER";
})

.controller("sonController", function($scope) {
    $scope.title = "CHILDREN TIGER";
})

.directive("testDirective", function() {
    return {
        transclude: true,
        replace: true,
        controller: function($scope, $element, $attrs, $transclude, $log) {
            var a = $transclude();
            $element.append(a);
            $log.info($scope.title);
            $log.info($scope.$parent.title);
        }
    }
})

實例地址

10. controllerAs

angualr 1.2之后,就已經開始支持controllerAs的語法,這樣我們就可以不用將屬性和方法掛載到$scope上,而是this上。

{{ demo.name }}
angular.module("app", [])
.controller("demoController", function() {
    this.name = "Jake";
})

實例地址

我們可以從實例中看出,這里的this就是指的as后面的那個別名。然后我們在表達式中就可以使用這個別名

我們知道,在directive中的controller,主要職能是對外提供交互接口,而結合require與link,因此我們常常會利用這樣的語法而非上面例子中的$scope

app.directive("testDirective", function() {
    return {
        controller: function() {
            this.name = "Jake";
        }
    }
})
11. require

字符串或者數組,字符串代表另一個指令的名字,它將作為link函數的第四個參數。具體用法我們可以舉例子來說明。

假設現在我們要編寫兩個指令,兩個指令的link函數中存在許多重合的方法,這時候我們就可以將這些重復的方法寫在第三個指令的controller中,然后在這兩個指令中,使用require將第三個指令引入進來,然后我們就可以通過link連接函數的第四個參數引用這些重合的方法了

指令之間常常通過這種方式進行交互

{{expander.text}}
var expModule=angular.module("expanderModule",[])
expModule.directive("accordion", function() {
    return {
        restrict : "EA",
        replace : true,
        transclude : true,
        template : "
", controller : function() { var expanders = []; this.gotOpened = function(selectedExpander) { angular.forEach(expanders, function(expander) { if (selectedExpander != expander) { expander.showMe = false; } }); } this.addExpander = function(expander) { expanders.push(expander); } } } }); expModule.directive("expander", function() { return { restrict : "EA", replace : true, transclude : true, require : "^?accordion", scope : { title : "=expanderTitle" }, template : "
" + "
{{title}}
" + "
" + "
", link : function(scope, element, attrs, accordionController) { scope.showMe = false; accordionController.addExpander(scope); scope.toggle = function toggle() { scope.showMe = !scope.showMe; accordionController.gotOpened(scope); } } } }); expModule.controller("SomeController",function($scope) { $scope.expanders = [{ title : "Click me to expand", text : "Hi there folks, I am the content that was hidden but is now shown." }, { title : "Click this", text : "I am even better text than you have seen previously" }, { title : "Test", text : "test" }]; });

實例地址

實例說明,controller是用來與不同指令之間通信的。

另外我們可以在require的參數值加上下面的某個前綴,這回改變查找控制器的行為。

沒有前綴 指令會在自身提供的控制器中進行查找,如果找不到任何控制器,則會拋出一個error

? 若在當前指令中沒有找到所需的控制器,則會將null傳給link鏈接函數的第四個參數

^ 如果在當前的指令中沒有找到所需的控制器,則會查找父元素的控制器

?^ 如果在當前和父元素中都沒有找到控制器,則會將null傳給link

12. angular指令編譯過程

首先加載angular庫,查找ng-app指令,從而找到應用的邊界,根據ng-app劃定的作用域來調用$compile服務進行編譯。

angular會遍歷整個html文檔,并根據js中指令的定義來處理在頁面上聲明的各個指令,按照指令的優先級排列,根據指令中的配置參數(template, replace, transclude等)轉換DOM,然后就開始按照順序執行各指令的compile函數(如果指令上有定義compile函數)對模板自身進行轉換。

此處的compile函數值什么指令中配置的,與上面說的$compile服務不一樣

每個compile函數執行完后會返回一個link函數,所有的link函數會合成一個大的link函數,然后這個大的link函數就會被執行, 主要做數據綁定,通過 DOM上注冊監聽器來動態修改scope中的數據,或者是使用$watchs監聽scope中變量來修改DOM,從而建立雙向綁定等等。

若我們的指令中沒有配置compile函數,那我們配置的link函數就會運行,她做的事情大致跟上面compile返回之后所有的link合成的大link函數差不多。

所以,在指令中compile與link選項是互斥的,如果同時設置了這兩項,那么就會把compile所返回的函數當做是鏈接函數,而link選項本身會被忽略。

13. compile編譯函數與link鏈接函數

cmopile選項可以返回一個對象或者函數,在這里我們可以在指令和實時數據被放到DOM之前進行DOM操作,比如我們可以在這里進行添加或者刪除節點的DOM操作。

所以編譯函數是負責對模板的DOM進行轉換,并且僅僅只會運行一次

//compile函數的語法
compile:function compile(tElement,tAttrs,transclude){
      return{
        pre:function preLink(scope,iElement,iAttrs,controller){},
        post:function postLink(scope,iElement,iAttrs,controller){}
      }
    }

對于我們編寫的大部分指令來說,并不需要對模板進行轉換,所以大部分情況只需要編寫link函數就行。

preLink函數會在編譯階段之后,指令鏈接到子元素之前執行,類似的,postLink會在指令鏈接到子元素之后執行。這意味著,為了不破壞綁定過程,如果你需要修改DOM結構,你應該在postLink函數中來做這件事情。

link函數負責將作用域與DOM進行鏈接

//link鏈接函數
link:function postLink(scope,iElement,iAttrs){}

若指令中定義有require選項,則link函數會有第四個參數,代表控制器或者所依賴的指令的控制器(上面require選項例子已有例子)

內容都真夠多的,終于整理完了,今天寫了兩篇文章,感覺好累!如果大家覺得文章對你有幫助,求贊求收藏。

許多內容都是從不同的網站上整理而來,每一個實例都是自己運行過后保存在codepen上,大家可以結合codepen的例子結合理解文章內容,本文屬于收集文,非原創,但絕對干貨!值!得!一!贊!與收藏。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/111298.html

相關文章

  • Angular directive 實例詳解

    摘要:方法三使用調用父作用域中的函數實例地址同樣采用了缺省寫法,運行之后,彈出窗口布爾值或者字符,默認值為這個配置選項可以讓我們提取包含在指令那個元素里面的內容,再將它放置在指令模板的特定位置。 準備代碼,會在實例中用到 var app = angular.module(app, []); angular指令定義大致如下 app.directive(directiveName, functi...

    BLUE 評論0 收藏0
  • Angular directive 實例詳解

    摘要:方法三使用調用父作用域中的函數實例地址同樣采用了缺省寫法,運行之后,彈出窗口布爾值或者字符,默認值為這個配置選項可以讓我們提取包含在指令那個元素里面的內容,再將它放置在指令模板的特定位置。 準備代碼,會在實例中用到 var app = angular.module(app, []); angular指令定義大致如下 app.directive(directiveName, functi...

    mengera88 評論0 收藏0
  • angular 指令詳解(一)compile與link

    摘要:實例元素及實例屬性都會作為參數傳遞到函式函式關連於此實例的實例元素實例元素的屬性結論到目前為止,但愿你有清楚的理解關于及之間的差異。 原文地址:https://987.tw/2014/09/03/ang... AngularJS directives是令人驚艷的。它允許你創造高度語意且可重復利用的元件。在某種意義上你可以認為它是極致的web components先驅者。 有許多很棒的文...

    crossea 評論0 收藏0
  • angularJS directive用法詳解

    摘要:可選參數,布爾值或者對象默認值為,可能取值默認值。布爾值或者字符,默認值為這個配置選項可以讓我們提取包含在指令那個元素里面的內容,再將它放置在指令模板的特定位置。 前言 最近學習了下angularjs指令的相關知識,也參考了前人的一些文章,在此總結下。 歡迎批評指出錯誤的地方。 Angularjs指令定義的API showImg(https://segmentfault.com/img...

    hlcc 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<