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