VueJS 開發常見問題集錦

来源:http://www.cnblogs.com/wwhhq/archive/2017/12/23/8094058.html
-Advertisement-
Play Games

由於公司的前端開始轉向 VueJS,最近開始使用這個框架進行開發,遇到一些問題記錄下來,以備後用。 主要寫一些 官方手冊 上沒有寫,但是實際開發中會遇到的問題,需要一定知識基礎。 涉及技術棧 CLI: Vue CLI UI: Element HTML: Pug(Jade) CSS: Less Jav ...


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

涉及技術棧

  • CLI: Vue-CLI
  • UI: Element
  • HTML: Pug(Jade)
  • CSS: Less
  • JavaScript: ES6

polyfill 與 transform-runtime

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

1、非同步載入組件時,會產生 polyfill 代碼冗餘
2、不支持對全局函數與實例方法的 polyfill
兩個問題的原因均歸因於 babel-plugin-transform-runtime 採用了沙箱機制來編譯我們的代碼(即:不修改宿主環境的內置對象)。

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

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

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

npm un babel-plugin-transform-runtime -D

  修改 babel 配置文件

// .babelrc
{
  //...
  "plugins": [
    // - "transform-runtime"
  ]
  //...
}

  然後,安裝 babel-polyfill 依賴:

npm i babel-polyfill -D

  最後,在入口文件中導入

// src/main.js
import 'babel-polyfill'

ES6 import 引用問題

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

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

在 Vue 中使用 Pug 與 Less

安裝依賴

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

npm i pug -D
npm i less-loader -D

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

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

使用

<!-- xxx.vue -->
<style lang="less">
  .action {
    color: #ddd;
      ul {
        overflow: hidden;
        li {
          float: left;
        }
      }
  }
</style>
<template lang="pug">
  .action(v-if='hasRight')
    ul
      li 編輯
      li 刪除
</template>
<script>
  export default {
    data () {
      return {
        hasRight: true
      }
    }
  }
</script>

定義全局函數或變數

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

簡單粗暴型

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

// errHandler.js
window.errHandler = function () { // 不能使用箭頭函數
  if (err.code && err.code !== 200) {
    this.$store.commit('err', true)
  } else {
    // ...
  }
}

  在入口文件中導入:

// src/main.js
import 'errHandler.js'
  在組件中使用:

// xxx.vue
export default {
  created () {
    this.errHandler = window.errHandler.bind(this)
  },
  method: {
    getXXX () {
      this.$http.get('xxx/xx').then(({ body: result }) => {
        if (result.code === 200) {
          // ...
        } else {
          this.errHandler(result)
        }
      }).catch(this.errHandler)
    }
  }
}

優雅安全型

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

自定義路徑別名

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

import Index from '@/components/Index'

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

// build/webpack.base.js
{
  resolve: {
    extensions: ['.js', '.vue', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      '~': resolve('src/components')
    }
  }
}

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

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

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

CSS 作用域與模塊

組件內樣式

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

<style lang="less" scoped>
  @import 'other.less';
  .title {
    font-size: 1.2rem;
  }
</style>
在有 scoped 屬性的 style 標簽內導入其他樣式,同樣會受限於作用域,變為組件內樣式。復用程度較高的樣式不建議這樣使用。另,在組件內樣式中應避免使用元素選擇器,原因在於元素選擇器與屬性選擇器組合時,性能會大大降低。--- 兩種組合選擇器的測試:classes selector,elements selector

導入樣式

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

/* 單獨的全局樣式文件 */
/* style-global.less */
body {
  font-size: 10px;
}
.title {
  font-size: 1.4rem;
  font-weight: bolder;
}

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

// src/main.js
import 'style-global.less'

獲取表單控制項值

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

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

<input type='text' @change='change($event)'>
change (e) {
  let curVal = e.target.value
  if (/^\d+$/.test(curVal)) {
    this.num = +curVal
  } else {
    console.error('%s is not a number!', curVal)
  }
}

當然,如果 UI 框架採用 Element 會更簡單,它的事件回調會直接傳入當前值。

v-for 的使用 tips

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

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

索引值

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

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

  但是,在遍曆數字的時候需要註意,數字的 value 是從 1 開始,而 key 是從 0 開始:

<ul>
  <li v-for='(v, k) in 3' :key='k'> {{ k }}-{{ v }} 
  <!-- output to be 0-1, 1-2, 2-3 -->
</ul>
2.2.0+ 的版本里,當在組件中使用 v-for 時,key 現在是必須的。

模板的唯一根節點

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

<template>
  <h1>Title</h1>
  <article>Balabala...</article>
</template>

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

<template>
  <div>
    <h1>Title</h1>
    <article>Balabala...</article>
  </div>
</template>
原因參考:React-小記:組件開發註意事項#唯一根節點

項目路徑配置

  由於 vue-cli 配置的項目提供了一個內置的靜態伺服器,在開發階段基本不會有什麼問題。但是,當我們把代碼放到伺服器上時,經常會遇到靜態資源引用錯誤,導致界面一片空白的問題。

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

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

  build.assetsSubDirectory: 'static'
  build.assetsPublicPath: '/'

  dev.assetsSubDirectory: 'static'
  dev.assetsPublicPath: '/'

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

  其中 assetsSubDirectory 指靜態資源文件夾,也就是打包後的 js、css、圖片等文件所放置的文件夾,這個預設一般不會有問題。

  assetsPublicPath 指靜態資源的引用路徑,預設配置為 /,即網站根目錄,與 assetsSubDirectory 組合起來就是完整的靜態資源引用路徑 /static。

  寫到這裡解決方法已經很明顯了,只要把根目錄改為相對目錄就好了:

  build.assetsSubDirectory: 'static'
  build.assetsPublicPath: './'

  沒錯!就是一個 . 的問題。
文章還在完善中,歡迎大家一起討論 Vue.JS 開發中遇到的一些問題哈 /
話說收藏好多,你確定收藏了會記得看嗎_
讀一讀開發的時候至少會有個印象,點個贊打卡啦~
原文:VueJS 開發常見問題集錦
https://blog.beard.ink/JavaScript/VueJS-開發常見問題集錦/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、編譯環境 Linux version 3.10.0-327.el7.x86_64 ([email protected]) (gcc version 4.8.3 20140911 (Red Hat 4.8.3-9) (GCC) ) greenplum 5.3.0 二、編 ...
  • What Is Apache Hadoop? Hadoop是一個可靠的、可擴展的、分散式計算的開源軟體。 Hadoop是一個分散式處理大數據的框架。它被設計成從一臺到上千台不等的伺服器,每個伺服器都提供本地計算和存儲的能力。它並非依賴於硬體來提供高可用服務。 Hadoop這個工程包含如下模塊: Ha ...
  • 【github】http://www.liu12fei08fei.top/blog/14capture.html 抓包工具介紹 抓包工具介紹 whistle 啟動whistle 重啟whsitle 停止whistle 調試模式啟動whistle(主要用於查看whistle的異常及插件開發) 更新wh ...
  • 某些Google Play服務(例如Google登錄和App Invites)要求我們提供簽名證書的SHA-1,以便google paly為我們的應用創建OAuth2客戶端和API密鑰。 那麼如何獲取SHA-1呢? 獲取SHA-1有多種方法,這裡我們介紹用命令行的方法。(使用keytool,註意,k ...
  • 一、組件 1、UI組件 (Android.view.View的子類或者間接子類) 2、容器組件(Android.view.ViewGroup子類或者間接子類) 二、UI組件:TextView,Spinner(下拉式列表),ListView(列表) 容器組件:RelevantLayout,Linear ...
  • 前言 雖然說本系列中架構篇是第一章,但實際過程中是在慢慢演化的第二版中才有這個概念, 經過不斷的迭代,演化才逐步穩定 明確目標 首先明確需要做成一個什麼樣的框架? 大致就是: 一套API規範(統一 與`iOS`),所有API非同步調用(防止阻塞) 提供大部分原生功能的API(包括很多常用的功能給 使用 ...
  • JavaScript中數組排序的方法有兩個reverse()和sort()。 reverse()方法會反轉數組項的順序: sort()方法會按照字元串升序排列數組項,sort()方法會調用每個數組項的tostring()方法,即使數組中的每一項都是數值,sort()方法比較的也是字元串: 這種方式在 ...
  • 在網頁或者是APP的開發中,動畫運用得當可以起到錦上添花的作用。正確使用動畫,不但可以有助於用戶理解交互的作用,還可以大大提高網頁應用的魅力和使用體驗。並且在現在的網頁開發中,動畫已經成為了一個設計的標準,變得越來越重要。特別是在一些和用戶交互的地方,使用動畫能更好的給用戶以反饋,提升用戶的操作體驗 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...