背景
習慣了這樣的寫法了,上來先來一個背景,交待一下事情的起因。事情的起因很簡單,用慣了mvc框架,想來一發前后端完全分離的框架試試。選用的人員和技術是這樣子的,讓原本做java的web開發的人員使用vue,在visual studio code里面寫純前端的代碼,然后由.net的同事,提示webapi2的接口。關於這個設計中的權限驗證等問題,會單獨一篇筆記進行介紹。
這里要說的是,由於前后端分離,導致沒有了后台的java模板或者.net的razor之類的視圖引擎。沒有了這種東西會很尷尬,因為需要用ajax來獲取數據,獲取到數據之后呢,用jquery的選擇器選擇dom然后一個個填充,提交的時候再用jquery的選擇器選擇dom取其值——。這樣子的話,估計我要被同事們罵死……。為了鄰里和諧,我覺得vue比較流行,而且它的mvvm據說速度不錯,試用了一下,覺得簡單方便條條框框少,畢竟我只是要用它的mvvm功能,只是為了把對象與dom綁定,把事件相綁定。
單面(SPA) vs 多頁
這個是我比較頭疼的問題,其實個人比較傾向單面應用,因為直觀上覺得雖然第一次要加載的東西比較多,但是,由於瀏覽器有緩存以及做好載入界面,用戶其實是容易接受的。而多頁面每次都要加載許多東西,雖然也有緩存,但是許多對象都需要初始化,直覺上就知道總的性能不如單頁應用。然后我就開始搭建vue的spa了,用了vue的webpack模板,搭建出來的項目如下:
由於使用的工具是vscode,所以,輸入命令,調用bower,npm等還是比較爽的,而且可以直接開發了。但是,我發現,我想使用的是一個開源的基於bootstrap的后台管理系統模板,這個模板相互依賴特別多,我理了半天,沒理清楚,更別說把它做成vue的組件化了。沒過多久,我就放棄了這條我其實比較喜歡的路。
放棄了spa,選擇了多頁,但是,多頁又帶來了另外一個問題,就是是用iframe將菜單、導航等獨立在外以便共用,還是每個頁面都帶一個菜單、導航。
iframe VS 純多頁
公司的項目一直都是在使用iframe,但是,這次的項目有個明確的要求,就是要自適應布局,要能在手機上無縫轉換,這個,就是我很不放心iframe,我試着將iframe放在bootstrap自適應的布局中,確實也可以很好的進行工作,但是,總覺得有一天它無故導致出現滾動條,無故導致某些東西展示不全。同時,它還有一個致命的問題,就是模態彈窗只能遮住iframe,而非整個瀏覽器頁面,這就很頭疼。這樣用戶的操作流程就是開放性的了,很難摸清楚用戶的實際操作流程,會導致什么意外的情況發生。
所以,最后,只能用純多頁的了。
純多頁的前端
純多頁其實也存在一個問題,就是上面所說的,共用區域在每個頁面里面都要寫一次,其實,頭部導航、左邊菜單,還是很煩的,加上沒有后台幫助渲染,前端的代碼少不了。所以,我自己寫了一個方法,用來將其它的html頁面加載至當前界面的當前位置,其實類似於include。
function HtmlInclude(url) {
var req = false;
// Safari, Firefox, 及其他非微軟瀏覽器
if (window.XMLHttpRequest) {
try {
req = new XMLHttpRequest();
} catch (e) {
req = false;
}
} else if (window.ActiveXObject) {
// For Internet Explorer on Windows
try {
req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
req = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
req = false;
}
}
}
if (req) {
// 同步請求,等待收到全部內容
req.open('GET', url, false);
req.send(null);
document.write(req.responseText);
} else {
document.write("對不起,你的瀏覽器不支持" +
"XMLHTTPRequest 對象。這個網頁的顯示要求" +
"Internet Explorer 5 以上版本, " +
"或 Firefox 或 Safari 瀏覽器,也可能會有其他可兼容的瀏覽器存在。");
}
}
調用的方法如下:
這樣,在
<script>
HtmlInclude("snip/menu_left.html");
</script>
的位置,最終就會變成"snip/menu_left.html"中的代碼,簡單完美!但是,在后面的調試過程中發現,瀏覽器中根本無法調試"snip/menu_left.html"中的代碼,這就很尷尬了~~~
vue組件的劍走偏鋒
vue的組件化提供了相當牛逼的特性,但是,對於單文件的支持非常地不行,只能在webpack等“編譯”功能的前提下,才可以使用.vue文件之類的組件單文件模式。但是,公司內部其實連html,css,javascript是非常模糊,讓一下子躍過html,css,js直接去用webpack編譯,估計不僅調試起來讓人崩潰,甚至連開始都開始不了。所以,咱們還是從實際出發,以html為骨骼,以css為皮肉, 以javascript為筋脈。
查閱了一下,vue提供了另外兩個模式的方式,其一是內聯模板,這種內聯模板其實是讓組件的調用者給予組件的template內容,這相當於在每個頁面里面都要把對應的組件的模板寫一遍,與我們的需求不符。其二便是X-Templates,這個東西與我們需要的功能類似。它將template內容單獨寫成html格式的js文件,然后可以通過<script type='text/x-template' src='' id''>去加載,在之后再加載與之對應的組件js文件,並在組件的template處寫上面那個x-template標簽中的id。這下又尷尬了,每個組件的引用必須引用兩個文件,而且還分先后,並且,引用模板的js文件時,需要特殊指定type,同時,因為是js文件,編輯器對html提示功能就瞎了。所以,vue內置的這兩種模式並不適合我。
我的方案
可能是經歷的原因,我覺得,我的任何項目里面都要有jquery,雖然vue提供了ajax的請求插件,但是,我依然覺得有必須引用一下jquery,有了它,我才有安全感,客戶的各種奇葩需求,我心中才有底,不然今天動畫,明天校驗的,我能給愁死。
於是,我做了另外一個打算,既然
Vue.component('my-component', {
template: ""
});
我給template這個對象字符串,而我又想給它的是html頁面,那么我用jquery請求就是嘍,如下:
Vue.component('my-component', {
template: $.getSync("templates/com1.html")
});
這樣子的話,我只需要在templates文件夾中增加這個com1.html,供vue使用即可。這個$.getSync是我實現的一個jquery的擴展方法,因為jquery的同步請求只有$.ajax中才有,而且還是要通過回調,$.get方法是異步的,除非設置全局同步,全局同步會影響其它的功能代碼,所以,萬船無奈自己用$.ajax封裝了一個$.getSync方法。
jQuery.extend({
getSync:function(url){
var result=null;
$.ajax({
url:url,
async:false,
success:function(data){
result=data;
}
});
return result;
}
});