如何優化我們的程式碼(vue專案)

qiugu發表於2019-04-07

前言

作為一個前端,可能絕大多數的時間都是在寫的業務程式碼,時間一長,大家會覺得乏味、沒意思等等,但是其實就算只是寫業務程式碼,我們也依然能夠找到有興趣的點,說的簡單一點就是程式碼優化,不僅僅侷限在業務邏輯這塊,像是程式碼複用、效率等等都是我們可以加以改進的地方,學會在業務程式碼中找到不足,總結經驗,這樣日積月累,量變產生質變,必然我們的技術也是不斷再上升的。今天其實就是說下我自己在vue專案中進行的一些總結或者是經驗,如果有錯誤的地方也是歡迎大家指正。

1.相容IE11

用過vue的同學們應該都比較清楚,vue其實是可以相容ie9的,但是這種相容並不是說,你寫了一個專案,開啟ie9就能相容了,是需要用工具將程式碼進行轉換的。我之前也是這樣以為的,直到近期一個專案完成之後,開啟ie11,發現頁面顯示正常的,但是所有的http請求都是無效的,經過了一番查詢,才知道這個babel-polyfill的包的用處,當然知道的同學可以略過啦,不知道的話,跟著我繼續往下看

我們使用現代瀏覽器的話,很多像是es7、es8的語法,可能都是已經支援了,但是放在ie上,這些方法都是通通不認識的,因此我們就需要一個工具來將這些ie瀏覽器不認識的語法轉換成ie所認識的,那麼知道了這個babel的包,其實就很簡單了,我們直接這樣在vue中的main.js中引入這個包即可

import "babel-polyfill";
複製程式碼

但是這樣引入的話,在打包的時候,包可能會比較大,會影響到前端頁面的開啟速度,所以又出現了一種按需轉譯的用法,即當我們需要用到轉譯程式碼的時候,會替我們轉譯,並不是一次轉譯所有的程式碼,這種用法同學們應該也是非常熟悉了,就是所謂的“懶載入”,和vue的路由懶載入是一個道理,那麼如何使用呢,首先下載的是一個@babel/polyfill的包,這個包的話也是一個翻譯程式碼的作用,但是可以進行配置來實現按需載入

npm i @babel/polyfill -D
複製程式碼

然後我們需要在babel.config.js中進行按需載入的配置

presets: [
    '@vue/app',
    [
      '@babel/preset-env',
      {
        'useBuiltIns': 'entry'
      }
    ]
]
複製程式碼

注意這個@babel/preset-env是一個有關環境變數的包,這個包在你使用vue腳手架3.0建立專案時就會自帶這個包了,所以是不需要下載的,最後在main.js中引入我們之前下載的包就可以了。

import "@babel/polyfill";
複製程式碼

這樣就大功告成了,打包的話也可以看到打包體積變小了

如何優化我們的程式碼(vue專案)

如何優化我們的程式碼(vue專案)
對比可以看到體積小了20kb,但是問題來了,明顯在主包中檔案體積過大,已經1.5M了,這個體積頁面首次開啟的時候,可能會需要3-10秒的時間,使用者體驗肯定是極差的,所以下面我們也說到如何按需載入我們的元件,注意我們vue專案使用的是ant-design-vue的ui框架,所謂按需載入元件,就是我們專案中用到了這個元件才匯入這個元件,沒有用到的話,就不要將這個元件的內容打包進去,也包括元件的樣式。

2.按需打包元件

其實關於按需打包我們需要的元件,很多元件也介紹如何按需使用,ant-design-vue也提供了這些內容,想要詳細瞭解的同學可以點開連結檢視文件,這裡也是簡單說一下,首先需要下載babel-plugin-import的外掛,然後需要在babel.config.js中進行如下配置

plugins: [
    [
      "import",
      {libraryName: "ant-design-vue",libraryDirectory: "es",style: true}
    ]
  ]
複製程式碼

之後的話,我們就不能全域性引入元件了,而是引入我們專案中所用到的一些元件,可以將這些引入的元件單獨放入一個js檔案中,這樣方便以後新增元件

//index.js
import Vue from 'vue';
import {
    Button,
    Row,
    Col,
    Layout,
    Menu,
    Icon,
    Form,
    Tag,
    Input
} from 'ant-design-vue';

Vue.use(Button)
Vue.use(Row)
Vue.use(Col)
Vue.use(Layout)
Vue.use(Menu)
Vue.use(Icon)
Vue.use(Form)
Vue.use(Tag)
Vue.use(Input)
//也可以這樣寫,但是這樣寫比較麻煩
// Vue.component(Button.name,Button)
// Vue.component(Row.name,Row)
// Vue.component(Col.name,Col)
// Vue.component(Layout.name,Layout)
// Vue.component(Layout.Header.name,Layout.Header)
// Vue.component(Layout.Sider.name,Layout.Sider)
// Vue.component(Layout.Footer.name,Layout.Footer)
// Vue.component(Layout.Content.name,Layout.Content)
// Vue.component(Menu.name,Menu)
// Vue.component(Icon.name,Icon)
// Vue.component(Form.name,Form)
// Vue.component(Tag.name,Tag)
// Vue.component(Form.Item.name,Form.Item)
// Vue.component(Input.TextArea.name,Input.TextArea)
複製程式碼

然後我們再來打包看看此時的檔案大小

如何優化我們的程式碼(vue專案)
一下子少了近500kb,是不是好了很多呢,當然如果包體積還是比較大,這個時候我們可以考慮將一些依賴排除在打包當中,使用external的配置,這裡就不多說了,有興趣的同學可以自己試試。

3.自定義元件的v-model指令

說完了如果優化打包,我們再來看看如何提高我們的程式碼質量。v-model這個指令相信大家也都用過,它雙向繫結的機制是不是非常省事呢,如果我們自己要實現一個v-model繫結又該如何做呢,比如我們需要監聽某個富文字編輯器內容的變化,獲取內容以及儲存富文字的內容,這個時候就剛好用上自定義的v-model

<template>
  <div class="hello">
    <editor :id="id" :min-height="500" width="100%" :content="editor"
            @on-content-change="onContentChange"></editor>
  </div>
</template>

<script>
export default {
  name: 'kindeditor',
  model: {
    prop: 'editor',
    event: 'content-change'
  },
  props: {
    editor: String,
    id: String
  },
  data () {
    return {}
  }
  methods: {
    onContentChange (val) {
      this.$emit('content-change',val);
    }
  }
}
</script>
複製程式碼

其實關鍵就在model屬性上,定義了父元件傳過來的props,以及發生變化的事件名稱,需要注意的地方在於,當內容發生改變時,我們不能將改變後的值賦給props屬性,因為vue中預設是單向資料流,props的值只能是由父元件來改變,這樣的話,我們就能輕易的監聽這個富文字編輯器的值,而不用去用watch監聽或者是其他的方法來實現,這個實現的方法在vue的文件中也有提到,大家也可以去文件檢視詳情。

4.條件語句優化

在我們的專案中肯定是有無數的if條件語句的程式碼,如果條件巢狀不多的話,那沒什麼問題,如果巢狀過多過深,就會導致程式碼難以理解,維護困難,因此針對條件語句的優化也是勢在必行的,這裡也是參考了很多大佬們的文章,吸取他們的經驗,使用一些比較常用的方法來優化條件語句,比如錯誤優先處理return

this.form.validateFields((err,values) => {
     if (err) {
        this.$message.warning('驗證失敗,請重新輸入!');
        return;
     }
     let fileId = values.fileId.map(item => {
         return item.response.result
     });
     let params = Object.assign(values,{
        govUserId: sessionStorage.getItem('userId'),
        fileId: fileId.slice(-1)
     })
    this.resSubmit(params)
});
複製程式碼

這樣一個表單驗證的方法,當如果發生錯誤時,直接提示錯誤資訊,然後退出驗證,少了一個else的程式碼塊,程式碼更少一些,而且也很容易理解

另外比較常用的就是利用三目運算子,以及短路操作符“&&”和“||”,比如

this.panes.length > 1 && this.$store.commit('DELETE_TAB',key);
//或者是
this.panes.length > 1 ? this.$store.commit('DELETE_TAB',key) : '';
複製程式碼

除此還有上面文章中提到的更復雜的條件判斷,使用新的資料結構Map來進行判斷,而所有這些條件語句,都是我們程式碼當中需要優化的地方。

5.解構賦值以及函式預設值的應用

解構賦值是ES6當中的內容,現在ES10都已經出來了,如果ES6還沒有用上的話,那就顯得我們前端太low啦,當然這只是開個玩笑,不過ES6所帶來的解構賦值以及函式預設值都是能夠簡化我們的程式碼,使程式碼更容易理解,所以既然我們學習ES6了,那麼就必須要學以致用。

//給引數新增預設值,當引數為undefined的時候,則使用預設的引數值
async getData(currentPage = 0,pageSize = 10) {
    //將請求的結果賦值給一個物件,並且給物件中的每個屬性都取了一個名字,後面直接可以使用這個變數進行操作,而不需要用.語法
      let {response,username,timeToken,govUserId} = await this.$store.dispatch('getSign'),
      params = {
        sign: response.result.sign,
        username,
        timeToken,
        govUserId,
        currentPage,
        pageSize
      }
 }
複製程式碼

解構和函式預設值看起來好像比較複雜,但是用熟悉了以後,會發現少寫了很多程式碼,並且程式碼看起來也是一目瞭然,同時預設值還幫助我們省去了關於引數的判斷,是不是非常的方便的呢。

6.在vue中使用JSX

一直以來,我以為只有react中才能使用JSX,後來發現其實我們在vue中也能使用JSX,需要注意的是JSX在vue中和react中還是有一點區別的,這裡不會具體說這些區別,只是告訴大家,遇到一些複雜的元件,可以去嘗試使用JSX來寫,也是一種解決問題的方法

render () {
    return (
      <div class="apply_list">
        <a-table columns={this.columns}
          size="small" 
          dataSource={this.dataSource}
          pagination={this.pagination}
          loading={this.loading}
          rowKey={(record,index) => index}
          onChange={this.handleTableChange}
          locale={{emptyText: '暫無資料'}}
        >
        </a-table>
      </div>
    )
}
複製程式碼

JSX在vue中,是寫在render()鉤子中的,直接返回return一個JSX物件就可以了,網上也有關於vue中的JSX怎麼使用,大家可以去搜搜。

寫在最後

很久很久沒有寫部落格了,不只是因為工作忙的原因,還有自己懶的因素在裡面,人如果在舒適區待太久的話,總會慢慢去的磨滅了自己的初衷,自己的目標,因此也是希望通過寫部落格來提醒自己,不斷學習,不斷積累,技術是沒有任何捷徑可走,而我走的已經比別人慢了很多,所以還需要繼續努力丫。

最後上面提到的程式碼,都在我的github上面,最近工作關係使用ant-design-vue的ui框架,然後就漸漸喜歡了這個框架,感覺它更加靈活好用,並且設計也比較漂亮,大家可以對照這我的專案和官方的文件來進行學習喲。

相關文章