單頁應用SPA開發最佳實踐

最近用vue+vue-router作了個單頁應用的項目,頁面大概有15個左右。積累了一些開發經驗在此作一些記錄.本文主要從可維護性方面來考慮SPA的開發實踐css

全站的顏色定義放在一個less或者scss的文件裏,其餘組件和頁面import這個配置來引用顏色。

示例代碼: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

vue,vue-router單獨抽出來,用script標籤引入

bad case

npm install vue
npm install vue-router
//js
import Vue from 'vue'
import VueRouter from 'vue-router'

good case

<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事件。

詳見連接使用自定義事件的表單輸入組件

5. 優雅解決ios的fixed問題

ios的fixed問題由來已久,在單頁應用中咱們免不了須要處理這樣的bug。如何優雅解決這個問題

如圖:TB1H4VrdgMPMeJjy1XbXXcwxVXa-628-1052.jpg這是一個經典的移動端佈局。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方法裏觸發事件。

6.如何拉起其餘app

webapp拉起其餘native app是常見的場景,一般咱們都經過scheme來拉起其餘app

不過在ios中偶爾會遇到這個拉起的動做偶爾會被一些web容器記錄在history裏。爲了處理這個狀況一般在ios裏面咱們都是創建一個iframe的元素而後把iframe的src指向這個schema,而後把iframe插入dom,在延時刪除這個元素。這樣history裏就不會有這個記錄了。不過此方法對安卓無效。


同步更新在個人我的博客https://www.56way.com/p/108.html

相關文章
相關標籤/搜索