在使用Anguarjs進(jìn)行web開(kāi)發(fā)或者進(jìn)行SPA(single page application)開(kāi)發(fā)時(shí),往往會(huì)遇到下面這樣的問(wèn)題。
刷新頁(yè)面時(shí),頁(yè)面會(huì)出現(xiàn)一些亂碼,這里的亂碼具體是指`{{expression}}`或者`{{expression | filter}}`這種形式的表達(dá)式亂碼,然后這些亂碼又快速的消失了,然后頁(yè)面就正常了。這個(gè)問(wèn)題的原因是,在一些現(xiàn)代瀏覽器,比如Chrome,F(xiàn)irefox等中尤為嚴(yán)重。當(dāng)然還跟環(huán)境的網(wǎng)絡(luò)速度有關(guān)。
出現(xiàn)這個(gè)問(wèn)題的根本原因是,JavaScript操作DOM都是在DOM加載完成(DOM Ready)之后的才進(jìn)行的。換句話說(shuō),Angularjs只會(huì)在DOM Ready之后才回去解析html模版以及Angularjs的directive,在這之前html模版中的內(nèi)容會(huì)被原封不動(dòng)的展示在頁(yè)面,這時(shí)候就會(huì)出現(xiàn)所謂的亂碼問(wèn)題。
那么我們?nèi)绾谓鉀Q這個(gè)問(wèn)題呢?
Angularjs官方針對(duì)這個(gè)問(wèn)題提供了原生的解決方案,就是我們今天要說(shuō)的主角ng-cloak
指令。
我們先來(lái)看一下Angularjs的源碼中對(duì)這個(gè)ng-cloak
是如何實(shí)現(xiàn)的。
Angularjs將ng-cloak
實(shí)現(xiàn)為directive,其代碼如下,
!angular.$csp()
&& angular
.element(document)
.find('head')
.prepend('<style type="text/css">' +
'@charset "UTF-8";' +
'[ng\\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak,.ng-hide{display:none !important;}' +
'ng\\:form{display:block;}' +
'.ng-animate-block-transitions{transition:0s all!important;-webkit-transition:0s all!important;}' +
</style>');
大家不要對(duì)這一坨代碼感到畏懼,其實(shí)它做的事很簡(jiǎn)單,就是在html的中head
標(biāo)簽中插入一段內(nèi)聯(lián)的css樣式。其中部分的代碼是這樣的,
[ng\\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide {
display:none !important;
}
很顯然,Angularjs對(duì)ng-cloak
相關(guān)的元素設(shè)置了display: none !important
這樣一個(gè)屬性,目的就是隱藏相關(guān)元素。這樣在在DOM還沒(méi)有Ready的時(shí)候,將相關(guān)元素隱藏起來(lái),這樣頁(yè)面就不會(huì)出現(xiàn)亂碼了。
當(dāng)DOM Ready的時(shí)候,Angularjs開(kāi)始解析指令。我們來(lái)看一下ng-cloak
這個(gè)指令都做了哪些事情,
var ngCloakDirective = ngDirective({
compile: function(element, attr) {
attr.$set('ngCloak', undefined);
element.removeClass('ng-cloak');
}
});
可見(jiàn),當(dāng)Angularjs開(kāi)始解析ng-cloak
指令的時(shí)候,又會(huì)把這個(gè)樣式給去除掉。這樣頁(yè)面又顯示了。
通過(guò)以上分析,我們知道了使用ng-cloak
指令來(lái)避免頁(yè)面出現(xiàn)亂碼的原理,其實(shí)通過(guò)先隱藏后顯示來(lái)規(guī)避了DOM尚未Ready這段時(shí)間的真空期。
理論是美好的,但是現(xiàn)實(shí)往往會(huì)給我一個(gè)響亮的耳光。
在實(shí)際使用的過(guò)程中,我們要想使上面的過(guò)程完美表現(xiàn),就必須要先在head
標(biāo)簽中先引入Angularjs的源碼,而不能在頁(yè)面的最后引入Angularjs文件。
因?yàn)楹笳邥?huì)造成這樣一種情況:在Angularjs文件還沒(méi)引入時(shí),意味著還沒(méi)給ng-cloak
相關(guān)元素做隱藏處理,頁(yè)面就已經(jīng)展示了,這是頁(yè)面仍然會(huì)出現(xiàn)亂碼。
但是一般性的原則告訴我們,應(yīng)該把css文件放在頭部,把js文件放在尾部。那么我們?nèi)绾谓鉀Q這個(gè)矛盾呢?
解決方案是,我們手動(dòng)在head
中將ng-cloak
相關(guān)的元素設(shè)置為隱藏,即添加如下的代碼,
<head>
<style>
[ng:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak {
display:none !important;
}
</style>
</head>
或者將這一段代碼放在我們?cè)?code>head中加載的css文件中,這樣就可以確保頁(yè)面加載的時(shí)候,不管它有沒(méi)有DOM Ready,ng-cloak
相關(guān)元素肯定是隱藏的。
如果你發(fā)現(xiàn)在body
上加了ng-cloak
,但是仍然不起作用,那么原因應(yīng)該就是上面所描述的,這時(shí)候你就需要在head
中添加隱藏代碼或者在引入的css文件中添加相關(guān)代碼了。
最后提一點(diǎn),如果中的表達(dá)式僅僅是展示一些文本內(nèi)容,我們可以使用
ng-bind
這個(gè)指令來(lái)實(shí)現(xiàn)。
更多建議: