什么是單頁應用
單頁應用,是指將用戶視覺上的多個頁面在技術上使用一個載體來實現的應用。
換句話來講,用戶視覺效果,與技術實現的載體,並不是一定要一一對應的。采取哪種技術方案,取決於產品設計、技術組成以及方案之間的優劣平衡。
放到 Web 前端環境中,這個承載了多個視覺效果的載體,就是 html 文件(或 asp,jsp 等)。
為便於描述,本文將使用多個術語。其名稱及對應的含義如下所示:
頁面:技術上的一個html文件;
視圖:視覺上的一頁內容;
初步實現單頁應用
直觀效果的單頁應用,其實現過程其實並不復雜。
我們可以使用 div 或 section 等標簽承載視圖的展現,並通過腳本實現特定視圖的呈現與隱藏。例如:
<!DOCTYPE HTML> <html> <head>...</head> <body> <div id = "view1" class = "view">page1</div> <div id = "view2" class = "view">page2</div> </body> </html>
.view{
display: none;
}
.view.active{
display: block;
}
var find = function(selector){
return document.querySelector(selector);
};
find(".view.active").classList.remove("active");
find("#view2.view").classList.add("active");
這可能是最簡單的單頁應用了。
和其它框架相比,View.js為單頁應用開發提供了的以下幾個關鍵特性彰顯了它的比較優勢:
無需配置和開發,視圖導航開箱可用
允許在視圖切換時傳遞任意類型的參數
允許自定義視圖切換動畫
允許自定義視圖配置
以事件驅動地形式完成視圖功能的開發
View.js是為了簡化移動端單頁應用的功能開發而創建的,web前端開發者可以繼續沿用既有技術棧,不會因為使用view.js而面臨較大的沖擊。
需要注意的是,和vue不同,對於使用View.js完成的單頁應用,其HTML文檔仍然由HTML、CSS和JS組成。開發者一如既往地需要手動建立html、css和js文件,並手動完成資源的引用。因為View.js的舞台,是瀏覽器裝載文檔之后的運行時環境。
視圖導航
視圖導航,在視圖切換時由View.js自動完成。下面是一個例子
/* 切換至商品詳情視圖 */
View.navTo("goods-detail", {
options: {
goodsId: "G01"
}
});
視圖切換后,頁面URL將自動變更為:http://domain:port/context/index.html#goods-detail!goodsId=G01。
View.js當前僅支持hash形式的地址表示。
視圖傳參
View.js允許以視圖為單位拆分任務,執行多人協作。視圖之間使用參數完成協作。參數在進行視圖切換時傳遞,如下所示:
View.navTo("goods-detail", {
options: {/* 使用options傳遞的參數將反饋到地址欄中,因此只能傳遞字符串類型的參數 */
goodsId: "G01"
}
});
/* ---------------------------------- */
View.navTo("delivery-address-list", {
params: {/* 使用params傳遞的參數不會反饋到地址欄中,因此可以是任意被瀏覽器所支持的類型 */
selectCallback: function(selectedAddress){
//...
}
}
});
/* ---------------------------------- */
View.navTo("goods-detail", {
params: {
goodsId: "G01",
},
options: {
goodsId: "G02"
}
});
var view = View.ofId("goods-detail");
view.on("enter", function(){
var goodsId = view.getParameter("goodsId");// --> G01
goodsId = View.getActiveViewOption("goodsId");// --> G02
goodsId = view.seekParameter("goodsId");// --> G01
});
視圖配置
多數情況下,一個視圖的表現和行為是固定的一種。但對於軟件提供商,其同一產品在被多個客戶購買時,會遇到“不同客戶有不同需求,拒絕需求沒收入,答應需求成本高”的窘境。而不同需求的差異點通常也並不高,可能也就只有10-30%左右的差別。但因為10%的差別,就要把源碼硬拷貝2份,對於軟件提供商而言,成本無疑高了許多。
View.js考慮到了這一點。
通過引入視圖配置,開發者可以將視圖開發為多種形態的綜合體,最終以視圖配置的方式指定視圖的具體工作模式或表現形式。如下所示:
var view = View.ofId("register");
/* 默認配置:密碼最少位數 */
view.config.get("password-min-length").setValue(6);
/* 默認配置:密碼最多位數 */
view.config.get("password-max-length").setValue(20);
/* -------------------------------------------- */
view.find(".submit").addEventListener("click", function(){
var pwd = pwdObj.value.trim();
var minLen = view.config.get("password-min-length").getValue(),
maxLen = view.config.get("password-max-length").getValue();
if(pwd.length < min){
alert("密碼長度不能少於" + minLen + "位");
return;
}
if(pwd.length > max){
alert("密碼長度不能多於" + maxLen + "位");
return;
}
});
/* -------------------------------------------- */
/* 客戶A的視圖配置 */
/* 重載既有配置:密碼最少位數 */
view.config.get("password-min-length").setValue(10, true);/* 第二個參數用於復寫可能已經存在的值,如果不傳且已經有值,則賦值無效,相當於什么也沒做 */
/* 重載默認配置:密碼最多位數 */
view.config.get("password-max-length").setValue(20, true);
/* -------------------------------------------- */
/* 客戶B的視圖配置 */
/* 重載既有配置:密碼最少位數 */
view.config.get("password-min-length").setValue(4, true);
/* 重載默認配置:密碼最多位數 */
view.config.get("password-max-length").setValue(10, true);
事件驅動
開發者通過監聽視圖的相關事件來決定執行特定操作的時機。View.js為每個視圖實例預制了如下幾個事件:
ready - 視圖就緒,在視圖第一次進入時觸發;
beforeenter - 視圖即將進入
enter - 視圖進入
afterenter - 視圖進入后
leave - 視圖離開
除此之外,開發者還可以根據自己的業務需要,自行發起並消費事件,如下所示:
var view = View.ofId("myView");
view.on("myevent", function(e){
view.logger.debug("Event name: {}, event data: {}", e.name, e.data);
});
//…
view.fire("myevent", {a: 1});//-> 0918 10:20:54 [View#myView]: Event name: null, event data: {"a":1}
