摘要:發(fā)生改變時,會得到對應的響應。工廠方法通過執(zhí)行,讓它遵守所有注入聲明規(guī)則,讓其變?yōu)榭勺⑷氲?。這屬性用于在的調用之前進行排序。這將允許之間相互溝通,增強相互之間的行為。
英文地址:directive
Directive是教HTML玩一些新把戲的途徑。在DOM編譯期間,directives匹配HTML并執(zhí)行。這允許directive注冊行為或者轉換DOM結構。
Angular自帶一組內置的directive,對于建立Web App有很大幫助。繼續(xù)擴展的話,可以在HTML定義領域特定語言(domain specific language ,DSL)。
Directive有駝峰式(camel cased)的風格的命名,如ngBind(放在屬性里貌似用不了~)。但directive也可以支蛇底式的命名(snake case),需要通過:(冒號)、-(減號)或_(下劃線)連接。作為一個可選項,directive可以用“x-”或者“data-”作為前綴,以滿足HTML驗證需要。這里列出directive的合法命名:
ng:bind
ng-bind
ng_bind
x-ng-bind
data-ng-bind
Directive可以放置于元素名、屬性、class、注釋中。下面是引用myDir這個directive的等價方式。(但很多directive都限制為“屬性”的使用方式)
Directive可以通過多種方式引用,下面列出N種等價的方式:
二、String interpolationinvoke-directive Hello
ngBind="name" 這個用不了~~
ng:bind="name"
ng_bind="name"
ng-bind="name"
data-ng-bind="name"
x-ng-bind="name"
在編譯過程中,compiler通過$interpolate服務匹配文本與屬性中的嵌入表達式(如{{something}})。這些表達式將會注冊為watches,并且作為digest cycle(之前不是digest-loop嗎?!)的一部分,一同更新。下面是一個簡單的interpolation:
Hello {{username}}!三、Compilation process, and directive matching
HTML“編譯”的三個步驟:
1. 首先,通過瀏覽器的標準API,將HTML轉換為DOM對象。這是很重要的一步。因為模版必須是可解析(符合規(guī)范)的HTML。這里可以跟大多數的模版系統(tǒng)做對比,它們一般是基于字符串的,而不是基于DOM元素的。
2. 對DOM的編譯(compilation)是通過調用$comple()方法完成的。這個方法遍歷DOM,對directive進行匹配。如果匹配成功,那么它將與對應的DOM一起,加入到directive列表中。只要所有與指定DOM關聯的directive被識別出來,他們將按照優(yōu)先級排序,并按照這個順序執(zhí)行他們的compile() 函數。directive的編譯函數(compile function),擁有一個修改DOM結構的機會,并負責產生link() function的解析。$compile()方法返回一個組合的linking function,是所有directive自身的compile function返回的linking function的集合。
3. 通過上一步返回的linking function,將模版與scope連接起來。這反過來會調用directive自身的linking function,允許它們在元素上注冊一些監(jiān)聽器(listener),以及與scope一起建立一些watches。這樣得出的結果,是在scope與DOM之間的一個雙向、即時的綁定。scope發(fā)生改變時,DOM會得到對應的響應。
var $compile = ...; // injected into your code var scope = ...; var html = ""; // Step 1: parse HTML into DOM element var template = angular.element(html); // Step 2: compile the template var linkFn = $compile(template); // Step 3: link the compiled template with the scope. linkFn(scope);四、Reasons behind the compile/link separation
在這個時候,你可能會想知道為什么編譯進程會劃分為compile和linke兩個步驟。為了明白這一點,讓我們看看一個真實的例子(repeater)
Hello {{user}}, you have these actions:
簡單地講,之所以分開compile和linke兩步,是因為有時候需要在model改變后,對應的DOM結構也需要改變的情況,如repeaters。
當上面的例子被編譯時,編譯器會遍歷所有節(jié)點以尋找directive。{{user}}是一個interpolation directive的例子。ngRepeat又是另外一個directive。但ngRepeat有一個難點。它需要能夠很快地為每一個在users.actions中的action制造出新的li的能力。這意味著它為了滿足克隆li并且嵌入特定的action(這里是指user的actions的其中一個值)的目的,需要保持一個干凈li元素的拷貝,li元素需要被克隆和插入ul元素。但僅僅克隆li元素是不夠的。還需要編譯li,以便它的directive({{action.descriptions}})能夠在正確的scope中被解析。原始的方法,一般會簡單地插入一個li元素的拷貝,然后編譯它。但編譯每一個li元素的拷貝會比較緩慢,因為編譯過程需要我們遍歷DOM節(jié)點樹,查找directive并運行它們。如果我們有一個編譯,需要通過repeater對100個item進行處理,那么我們將陷入性能問題。
問題的解決方案,是將編譯過程分解為兩個步驟。compile階段識別出所有directive,并且將它們按照優(yōu)先級進行排序,在linking階段將特定的scope與特定的li綁定在一起。
ngRepeat將各個li分開編譯以防止編譯過程落入li元素中。li元素的編譯結果是一個包含所有包含在li元素中的directive的linking function,準備與特定li元素的拷貝進行連接。在運行時,ngRepeat監(jiān)測表達式,并作為一個item,被加入到一個li元素拷貝的數組,為克隆好的li元素創(chuàng)建新的scope,并調用該拷貝對應的link function。
總結:
編譯函數(compile function) - 編譯函數在directive中是比較少見的,因為大多數directive只關心與指定的DOM元素工作,而不是改變DOM元素的模版(DOM自身以及內部的結構)。為了優(yōu)化性能,一些可以被directive實例共享的操作,可以移動到compile函數中。
連接函數(link function) - 極少directive是沒有l(wèi)ink function的。link function允許directive在指定的拷貝后的DOM元素實例上注冊監(jiān)聽器,也可以將scope中特定內容復制到DOM中。
在這個例子里面,我們將建立一個根據輸入格式,顯示當前時間的directive。
六、寫一個directive(詳細版)time-format Date format:
Current time is :
下面是一個創(chuàng)建directive樣例(directive對象定義模版)。想看詳細列表,請繼續(xù)往下看。
var myModule = angular.module(...); myModule.directive("directiveName", function factory(injectables) { var directiveDefinitionObject = { priority: 0, template: "", templateUrl: "directive.html", replace: false, transclude: false, restrict: "A", scope: false, compile: function compile(tElement, tAttrs, transclude) { return { pre: function preLink(scope, iElement, iAttrs, controller) { ... }, post: function postLink(scope, iElement, iAttrs, controller) { ... } } }, link: function postLink(scope, iElement, iAttrs) { ... } }; return directiveDefinitionObject; });
在大多數場景下,我們并不需要精確控制,所以上面的定義是可以化簡的。定義模版中的每一部分,將在下面章節(jié)講解。在這個章節(jié),我們僅僅關注定義模版的異構體(isomers of this skeleton,沒看懂。。。期待大家補充)。
簡化代碼的第一步是依賴默認值。因此,上面的代碼可以簡化為:
var myModule = angular.module(...); myModule.directive("directiveName", function factory(injectables) { var directiveDefinitionObject = { compile: function compile(tElement, tAttrs) { return function postLink(scope, iElement, iAttrs) { ... } } }; return directiveDefinitionObject; });
大多數directive只關心實例,而不是模版轉換,所以可以進一步化簡(翻譯得很勉強。。。期待大家補充):
var myModule = angular.module(...); myModule.directive("directiveName", function factory(injectables) { return function postLink(scope, iElement, iAttrs) { ... } });七、工廠方法
工廠方法負責創(chuàng)建directive。它僅僅使用一次,就在compiler第一次匹配到directive的時候。你可以在這里執(zhí)行一些初始化操作。工廠方法通過$injector.invoke執(zhí)行,讓它遵守所有注入聲明規(guī)則(rules of injection annotation),讓其變?yōu)榭勺⑷氲摹?/p> 八、directive定義對象說明
directive定義對象提供了compiler的結構。屬性如下:
name - 當前scope的名稱,注冊時可以使用默認值(不填)。
priority(優(yōu)先級)- 當有多個directive定義在同一個DOM元素時,有時需要明確它們的執(zhí)行順序。這屬性用于在directive的compile function調用之前進行排序。如果優(yōu)先級相同,則執(zhí)行順序是不確定的(經初步試驗,優(yōu)先級高的先執(zhí)行,同級時按照類似棧的“后綁定先執(zhí)行”。另外,測試時有點不小心,在定義directive的時候,兩次定義了一個相同名稱的directive,但執(zhí)行結果發(fā)現,兩個compile或者link function都會執(zhí)行)。
terminal(最后一組)- 如果設置為”true”,則表示當前的priority將會成為最后一組執(zhí)行的directive。任何directive與當前的優(yōu)先級相同的話,他們依然會執(zhí)行,但順序是不確定的(雖然順序不確定,但基本上與priority的順序一致。當前優(yōu)先級執(zhí)行完畢后,更低優(yōu)先級的將不會再執(zhí)行)。
scope - 如果設置為:
true - 將為這個directive創(chuàng)建一個新的scope。如果在同一個元素中有多個directive需要新的scope的話,它還是只會創(chuàng)建一個scope。新的作用域規(guī)則不適用于根模版(root of the template),因此根模版往往會獲得一個新的scope。
{}(object hash) - 將創(chuàng)建一個新的、獨立(isolate)的scope?!眎solate” scope與一般的scope的區(qū)別在于它不是通過原型繼承于父scope的。這對于創(chuàng)建可復用的組件是很有幫助的,可以有效防止讀取或者修改父級scope的數據。這個獨立的scope會創(chuàng)建一個擁有一組來源于父scope的本地scope屬性(local scope properties)的object hash。這些local properties對于為模版創(chuàng)建值的別名很有幫助(useful for aliasing values for templates --!)。本地的定義是對其來源的一組本地scope property的hash映射(Locals definition is a hash of local scope property to its source #&)$&@#)($&@#):
@或@attr - 建立一個local scope property到DOM屬性的綁定。因為屬性值總是String類型,所以這個值總是返回一個字符串。如果沒有通過@attr指定屬性名稱,那么本地名稱將與DOM屬性的名稱一直。例如
=或=expression(這里也許是attr) - 在本地scope屬性與parent scope屬性之間設置雙向的綁定。如果沒有指定attr名稱,那么本地名稱將與屬性名稱一致。例如
&或&attr - 提供一個在父scope上下文中執(zhí)行一個表達式的途徑。如果沒有指定attr的名稱,那么local name將與屬性名稱一致。例如
controller - controller 構造函數。controller會在pre-linking步驟之前進行初始化,并允許其他directive通過指定名稱的require進行共享(看下面的require屬性)。這將允許directive之間相互溝通,增強相互之間的行為。controller默認注入了以下本地對象:
$scope - 與當前元素結合的scope
$element - 當前的元素
$attrs - 當前元素的屬性對象
$transclude - 一個預先綁定到當前轉置scope的轉置linking function :function(cloneLinkingFn)。(A transclude linking function pre-bound to the correct transclusion scope)
require - 請求另外的controller,傳入當前directive的linking function中。require需要傳入一個directive controller的名稱。如果找不到這個名稱對應的controller,那么將會拋出一個error。名稱可以加入以下前綴:
? - 不要拋出異常。這使這個依賴變?yōu)橐粋€可選項。
^ - 允許查找父元素的controller
restrict - EACM的子集的字符串,它限制directive為指定的聲明方式。如果省略的話,directive將僅僅允許通過屬性聲明:
E - 元素名稱:
A - 屬性名:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/78014.html
摘要:除在全球率先支持外,現已全面應用于等主流框架中。本文中,我們將專注于如何將添加到用編寫的應用程序中。使用創(chuàng)建應用程序。接下來,我們定義適用于這些元素中托管的應用程序面板元素和控件的規(guī)則。往期精彩用玩轉您的應用 為什么選擇WijmoJS? 作為一款純前端控件集,WijmoJS秉承快如閃電,觸控優(yōu)先的設計理念,在提供優(yōu)質服務和產品的同時,專注于企業(yè)應用開發(fā),不斷優(yōu)化產品架構,與時俱進。除在...
摘要:在之前的文章中,我們已經介紹了使用與三大框架結合搭建您的應用程序。使用創(chuàng)建應用程序。擴展閱讀用玩轉您的應用用玩轉您的應用用玩轉您的應用近期活動問卷調查揚帆萬里,因您前行使用反饋意見征集 前言: 在本文中,我們將著重介紹如何將WijmoJS與Ionic一起使用,來創(chuàng)建一款移動端支持優(yōu)先、快捷高效的應用程序。在之前的文章中,我們已經介紹了使用WijmoJS與Angular、React、Vu...
摘要:相反,我們將專注于將添加到用編寫的簡單應用程序中。使用創(chuàng)建應用程序。示例應用程序有兩個組件應用程序和。除在全球率先支持外,現已全面應用于等主流框架中。 showImg(https://segmentfault.com/img/bVbcvaQ?w=500&h=278); 概述 在本文中,我們將展示如何將WijmoJS與NPM和Webpack一起使用來創(chuàng)建最流行的基于JavaScript應...
摘要:關于作為一款純前端控件集,秉承快如閃電,觸控優(yōu)先的設計理念,在提供優(yōu)質服務和產品的同時,專注于企業(yè)應用開發(fā),不斷優(yōu)化產品架構,與時俱進。靈活的為用戶提供易用輕松的操作體驗,全面滿足開發(fā)所需,是構建企業(yè)應用程序最完整的純前端控件集。 前文回顧 在《用 WijmoJS 玩轉您的Web應用》系列文章中,我們已經介紹了Angular和Vue框架下 WijmoJS 的玩法。 而今天,我們將展示如...
閱讀 1225·2021-09-26 09:55
閱讀 3191·2019-08-30 15:55
閱讀 965·2019-08-30 15:53
閱讀 2296·2019-08-30 13:59
閱讀 2380·2019-08-29 13:08
閱讀 1107·2019-08-29 12:19
閱讀 3302·2019-08-26 13:41
閱讀 418·2019-08-26 13:24