最近用vue+vue-router作了個單頁應用的項目,頁面大概有15個左右。積累了一些開發經驗在此作一些記錄.本文主要從可維護性方面來考慮SPA的開發實踐css
示例代碼:define.scsshtml
$bgColor: #fff; $color:#619eee; $fontColor:#333333; $fontColor01:#A5A5A5; $fontColor02:#4a4a4a; $fontColor03:#448CFF; $color300:#ed5630; $color3001:#fbfbfb; $accpetColor:#2fbe27; $refusedColor: #de0101; $hrefColor:#4a90e2; $redColor:#ff4c4c;
好處:vue
方便維護整站的色彩風格,後續遇到VI升級改版等,你就偷着樂吧。ios
npm install vue npm install vue-router //js import Vue from 'vue' import VueRouter from 'vue-router'
<script src="/path/to/vue.js"></script> <script src="/path/to/vue-router.js"></script>
或者web
<script src="https://g.alicdn.com/cn-yz/bmw/0.2.5/vendor/vue??2.2.0.js,vue-router.min.js「></script>
好處:vue-router
import過來的js會和你的業務代碼打包在一塊兒。無謂的增長代碼的體積,並且vue這類基礎包的更新頻率是低於業務代碼的。單拆出來加載有利於瀏覽器緩存npm
拆出來的會比import在一塊兒的體積減少30k左右api
ex:瀏覽器
//myTool.js function get(param){ $.get(param); } function post(param){ $.post(param) }
你可能會質疑。。這樣有什麼用緩存
1.當你的應用跑在在多個容器的場景,好比手淘,他有個mtop的請求模式(一種接口調用方式),好比還須要跑在釘釘裏面。你只須要在裏判斷一下容器環境就能夠區分對應的api調用方式
ex:
function get(param) { switch (container) { case "taobao": mtop.request(param); break; case "web": $.get(param) break; case "weixin": //balabala break; default: break; } }
2.當你遇到csrf攻擊須要給每一個請求添加token。若是你不知道什麼是csrf,請點擊這裏
3.你能夠在這裏給每一個請求添加一個loading模態框,免去每一個方法調用前本身添加的煩惱
ex:
function get(param){ var show = param.showloading===undefined?true:param.showloading; if(show){ $.showPreloader(); } $.get(param); }
4.v-model與v-on:input的坑
ex:vue 2.2.0+
<input type="text" v-model="a" v-on:input="myInput"/> <script> function myInput(){ this.a = "abc"; } </script>
當你在myInput方法裏作一些操做,好比校驗輸入值,你會發現數據並無更新到對應的input,這是由於v-model也監聽了輸入框的input事件
解決辦法:綁定value值,js更新value
<input type="text" :value="a" v-on:input="myInput"/> <script> function myInput(){ var formattedValue = "abc"; this.a = formattedValue; this.$refs.input.value = formattedValue this.$emit('input', Number(formattedValue)) } </script>
對於中文:v-model也不是很適用
對於要求 IME (如中文、 日語、 韓語等) (IME意爲’輸入法’)的語言,你會發現v-model不會在 ime 輸入中獲得更新。若是你也想實現更新,請使用 input事件。
詳見連接使用自定義事件的表單輸入組件
ios的fixed問題由來已久,在單頁應用中咱們免不了須要處理這樣的bug。如何優雅解決這個問題
如圖:這是一個經典的移動端佈局。header和footer相對於瀏覽器固定,body高度可變。
這樣的佈局單獨一個頁面沒什麼難度。不過當你把footer設爲fixed的時候會在ios上看到奇異的效果。
當單頁應用裏有不少個這樣的頁面,並且header的高度也不是固定的時候,你就會發現每一個頁面都須要搞定body的高度css仍是有點繁瑣的。。
有沒有一個優雅的方式來作這個事情。讓代碼可維護性更好。
這個佈局的難點在於如何搞定body在不一樣機型上的高度。若是用純css來作,可能須要用到calc,或者boder等之類的,並且針對每一個頁面不header不一樣,須要從新計算body的高度。
雖然咱們在佈局方面不推薦使用js來處理,不過在是個時候是使用js處理body的高度的時候了。
步驟:
咱們須要獲取容器的高度。
var w_height = $(window).height();
獲取header和footer的等fixed元素的高度
這裏咱們能夠給須要fixed的元素加個自定義屬性
fixed-box="true"
<div class="header" fixed-box="true"></div> <div class="body " fixed-box="scroll"> //balabalaba </div> <div class="footer" fixed-box="true"></div>
在每一個頁面被路由到加載的時候mounted觸發一個事件,告知js須要計算處理body高度
mounted: function() { _body.trigger("mounted"); },
在main.js等入口函數裏監聽這個事件處理相關邏輯
jWin.on("mounted", function () { //元素加載後計算可滾動元素的區域寬度 var height = 0; $("[fixed-box='true']").each(function () { height = height + $(this).height(); }); var h = w_height - height; $('[fixed-box="scroll"]').height(h); });
這樣整個頁面的佈局均可以在這個js裏處理,後續新增頁面只須要作兩個事情:
1.給頁面加fixed屬性。 2.在mounted方法裏觸發事件。
webapp拉起其餘native app是常見的場景,一般咱們都經過scheme來拉起其餘app
不過在ios中偶爾會遇到這個拉起的動做偶爾會被一些web容器記錄在history裏。爲了處理這個狀況一般在ios裏面咱們都是創建一個iframe的元素而後把iframe的src指向這個schema,而後把iframe插入dom,在延時刪除這個元素。這樣history裏就不會有這個記錄了。不過此方法對安卓無效。