##一.CSST是什麼
CSST 的近義詞是 JSONP,而不是 SASS、PostCSS 之類的東西。也就是說,JSONP 能做的,(CSS3 環境下)用 CSST 也可以做到
Ajax 不能跨域,而 JSONP 算是 Ajax 的跨域補丁(當然,還有其他跨域方法,但 JSONP 是應用最廣泛的)
CSST 最大的限制是只適用於支援 CSS3 的環境,但我們用不用它這不重要,思路與原理比較有意思
##二.實現原理
###1.用戶端(瀏覽器 JS)
- 發送請求
向 head 裡插入一個 <link>,透過 href 屬性發出請求
- 準備接收回應
建立一個看不見的 span,監聽其 animationstart 事件(所以需要 CSS3 環境)
###2.伺服器端(node/PHP...)
- 回傳樣式(將透過 id 套用給隱藏 span)
樣式內容分為兩部分:1. content(用 CSS 屬性 content 攜帶業務邏輯要回傳的字串);2. animation(通知用戶端,回應傳回了)
伺服器端只做這一件事,用戶端收到回應後,取出 span 的 content 內容,文字傳輸完成
###3.細節問題(技術手段)
- 怎麼監聽
<link>載入完畢?
收集線上的資料,發現常見的方案是計時器或者用 onpropertychange、DOMAttrModified。
考慮是 CSS3 場景,取巧用動畫開始 (animationstart) 這個事件來捕獲。
onpropertychange 和 DOMAttrModified 事件以及更新的 MutationObserver 在相容性方面存在很多問題,而 animationstart 事件相容性相對較好(不支援 Android 2.3 及其以下版本,不支援 IE6-IE9),因為動畫事件是 CSS3 動畫模組規範的一部分,支援 CSS3 動畫的 UA 應該都支援對應的動畫事件
- 怎麼傳送特殊字元("、'、\、\n、\r、\t)?
Chrome、Safari 對 content 樣式屬性字元解析並不一致
為避免未知解析規則影響,統一使用 base64 編碼
瀏覽器環境下編碼/解碼 Base64 相對容易,也適用於其他需要支援特殊字元的場景
##三.優缺點
優點:如果介面被攻陷的話,後果比 JSONP 小一點(link 標籤比 script 標籤安全些,後者注入程式碼能直接執行,前者只影響樣式)
P.S. 如果介面都被攻陷了,這一點防禦措施興許還能起到什麼關鍵性作用嗎?
缺點:
-
只支援 CSS3 環境
-
DOM 操作多於 JSONP(每次請求需要增加/刪除一個 link 一個 span,JSONP 每次只需要增加/刪除一個 script,而且隱藏 span 的增加/刪除以及樣式更新可能會導致頁面部分 reflow)
所以,不推薦使用 CSST,JSONP 明顯更方便實用,本文只是想說這種思路與原理值得了解
如果非要用的話,也應該考慮一下不支援/部分支援 CSS3 的 UA 的感受,需要完善特徵檢測(原專案暫時沒有添上):
var animation = false,
animationstring = 'animation',
keyframeprefix = '',
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
pfx = '',
elm = document.createElement('div');
if( elm.style.animationName !== undefined ) { animation = true; }
if( animation === false ) {
for( var i = 0; i < domPrefixes.length; i++ ) {
if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
pfx = domPrefixes[ i ];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animation = true;
break;
}
}
}
(以上程式碼摘自 Detecting CSS animation support - CSS | MDN)
更好的相容性需要手動重構程式碼,算了,了解下就好
###參考資料
-
mobilebone.js-mobile 行動 web APP 單頁切換骨架:參考 animationstart 事件的相容性(這週還得感謝 zxx 前輩,幫我解決了一個翻譯問題..)
暫無評論,快來發表你的看法吧