開發(fā)那點事(八)基于VUE框架封裝一些工作常用的功能

開發(fā)背景
來北京工作已經(jīng)一年多了绽榛,大大小小的項目也寫了不少灭美,磕磕碰碰到了現(xiàn)在铁坎,記錄一下

功能要點

  • 1 公共網(wǎng)絡(luò)請求封裝
  • 2 自定義dialog
  • 3 base組件封裝
  • 4 多環(huán)境打包優(yōu)化
  • 5 路由按需加載梯捕,gzip開啟
  • 6 骨架屏功能實現(xiàn)

上干貨

1 公共網(wǎng)絡(luò)請求封裝
這個功能其實在以前的文章中就有說到過傀顾,核心就是抽取接口地址的前綴短曾,根據(jù)后臺返回的接口內(nèi)容嫉拐,進(jìn)行統(tǒng)一的出來(彈對話框婉徘,執(zhí)行回調(diào))

需要注意的地方就是多個網(wǎng)絡(luò)時儒鹿,多個遮罩層的處理方式

這個不多說几晤,直接上代碼(基于axios)

//開始加載動畫效果
function startNetWork(msgText) {
  //修復(fù)多接口訪問無法關(guān)閉浮層BUG
  if (document.body.contains(loadDialog)) {
    document.body.removeChild(loadDialog);
  }
  loadDialog = document.createElement('div');
  loadDialog.className = 'popContainer';
  let loadImage = document.createElement('img');
  loadImage.src = 'static/img/load.svg';
  let loadMsg = document.createElement('label');
  loadMsg.innerText = msgText ? msgText : '加載中...';
  loadDialog.appendChild(loadImage);
  loadDialog.appendChild(loadMsg);
  document.body.appendChild(loadDialog)
}

//關(guān)閉加載動畫效果
function stopNetWork() {
  //修復(fù)多接口訪問無法關(guān)閉浮層BUG
  if (document.body.contains(loadDialog)) {
    document.body.removeChild(loadDialog);
  }
}

// get網(wǎng)絡(luò)請求
function get(networkParam, data, vueObj, successCallback, errorCallback) {
  let realUrl = preUrl + networkParam.url;
  if (networkParam.showLoading) {
    startNetWork();
  }
  let token = getUserData('token');
  if (!token) {
    // 跳轉(zhuǎn)回登錄頁
    vueObj.$router.push({path: '/'})
  }
  axios.get(realUrl, {
    params: data,
    headers: {
      token: token
    }
  }).then(function (response) {
    stopNetWork();
    console.log(response);
    successCallback(vueObj, response.data)
  }).catch(function (response) {
    console.log(response, 'get axios');
    stopNetWork();
    errorCallback(vueObj, response);

  })
}

2 自定義Toast

這個功能的原理跟網(wǎng)絡(luò)請求時的動畫比較相似圾浅,通過js動態(tài)生成div喷鸽,拼接到本頁body標(biāo)簽下,然后通過定時器移除div魁衙,達(dá)到Toast的效果

let info = {
  background: 'black',
  color: 'white',
  width: '80%',
  content: '輸出內(nèi)容',
  borderRadius: '10px',
  duration: 2000
};

// toast相關(guān)配置見上方
function toast(toastInfo) {
  let duration = 800;
  let m = document.createElement('div');
  let color = toastInfo.color ? toastInfo.color : info.color;
  let width = toastInfo.width ? toastInfo.width : info.width;
  let background = toastInfo.background ? toastInfo.background : info.background;
  let borderRadius = toastInfo.borderRadius ? toastInfo.borderRadius : info.borderRadius;
  m.innerHTML = toastInfo.content ? toastInfo.content : info.content;
  m.style.cssText = "width: " + width + ";min-width: 150px;opacity: 1;height: 30px;color: " +
    color + ";line-height: 30px;text-align: center;border-radius: " + borderRadius + ";position: fixed;top: 40%;left: 10%;z-index: 999999;background: " + background + ";font-size: 16px;";
  document.body.appendChild(m);
  setTimeout(function () {
    let d = 0.5;
    m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
    m.style.opacity = '0';
    setTimeout(function () {
      document.body.removeChild(m)
    }, d * 1000);
  }, duration);
}

3 base組件封裝
這個基vue存在的目的是為了解耦纯蛾,項目中所有的頁面文件不直接操作封裝好的網(wǎng)絡(luò)請求翻诉,等一些常用的util,而且通過這個基vue間接的操作碰煌,base起到了一個橋梁的作用芦圾,使得代碼更加的規(guī)范

export default {
  name: "base",
  data() {
    return {
      toastInfo: {
        background: "red",
        color: "white",
        width: "80%",
        content: "ce",
        borderRadius: "20px",
        duration: 500
      }
    };
  },
  methods: {
    // 設(shè)置遮罩層
    setShade(msgText) {
      showShade(msgText);
    },
    testLoading() {
      startNetWork();
    },
    // 設(shè)置對話框背景顏色
    setToastBackGroud(color) {
      this.toastInfo.background = color;
    },
    // 設(shè)置對話框邊框圓角 radiusPx 單位px
    setToastBorderRadius(radiusPx) {
      this.toastInfo.borderRadius = radiusPx;
    },
    //  彈出對話框 conten 彈出內(nèi)容
    showToast(content) {
      this.toastInfo.content = content;
      toast(this.toastInfo);
    },
    //帶動畫效果的GET請求
    get(params, data, vueObj, successCallback, errorCallback) {
      let networkParam = {
        url: "",
        showLoading: true
      };
      if (typeof params == "string") {
        networkParam.url = params;
      } else {
        networkParam = params;
      }
      get(
        networkParam,
        data,
        vueObj,
        function(_this, data) {
          if (data.status == -1) {
            localStorage.clear();
            _this.muiTost(data.msg);
            _this.$router.push({
              path: "/"
            });
          }
          if (data.data != undefined && data.data != null) {
            successCallback(_this, data);
          } else {
            _this.showToast("未知錯誤");
          }
        },
        function(_this, response) {
          console.log("errorCallback");
          if (response.response) {
            errorCallback(_this, response.response.data);
            return;
          }
          _this.showToast("未知錯誤");
        }
      );
    },
    //帶動畫效果的POST請求

    post(params, data, vueObj, successCallback, errorCallback) {
      let networkParam = {
        url: "",
        showLoading: true
      };
      if (typeof params == "string") {
        networkParam.url = params;
      } else {
        networkParam = params;
      }
      post(
        networkParam,
        data,
        vueObj,
        function(_this, data) {
          if (data.status == undefined || data.status == null) {
            _this.showToast("未知錯誤");
          } else if (data.status == 0 && successCallback != undefined) {
            successCallback(_this, data);
          } else if (data.status == -1) {
            localStorage.clear();
            _this.muiTost(data.msg);
            _this.$router.push({
              path: "/"
            });
          } else {
            _this.showToast(data.msg);
          }
        },
        function(_this, response) {
          console.log("errorCallback");
          if (response.response) {
            errorCallback(_this, response.response.data);
            return;
          }
          _this.showToast("未知錯誤");
        }
      );
    }
  }
};

//其他vue通過extends來繼承base
 import base from '../page/base';
 export default {
        extends: base,
        name: "Login"
}

4 多環(huán)境打包優(yōu)化
由于公司上線流程比較規(guī)范夜焦,有將項目部署到多個環(huán)境的需求,所以將抽象出一個build.js文件來設(shè)置環(huán)境名巷波。

// test test環(huán)境
// dev dev環(huán)境
// pre 預(yù)發(fā)布環(huán)境
// prod 生產(chǎn)環(huán)境
const buildTip = 'test';
module.exports.buildTip = buildTip;//將變量拋出抹镊,在路由文件以及打包文件等引入

其中路由文件以及打包文件中的相關(guān)配置是需要同步的
router/index.js

import Vue from 'vue'
import Router from 'vue-router'
import {buildTip} from "../util/build";

//適配多種環(huán)境打包
let base;
switch (buildTip) {
  case "test":
    base = '/demo/';
    break;
  case "dev":
    base = '/demo/';
    break;
  case "pre":
    base = '/demo/';
    break;
  case "prod":
    base = '/demo/';
    break;
}
Vue.use(Router);

export default new Router({
  base: base,//將變量設(shè)置給base
  mode: 'history',
  routes: [
   
  ]
})

config/index.js

const build = require("../src/util/build");//引入build.js中的環(huán)境名稱
let indexDirName, assetsRoot, assetsPublicPath;
//適配多版本打包發(fā)布
switch (build.buildTip) {
  case "test":
    indexDirName = '../demo/index.html';
    assetsRoot = '../demo/';
    assetsPublicPath = '/demo/';
    break;
  case "dev":
    indexDirName = '../demo/index.html';
    assetsRoot = '../demo/';
    assetsPublicPath = '/demo/';
    break;
  case "pre":
    indexDirName = '../demo/index.html';
    assetsRoot = '../demo/';
    assetsPublicPath = '/demo/';
    break;
  case "prod":
    indexDirName = '../demo/index.html';
    assetsRoot = '../demo/';
    assetsPublicPath = '/demo/';
    break;
}
  build: {
    // Template for index.html
    index: path.resolve(__dirname, indexDirName), //對應(yīng)以上的三個變量

    // Paths
    assetsRoot: path.resolve(__dirname, assetsRoot),//對應(yīng)以上的三個變量
    assetsSubDirectory: 'static',
    assetsPublicPath: assetsPublicPath,//對應(yīng)以上的三個變量

    /**
     * Source Maps
     */

    productionSourceMap: false,
    // https://webpack.js.org/configuration/devtool/#production
    devtool: '#source-map',

    // Gzip off by default as many popular static hosts such as
    // Surge or Netlify already gzip all static assets for you.
    // Before setting to `true`, make sure to:
    // npm install --save-dev compression-webpack-plugin
    productionGzip: true,//同時需要在nginx服務(wù)器做出gzip配置
    productionGzipExtensions: ['js', 'css'],

    // Run the build command with an extra argument to
    // View the bundle analyzer report after build finishes:
    // `npm run build --report`
    // Set to `true` or `false` to always turn it on or off
    bundleAnalyzerReport: process.env.npm_config_report
  }

5 路由按需加載氨菇,gzip開啟
這個方面的作用是為了提高頁面訪問速度查蓉,屬于性能優(yōu)化

 routes: [
    {
      path: '/',
      name: 'home',
      component: function (resolve) {
        require(['../page/home'], resolve)//路由按需加載
      }
    }
    , {
      path: '/scroller',
      name: 'scroller',
      component: function (resolve) {
        require(['../page/scroller'], resolve)
      }
    }
  ]

至于gzip,起初以為前端配置就可以了乌询,到最后才發(fā)現(xiàn)還需要服務(wù)端nginx的配合

  productionGzip: true,//將false改為true,同時需要在nginx服務(wù)器做出gzip配置   
  productionGzipExtensions: ['js', 'css'],

nginx配置

    gzip  on;   #開啟gzip
    gzip_min_length 1k; #低于1kb的資源不壓縮
    gzip_comp_level 5; #壓縮級別【1-9】,越大壓縮率越高豌研,同時消耗cpu資源也越多妹田,建議設(shè)置在4左右。
    gzip_types text/plain application/javascript application/x-javascript text/javascript text/xml text/css; 
    gzip_disable "MSIE [1-6]\.";  #配置禁用gzip條件鹃共,支持正則鬼佣。此處表示ie6及以下不啟用gzip(因為ie低版本不支持)
    gzip_vary on;  #是否添加“Vary: Accept-Encoding”響應(yīng)頭

6 骨架屏功能實現(xiàn)
骨架屏,在用戶體驗方面的作用比較大霜浴,實現(xiàn)起來并不難晶衷,自定義組件+v-if就可以實現(xiàn)該功能了
具體實現(xiàn)如下

<template>
  <div class="container login column-center">
    <Skeleton v-if="!init"></Skeleton>

    <button @click="changeToastBackground">將對話框顏色改為紅色</button>
    <button @click="toast">測試Toast對話框</button>
    <button @click="testGet">測試Get請求</button>
    <button @click="testPost">測試Post請求</button>
    <button @click="testLoading">測試Loading</button>
    <button @click="testShade">測試遮罩</button>
    
  </div>
</template>

<script>
    import base from '../page/base';
    import Skeleton from "../personView/Skeleton"; //引入組件

    export default {
        extends: base,
        name: "Login",
        components: {
            Skeleton
        },
        data() {
            return {
                init: false//設(shè)置相關(guān)變量
            }
        },
        mounted() {
            let that = this;
            //模擬請求操作
            setTimeout(function () {
                that.init = true;
            }, 2000)
        },
        methods: {
            toast() {
                this.showToast('修改成功');
            },
            testShade() {
                this.setShade('測試')
            },
            testGet() {
                this.get('User/detail', {}, this, function (that, data) {
                        console.log(data)
                    },
                    function (that, data) {
                        console.log(data);
                        if (!isNaN(data.responseCode)) {
                            that.showToast(data.responseMessage)
                        }
                    }
                )
            },
            testPost() {
                this.post('User/detail', {test: '1231'}, this, function (that, data) {

                }, function (that, data) {
                    if (!isNaN(data.responseCode)) {
                        that.showToast(data.responseMessage)
                    }
                })
            },
            changeToastBackground() {
                this.setToastBackGroud('red')
            }
        }

    }
</script>

<style scoped>
  .login button {
    border: 0;
    padding: 0;
    margin-top: 10px;
    height: 40px;
    width: 80%;
    background-color: black;
    color: white;
    border-radius: 20px;
  }
</style>

最后
附上封裝的demo地址,其中還有自己實現(xiàn)的上拉加載搜索功能阴孟,需要的可以下載來看看
下載地址

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末慕嚷,一起剝皮案震驚了整個濱河市砂心,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異灶体,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門殖妇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事舰绘∏芈” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我腌闯,道長,這世上最難降的妖魔是什么分瘦? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上鬼雀,老公的妹妹穿的比我還像新娘励烦。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布句灌。 她就那樣靜靜地躺著藐窄,像睡著了一般撤缴。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天棺耍,我揣著相機(jī)與錄音嫩挤,去河邊找鬼狠怨。 笑死憎蛤,一個胖子當(dāng)著我的面吹牛碾盟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了磁椒?” 一聲冷哼從身側(cè)響起慎皱,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎万细,沒想到半個月后弓千,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體姻政,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年帽揪,在試婚紗的時候發(fā)現(xiàn)自己被綠了蔗崎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笔刹。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出实蔽,到底是詐尸還是另有隱情拨脉,我是刑警寧澤箕昭,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布桨武,位于F島的核電站,受9級特大地震影響煌往,放射性物質(zhì)發(fā)生泄漏却邓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望锁保。 院中可真熱鬧做葵,春花似錦怎燥、人聲如沸瘫筐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坦康。三九已至,卻和暖如春惹恃,著一層夾襖步出監(jiān)牢的瞬間颊乘,已是汗流浹背负蚊。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留乍楚,地道東北人当编。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像徒溪,于是被迫代替她去往敵國和親忿偷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 概要 64學(xué)時 3.5學(xué)分 章節(jié)安排 電子商務(wù)網(wǎng)站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,208評論 0 3
  • 1 我的大學(xué)生活之大學(xué)英語學(xué)習(xí) 1) 在這個學(xué)期的大學(xué)英語學(xué)習(xí)中臊泌,我的GPS [Gains]:提升了口語能力和聽力...
    旅一46朱趙筱楠閱讀 242評論 0 0
  • 記得我曾經(jīng)想試圖提高自己的注意力鲤桥,那會我自己閉上眼睛然后心里默念數(shù)字,各種數(shù)字隨之外腦海里浮現(xiàn)渠概,不知道那種感覺是不...
    D023黎閱讀 207評論 0 1
  • 五六月正是吃龍蝦的季節(jié)茶凳,外公外婆還有爸爸媽媽帶著懂仔去新余鄉(xiāng)下找到一個地方去釣龍蝦。 現(xiàn)在吃龍蝦的人多,野生的已經(jīng)...
    敦厚新哥閱讀 439評論 2 1
  • 牧人慧妄、(齊井山)顷牌、蒙古族、號戲墨堂主塞淹、遼西牧人、先后就學(xué)于魯迅美術(shù)學(xué)院美術(shù)教育專業(yè)罪裹、遼寧教育學(xué)院國畫專業(yè)饱普、沈陽師范...
    崔英閣工筆重彩新媒體閱讀 2,901評論 0 3