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