一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

vue . js 前端開發(fā)常見問題集錦

 就這樣了__ 2018-03-02

作者: 熊D01001

https://blog./JavaScript/VueJS-開發(fā)常見問題集錦/

由于公司的前端開始轉(zhuǎn)向 VueJS,最近開始使用這個框架進行開發(fā),遇到一些問題記錄下來,以備后用。 主要在一些 官方手冊 上沒有寫,但是實際開發(fā)中會遇到的問題,需要一定知識基礎。

涉及技術棧

  • CLI: Vue-CLI

  • UI: Element

  • HTML: Pug(Jade)

  • CSS: Less

  • JavaScriptES6

1. polyfill 與 transform-runtime

首先, vue-cli 為我們自動添加了 babel-plugin-transform-runtime 這個插件,該插件多數(shù)情況下都運作正常,可以轉(zhuǎn)換大部分 ES6 語法。 但是,存在如下兩個問題:

  1. 異步加載組件時,會產(chǎn)生 polyfill 代碼冗余

  2. 不支持對全局函數(shù)與實例方法的 polyfill

兩個問題的原因均歸因于 babel-plugin-transform-runtime 采用了沙箱機制來編譯我們的代碼(即:不修改宿主環(huán)境的內(nèi)置對象)。

由于異步組件最終會被編譯為一個單獨的文件,所以即使多個組件中使用了同一個新特性(例如: Object.keys()),那么在每個編譯后的文件中都會有一份該新特性的 polyfill 拷貝。如果項目較小可以考慮不使用異步加載,但是首屏的壓力會比較大。 不支持全局函數(shù)(如: PromiseSet、 Map), SetMap 這兩種數(shù)據(jù)結構應該大家用的也不多,影響較小。但是 Promise 影響可能就比較大了。 不支持實例方法(如: 'abc'.include('b')、 ['1','2','3'].find((n)=>n<2) 等等),這個限制幾乎廢掉了大部分字符串和一半左右數(shù)組的新特性。

一般情況下 babel-plugin-transform-runtime 能滿足大部分的需求,當不滿足需求時,推薦使用完整的 babel-polyfill

替換 babel-polyfill

首先,從項目中移除 babel-plugin-transform-runtime卸載該依賴:

  1. npm un babel-plugin-transform-runtime -D

修改 babel 配置文件

  1. // .babelrc

  2. {

  3.  //...

  4.  'plugins': [

  5.    // - 'transform-runtime'

  6.  ]

  7.  //...

  8. }

然后,安裝 babel-polyfill 依賴:

  1. npm i babel-polyfill -D

最后,在入口文件中導入

  1. // src/main.js

  2. import 'babel-polyfill'

2. ES6 import 引用問題

ES6 中,模塊系統(tǒng)的導入與導出采用的是引用導出與導入(非簡單數(shù)據(jù)類型),也就是說,如果在一個模塊中定義了一個對象并導出,在其他模塊中導入使用時,導入的其實是一個變量引用(指針),如果修改了對象中的屬性,會影響到其他模塊的使用。 通常情況下,系統(tǒng)體量不大時,我們可以使用 JSON.parse(JSON.stringify(str)) 簡單粗暴地來生成一個全新的深度拷貝的 數(shù)據(jù)對象。不過當組件較多、數(shù)據(jù)對象復用程度較高時,很明顯會產(chǎn)生性能問題,這時我們可以考慮使用 Immutable.js。

鑒于這個原因,進行復雜數(shù)據(jù)類型的導出時,需要注意多個組件導入同一個數(shù)據(jù)對象時修改數(shù)據(jù)后可能產(chǎn)生的問題。 此外,模塊定義變量或函數(shù)時即便使用 let 而不是 const,在導入使用時都會變成只讀,不能重新賦值,效果等同于用 const 聲明。

3. 在 Vue 中使用 Pug 與 Less

安裝依賴

  Vue 中使用 vue-loader 根據(jù) lang 屬性自動判斷所需要的 loader,所以不用額外配置 Loader,但是需要手動安裝相關依賴:

  1. npm i pug -D

  2. npm i less-loader -D

還是相當方便的,不用手動修改 webpack 的配置文件添加 loader 就可以使用了

使用 pug 還是 pug-loader? sass 兩種語法的 loader 如何設置? --- 請參考 預處理器 · vue-loader

使用

  1. <!-- xxx.vue -->

  2. <style lang='less'>

  3.  .action {

  4.    color: #ddd;

  5.      ul {

  6.        overflow: hidden;

  7.        li {

  8.          float: left;

  9.        }

  10.      }

  11.  }

  12. </style>

  13. <template lang='pug'>

  14.  .action(v-if='hasRight')

  15.    ul

  16.      li 編輯

  17.      li 刪除

  18. </template>

  19. <script>

  20.  export default {

  21.    data () {

  22.      return {

  23.        hasRight: true

  24.      }

  25.    }

  26.  }

  27. </script>

4. 定義全局函數(shù)或變量

許多時候我們需要定義一些全局函數(shù)或變量,來處理一些頻繁的操作(這里拿 AJAX 的異常處理舉例說明)。但是在 Vue 中,每一個單文件組件都有一個獨立的上下文( this)。通常在異常處理中,需要在視圖上有所體現(xiàn),這個時候我們就需要訪問 this 對象,但是全局函數(shù)的上下文通常是 window,這時候就需要一些特殊處理了。

簡單粗暴型

最簡單的方法就是直接在 window 對象上定義一個全局方法,在組件內(nèi)使用的時候用 bind、 callapply 來改變上下文。 定義一個全局異常處理方法:

  1. // errHandler.js

  2. window.errHandler = function () { // 不能使用箭頭函數(shù)

  3.  if (err.code && err.code !== 200) {

  4.    this.$store.commit('err', true)

  5.  } else {

  6.    // ...

  7.  }

  8. }

在入口文件中導入:

  1. // src/main.js

  2. import 'errHandler.js'

在組件中使用:

  1. // xxx.vue

  2. export default {

  3.  created () {

  4.    this.errHandler = window.errHandler.bind(this)

  5.  },

  6.  method: {

  7.    getXXX () {

  8.      this.$http.get('xxx/xx').then(({ body: result }) => {

  9.        if (result.code === 200) {

  10.          // ...

  11.        } else {

  12.          this.errHandler(result)

  13.        }

  14.      }).catch(this.errHandler)

  15.    }

  16.  }

  17. }

優(yōu)雅安全型

在大型多人協(xié)作的項目中,污染 window 對象還是不太妥當?shù)?。特別是一些比較有個人特色的全局方法(可能在你寫的組件中幾乎處處用到,但是對于其他人來說可能并不需要)。這時候推薦寫一個模塊,更優(yōu)雅安全,也比較自然,唯一不足之處就是每個需要使用該函數(shù)或方法的組件都需要進行導入。 使用方法與前一種大同小異,就不多作介紹了。 ̄ω ̄=

5. Moment.JS 與 Webpack

在使用 Moment.js 遇到一些問題,發(fā)現(xiàn)最終打包的文件中將 Moment.js 的全部語言包都打包了,導致最終文件徒然增加 100 kB。查了一下,發(fā)現(xiàn)可能是 webpack 打包或是 Moment.js 資源引用問題(?),目前該問題還未被妥善處理,需要通過一些 trick 來解決這個問題。 在 webpack 的生產(chǎn)配置文件中的 plugins 字段中添加一個插件,使用內(nèi)置的方法類 ContextReplacementPlugin 過濾掉 Moment.js 中那些用不到的語言包:

  1. // build/webpack.prod.conf.js

  2. new webpack.ContextReplacementPlugin(/moment[\\/]locale$/, /^\.\/(zh-cn)$/)

解決方案采自 oleg-nogin@webpack/webpack#3128。 問題討論詳見 GitHub Issue: moment/moment#2373、webpack/webpack#3128。

6. 自定義路徑別名

可能有些人注意到了,在 vue-cli 生成的模板中在導入組件時使用了這樣的語法:

  1. import Index from '@/components/Index'

這個 @ 是什么東西?后來改配置文件的時候發(fā)現(xiàn)這個是 webpack 的配置選項之一:路徑別名。 我們也可以在基礎配置文件中添加自己的路徑別名,比如下面這個就把 ~ 設置為路徑 src/components 的別名:

  1. // build/webpack.base.js

  2. {

  3.  resolve: {

  4.    extensions: ['.js', '.vue', '.json'],

  5.    alias: {

  6.      'vue$': 'vue/dist/vue.esm.js',

  7.      '@': resolve('src'),

  8.      '~': resolve('src/components')

  9.    }

  10.  }

  11. }

然后我們導入組件的時候就可以這樣寫:

  1. // import YourComponent from 'YourComponent'

  2. // import YourComponent from './YourComponent'

  3. // import YourComponent from '../YourComponent'

  4. // import YourComponent from '/src/components/YourComponent'

  5. import YourComponent from '~/YourComponent'

既解決了路徑過長的麻煩,又解決了相對路徑的煩惱,方便很多吧!ヾ(???ゞ)

7. CSS 作用域與模塊

組件內(nèi)樣式

通常,組件中 <style></style> 標簽里的樣式是全局的,在使用第三方 UI 庫(如: Element)時,全局樣式很可能影響 UI 庫的樣式。我們可以通過添加 scoped 屬性來使 style 中的樣式只作用于當前組件:

  1. <style lang='less' scoped>

  2.  @import 'other.less';

  3.  .title {

  4.    font-size: 1.2rem;

  5.  }

  6. </style>

在有 scoped 屬性的 style 標簽內(nèi)導入其他樣式,同樣會受限于作用域,變?yōu)榻M件內(nèi)樣式。復用程度較高的樣式不建議這樣使用。 另,在組件內(nèi)樣式中應避免使用元素選擇器,原因在于元素選擇器與屬性選擇器組合時,性能會大大降低。 --- 兩種組合選擇器的測試:classes selector,elements selector

導入樣式

相對于 style 使用 scoped 屬性時的組件內(nèi)樣式,有時候我們也需要添加一些全局樣式。當然我們可以用沒有 scoped 屬性的 style 來寫全局樣式。但是相比較,更推薦下面這種寫法:

  1. /* 單獨的全局樣式文件 */

  2. /* style-global.less */

  3. body {

  4.  font-size: 10px;

  5. }

  6. .title {

  7.  font-size: 1.4rem;

  8.  font-weight: bolder;

  9. }

然后在入口文件中導入全局樣式:

  1. // src/main.js

  2. import 'style-global.less'

8. 獲取表單控件值

通常我們可以直接使用 v-model 將表單控件與數(shù)據(jù)進行綁定,但是有時候我們也會需要在用戶輸入的時候獲取當前值(比如:實時驗證當前輸入控件內(nèi)容的有效性)。

這時我們可以使用 @input@change 事件綁定我們自己的處理函數(shù),并傳入 $event 對象以獲取當前控件的輸入值:

  1. <input type='text' @change='change($event)'>

  1. change (e) {

  2.  let curVal = e.target.value

  3.  if (/^\d $/.test(curVal)) {

  4.    this.num = curVal

  5.  } else {

  6.    console.error('%s is not a number!', curVal)

  7.  }

  8. }

當然,如果 UI 框架采用 Element 會更簡單,它的事件回調(diào)會直接傳入當前值。

9. v-for 的使用 tips

v-for 指令很強大,它不僅可以用來遍歷數(shù)組、對象,甚至可以遍歷一個數(shù)字或字符串。

基本語法就不講了,這里講個小 tips:

索引值

在使用 v-for 根據(jù)對象或數(shù)組生成 DOM 時,有時候需要知道當前的索引。我們可以這樣:

  1. <ul>

  2.  <li v-for='(item, key) in items' :key='key'> {{ key }} - {{ item }}

  3. </ul>

但是,在遍歷數(shù)字的時候需要注意,數(shù)字的 value 是從 1 開始,而 key 是從 0 開始:

  1. <ul>

  2.  <li v-for='(v, k) in 3' :key='k'> {{ k }}-{{ v }}

  3.  <!-- output to be 0-1, 1-2, 2-3 -->

  4. </ul>

2.2.0 的版本里,當在組件中使用 v-for 時, key 現(xiàn)在是必須的。

10. 模板的唯一根節(jié)點

JSX 相同,組件中的模板只能有一個根節(jié)點,即下面這種寫法是 錯誤 的:

  1. <template>

  2.  <h1>Title</h1>

  3.  <article>Balabala...</article>

  4. </template>

我們需要用一個塊級元素把他包裹起來:

  1. <template>

  2.  <div>

  3.    <h1>Title</h1>

  4.    <article>Balabala...</article>

  5.  </div>

  6. </template>

原因參考:React-小記:組件開發(fā)注意事項#唯一根節(jié)點

11. 項目路徑配置

由于 vue-cli 配置的項目提供了一個內(nèi)置的靜態(tài)服務器,在開發(fā)階段基本不會有什么問題。但是,當我們把代碼放到服務器上時,經(jīng)常會遇到靜態(tài)資源引用錯誤,導致界面一片空白的問題。

這是由于 vue-cli 默認配置的 webpack 是以站點根目錄引用的文件,然而有時候我們可能需要把項目部署到子目錄中。

我們可以通過 config/index.js 來修改文件引用的相對路徑:

  1.  build.assetsSubDirectory: 'static'

  2.  build.assetsPublicPath: '/'

  3.  dev.assetsSubDirectory: 'static'

  4.  dev.assetsPublicPath: '/'

我們可以看到導出對象中 builddev 均有 assetsSubDirectory、 assetsPublicPath 這兩個屬性。

其中 assetsSubDirectory 指靜態(tài)資源文件夾,也就是打包后的 js、 css、圖片等文件所放置的文件夾,這個默認一般不會有問題。

assetsPublicPath 指靜態(tài)資源的引用路徑,默認配置為 /,即網(wǎng)站根目錄,與 assetsSubDirectory 組合起來就是完整的靜態(tài)資源引用路徑 /static。

寫到這里解決方法已經(jīng)很明顯了,只要把根目錄改為相對目錄就好了:

  1.  build.assetsSubDirectory: 'static'

  2.  build.assetsPublicPath: './'

沒錯!就是一個 . 的問題。ㄟ( ▔, ▔ )ㄏ


To be continue...

文章還在完善中,歡迎大家一起討論 Vue.JS 開發(fā)中遇到的一些問題哈 (?▽?)/ 話說收藏好多,你確定收藏了會記得看嗎(:зゝ∠)讀一讀開發(fā)的時候至少會有個印象,點個贊打卡啦~ 

覺得本文對你有幫助?請分享給更多人

關注==>>「前端教程」,提升前端技能

    本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    男人和女人黄 色大片| 色哟哟精品一区二区三区| 亚洲一区二区三区在线中文字幕| 亚洲欧美日产综合在线网| 日韩毛片视频免费观看| 丝袜av一区二区三区四区五区| 色欧美一区二区三区在线| 日本办公室三级在线观看| 国产超薄黑色肉色丝袜| 日韩亚洲激情在线观看| 99久热只有精品视频最新| 日韩精品少妇人妻一区二区| 国产精品第一香蕉视频| 亚洲中文字幕熟女丝袜久久| 五月天婷亚洲天婷综合网| 1024你懂的在线视频| 福利新区一区二区人口| 亚洲熟女熟妇乱色一区| 久久热麻豆国产精品视频 | 亚洲精品国产福利在线| 欧美自拍系列精品在线| 国产成人国产精品国产三级| 91欧美一区二区三区成人| 亚洲中文字幕有码在线观看| 日本丰满大奶熟女一区二区| 国产精品久久男人的天堂| 在线懂色一区二区三区精品| 一本久道久久综合中文字幕| 久久精品一区二区少妇| 日本高清不卡在线一区| 一区二区三区四区亚洲专区| 经典欧美熟女激情综合网| 久久国产亚洲精品赲碰热| 一区二区三区精品人妻| 成人国产一区二区三区精品麻豆 | 激情内射亚洲一区二区三区 | 麻豆91成人国产在线观看| 一区二区三区18禁看| 都市激情小说在线一区二区三区| 护士又紧又深又湿又爽的视频| 中文字幕91在线观看|