摘要:效果預(yù)覽來(lái)自的效果預(yù)覽引用了,已被墻,請(qǐng)謹(jǐn)慎預(yù)覽轉(zhuǎn)載聲明這篇文章其實(shí)源自的博客。主要內(nèi)容整個(gè)效果都建立在的里面。為了彌補(bǔ)這個(gè)缺陷,我決定改成在函數(shù)中對(duì)進(jìn)行操作。重點(diǎn)來(lái)了,是和初始位置的相對(duì)位置。就是元素的初始值。
效果預(yù)覽
來(lái)自codepen的效果預(yù)覽:(引用了angularjs,已被墻,請(qǐng)謹(jǐn)慎預(yù)覽)
http://codepen.io/flybywind/pen/aNjxJa
這篇文章其實(shí)源自BenNadel的博客。在此我要分享一下自己的收獲和一些更改。
主要內(nèi)容整個(gè)效果都建立在angularjs的directive里面。可以想到,作者綁定了mousemove事件,通過(guò)勾股定理計(jì)算的距離,除此之外,我還有些小收獲要跟大家分享一下:
directive中compile和link函數(shù)的區(qū)別
$interpolate和$compile這2個(gè)service的區(qū)別
如何把node內(nèi)部包含的所有文本字母都用span包裹起來(lái)
relative定位和absolute定位的差別
directive中compile和link函數(shù)的區(qū)別根據(jù)BenNadel自己在博客中的解釋?zhuān)?/p>
I use the compile() phase when I need to alter the structure of the DOM (Document Object Model) in a way that is based on nothing but the existing structure of DOM.
翻譯成漢字就是:當(dāng)我需要根據(jù)原始DOM(文檔對(duì)象模型,說(shuō)詳細(xì)了可能看不懂,還是用簡(jiǎn)稱(chēng)吧~)的結(jié)構(gòu)對(duì)Dom進(jìn)行改變時(shí),我使用compile函數(shù)。
道理其實(shí)也很簡(jiǎn)單,因?yàn)閍ngluar會(huì)對(duì)Dom結(jié)構(gòu)進(jìn)行改變,當(dāng)你進(jìn)入link函數(shù)后,你看到的Dom結(jié)構(gòu)可能跟你預(yù)期的不一樣,找不到你要的元素了,此時(shí)很多人可能就懵圈了。在BenNadel的另一篇博客中,他就給出了一個(gè)例子:首先他在一個(gè)directive中使用了template,在transclude部分(嵌入部分)中使用了ngRepeat。他發(fā)現(xiàn),只有在Compile階段,才能訪問(wèn)到使用了ngRepeat的元素,并且改變它們的class;而在link階段,是找不到的。
原因就是ngRepeat這個(gè)directive已經(jīng)把那些元素從Dom樹(shù)中刪除了,它們會(huì)在隨后被加入,但是在link階段你是找不到的。
所以,在這種可能很多人一輩子都見(jiàn)不到的情況下,你才必須使用compile。
在以上的例子中,BenNadel還利用priority對(duì)同一個(gè)directive進(jìn)行了兩階段處理,這種奇技淫巧從來(lái)沒(méi)見(jiàn)過(guò),領(lǐng)教了。
其實(shí)很多時(shí)候,在link和compile中處理的結(jié)果是一樣的,但是細(xì)節(jié)上有些差異,比如以下情況:
{{ word }}
其中bn-compile和bn-link分別是2個(gè)directive,一個(gè)在compile函數(shù)中打印出日志“compile”,并且給element增加class "c1",一個(gè)在link函數(shù)中打印出“l(fā)ink”,并且給element增加class "c2",c1、c2都有css樣式進(jìn)行展示。最終結(jié)果是生成的4個(gè)span都可以看到c1、c2的樣式,但是console中compile只打印了1次,link卻打印了4次。
這是因?yàn)椋琤n-compile是在compile階段修改的dom,它修改的是原始Dom結(jié)構(gòu),這跟你在html文檔中,手動(dòng)寫(xiě)上 class="c1"是一樣的。
當(dāng)然,在link函數(shù)中,也有一些地方是compile做不到的,有的時(shí)候你可能就是要對(duì)已經(jīng)部分渲染后的Dom結(jié)構(gòu)進(jìn)行修改,而且link函數(shù)中可以傳入scope,此時(shí)你可以進(jìn)行數(shù)據(jù)綁定了。這也就是下面我要講到的。
$interpolate和$compile這2個(gè)service的區(qū)別在BenNadel的原始文章中,他使用了compile對(duì)dom結(jié)構(gòu)進(jìn)行修改。但是如果我的文本內(nèi)容是通過(guò)數(shù)據(jù)綁定了,如下:
{{hello}}
特效就失敗了,如下:
第二個(gè)div因?yàn)榻壎ǖ氖莿?dòng)態(tài)數(shù)據(jù),最終是以模板形式顯示的。
為了彌補(bǔ)這個(gè)缺陷,我決定改成在link函數(shù)中對(duì)Dom進(jìn)行操作。其實(shí)就是把BenNadel在compile中的代碼放到link最開(kāi)始執(zhí)行就行了。另外,還需要對(duì){{}}進(jìn)行手動(dòng)編譯,此時(shí)$interpolate就要閃亮登場(chǎng)了。
以下是我的部分js代碼:
angular.module("Demo").directive( "scatterEffect", // $compile是把字符串編譯為element,所以字符串必須是dom形式 // $interpolate是把表達(dá)式和data 綁定到一起,$compile中會(huì)調(diào)用$interpolate function ($document, $interpolate) { return ({ link: link, restrict: "A" }); function link(scope, element, attributes) { // 如果是compile,則無(wú)法獲取scope var realContent = $interpolate(element.html())(scope); element.empty().append(realContent); // 這是原來(lái)compile中的函數(shù),element處理后,再放到link中調(diào)用 wrapLetters(element); /* other code */ } })
在以上代碼中,element.html()返回的是字符串,比如在處理第一個(gè)div時(shí),就是Happy Friday You Beautiful People!,第二個(gè)div就是{{hello}},開(kāi)始我嘗試用$compile編譯這個(gè)字符串,結(jié)果控制臺(tái)顯示 unrecognized expression: Happy Friday You Beautiful People!以及unrecognized expression: {{hello}} !問(wèn)了一下google大叔,發(fā)現(xiàn)原來(lái)要用$interpolate才行。
$compile是把字符串編譯為element,所以字符串必須是dom形式;$interpolate是把表達(dá)式和data綁定到一起,$compile中會(huì)調(diào)用$interpolate,后者只是前者的子過(guò)程。顯然,在我這個(gè)情況下,用$interpolate才行。
其實(shí)Happy Friday You Beautiful People!扔到chrome,會(huì)自動(dòng)給你加html和body使其正常顯示,但是angular沒(méi)法替你加,加上就亂套了。所以$compile必須接受標(biāo)準(zhǔn)的html語(yǔ)句,此處可以用正則判斷一下。我就懶得寫(xiě)了。
這句話盡管很長(zhǎng),但是做起來(lái),其實(shí)也很難(⊙﹏⊙)b。在此我只能奉上大神的代碼和我的膝蓋了,謹(jǐn)和諸君分享:
function findTextNodes(parent) {
// node是一個(gè)DOMElement, map返回一個(gè)jQuery對(duì)象,所以要想獲得array可以使用toArray() or get()
/* 我的注釋
If the node is an element node, the nodeType property will return 1.
If the node is an attribute node, the nodeType property will return 2.
If the node is a text node, the nodeType property will return 3.
If the node is a comment node, the nodeType property will return 8.
*/
// 此處的angular.element就是jQuery
var textNodes = angular.element(parent).contents().map(
function operator(i, node) {
return ((node.nodeType === 1) ? findTextNodes(node) : node);
}
);
return (textNodes.toArray());
}
// I find and wrap each text-based letter, within the given parent,
// in its own Span tag.
function wrapLetters(parent) {
findTextNodes(parent).forEach(
function(node) {
// Replace each individual letter with a Span tag.
var wrappedHtml = node.nodeValue.replace(/(S)/g, "$1");
// 最值得推敲的在這里:
var fragment = angular.element(document.createDocumentFragment())
.append(wrappedHtml);
node.parentNode.insertBefore(fragment[0], node);
node.parentNode.removeChild(node);
// 以下方法不行:jquery生成的元素列表默認(rèn)丟棄了首尾空格!
//$(wrappedHtml).insertBefore(node);
//node.parentNode.removeChild( node );
}
);
}
其實(shí)提取textNode,然后正則替換,最后插入原來(lái)的位置,聽(tīng)起來(lái)不難,但是如果利用jQuery把字符串轉(zhuǎn)換為dom,那么兩頭的空格就會(huì)丟掉,比如Happy Friday You 這個(gè)node,正則替換后wrappedHtml是這樣的:
jQuery轉(zhuǎn)換后,前后的空格都沒(méi)了。所以不能用它來(lái)轉(zhuǎn)換。
(哪位大神如果知道有可以控制jquery不丟空格的方法,請(qǐng)不吝賜教!)
最后,BenNadel大神也只好使用原生js進(jìn)行dom樹(shù)的替換了。
下面我們說(shuō)點(diǎn)關(guān)于css的知識(shí)。我經(jīng)常對(duì)absolute元素進(jìn)行top、left、right、bottom定位,我也知道這樣做之前,父元素必須用relative,但是我還真不知道原來(lái)relative元素也可以用TLRB這四兄弟進(jìn)行操作!真是丟人,確實(shí)需要反思啊。下面附上英文解釋和中文對(duì)照翻譯:
static Default value. Elements render in order, as they appear in the document flow
absolute The element is positioned relative to its first positioned (not static) ancestor element
fixed The element is positioned relative to the browser window
relative The element is positioned relative to its normal position, so "left:20px" adds 20 pixels to the element"s LEFT position
initial Sets this property to its default value.
static是position的默認(rèn)值,什么都不加就是那種效果;
absolute,大家最熟悉,TLRB指定的是和最近的relative父元素之間的相對(duì)位置
fixed,和瀏覽器窗口的相對(duì)位置,也比較簡(jiǎn)單。
重點(diǎn)來(lái)了,relative是和初始位置的相對(duì)位置。這也正是relative這個(gè)名字的含義,以前都沒(méi)仔細(xì)想過(guò)。。。
initial就是元素的初始值。有些元素的初始值可能不是static。反正各種奇葩的元素都可能,或者將來(lái)可能出現(xiàn)。
所以,總結(jié)一下,absolute、fixed和relative都是position類(lèi)型,只是相對(duì)的位置不同而已。
BenNadel正是利用了relative的這個(gè)特性,給每個(gè)span元素都設(shè)置為:
span.scatter-item { position: relative ; z-index: 100 ; }
然后,在mousemove事件中,調(diào)整top、left的值,使它們?cè)谑髽?biāo)距離目標(biāo)元素遠(yuǎn)的時(shí)候,偏離自己的位置;在鼠標(biāo)進(jìn)入目標(biāo)元素時(shí),重新回到自己的位置。
(z-index好像沒(méi)用~~)
終于碼完了
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/79276.html
摘要:效果預(yù)覽來(lái)自的效果預(yù)覽引用了,已被墻,請(qǐng)謹(jǐn)慎預(yù)覽轉(zhuǎn)載聲明這篇文章其實(shí)源自的博客。主要內(nèi)容整個(gè)效果都建立在的里面。為了彌補(bǔ)這個(gè)缺陷,我決定改成在函數(shù)中對(duì)進(jìn)行操作。重點(diǎn)來(lái)了,是和初始位置的相對(duì)位置。就是元素的初始值。 效果預(yù)覽 來(lái)自codepen的效果預(yù)覽:(引用了angularjs,已被墻,請(qǐng)謹(jǐn)慎預(yù)覽)http://codepen.io/flybywind/pen/aNjxJa 轉(zhuǎn)載聲明...
摘要:發(fā)生改變時(shí),會(huì)得到對(duì)應(yīng)的響應(yīng)。工廠方法通過(guò)執(zhí)行,讓它遵守所有注入聲明規(guī)則,讓其變?yōu)榭勺⑷氲摹_@屬性用于在的調(diào)用之前進(jìn)行排序。這將允許之間相互溝通,增強(qiáng)相互之間的行為。 英文地址:directive Directive是教HTML玩一些新把戲的途徑。在DOM編譯期間,directives匹配HTML并執(zhí)行。這允許directive注冊(cè)行為或者轉(zhuǎn)換DOM結(jié)構(gòu)。 Angular自帶...
摘要:實(shí)例元素及實(shí)例屬性都會(huì)作為參數(shù)傳遞到函式函式關(guān)連於此實(shí)例的實(shí)例元素實(shí)例元素的屬性結(jié)論到目前為止,但愿你有清楚的理解關(guān)于及之間的差異。 原文地址:https://987.tw/2014/09/03/ang... AngularJS directives是令人驚艷的。它允許你創(chuàng)造高度語(yǔ)意且可重復(fù)利用的元件。在某種意義上你可以認(rèn)為它是極致的web components先驅(qū)者。 有許多很棒的文...
摘要:屬性為時(shí),指示優(yōu)先級(jí)小于當(dāng)前指令的指令都不執(zhí)行,僅執(zhí)行到本指令。 作者:心葉時(shí)間:2018-04-22 10:58 一:自定義指令常用模板 下面是大致的說(shuō)明,不是全面的,后面來(lái)具體說(shuō)明一些沒(méi)有提及的細(xì)節(jié)和重要的相關(guān)知識(shí): angular.module(yelloxingApp, []).directive(uiDirective, function() { return { ...
閱讀 832·2023-04-25 22:13
閱讀 2344·2019-08-30 15:56
閱讀 2227·2019-08-30 11:21
閱讀 657·2019-08-30 11:13
閱讀 2022·2019-08-26 14:06
閱讀 1959·2019-08-26 12:11
閱讀 2291·2019-08-23 16:55
閱讀 541·2019-08-23 15:30