成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

VueJS 開發(fā)常見問題集錦

hedge_hog / 583人閱讀

摘要:由于公司的前端開始轉(zhuǎn)向,最近開始使用這個(gè)框架進(jìn)行開發(fā),遇到一些問題記錄下來,以備后用。查了一下,發(fā)現(xiàn)可能是打包或是資源引用問題,目前該問題還未被妥善處理,需要通過一些來解決這個(gè)問題。為解決這個(gè)問題,中提供了方法對(duì)象受現(xiàn)

由于公司的前端開始轉(zhuǎn)向 VueJS,最近開始使用這個(gè)框架進(jìn)行開發(fā),遇到一些問題記錄下來,以備后用。

主要寫一些 官方手冊(cè) 上沒有寫,但是實(shí)際開發(fā)中會(huì)遇到的問題,需要一定知識(shí)基礎(chǔ)。

涉及技術(shù)棧

CLI: Vue-CLI

UI: Element

HTML: Pug(Jade)

CSS: Less

JavaScript: ES6

正文:

polyfill 與 transform-runtime

  首先,vue-cli 為我們自動(dòng)添加了 babel-plugin-transform-runtime 這個(gè)插件,該插件多數(shù)情況下都運(yùn)作正常,可以轉(zhuǎn)換大部分 ES6 語法。

  但是,存在如下兩個(gè)問題:

異步加載組件時(shí),會(huì)產(chǎn)生 polyfill 代碼冗余

不支持對(duì)全局函數(shù)與實(shí)例方法的 polyfill

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

  由于異步組件最終會(huì)被編譯為一個(gè)多帶帶的文件,所以即使多個(gè)組件中使用了同一個(gè)新特性(例如:Object.keys()),那么在每個(gè)編譯后的文件中都會(huì)有一份該新特性的 polyfill 拷貝。如果項(xiàng)目較小可以考慮不使用異步加載,但是首屏的壓力會(huì)比較大。

  不支持全局函數(shù)(如:Promise、Set、Map),SetMap 這兩種數(shù)據(jù)結(jié)構(gòu)應(yīng)該大家用的也不多,影響較小。但是 Promise 影響可能就比較大了。

  不支持實(shí)例方法(如:"abc".includes("b")["1", "2", "3"].find((n) => n < 2) 等等),這個(gè)限制幾乎廢掉了大部分字符串和一半左右數(shù)組的新特性。

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

替換 babel-polyfill

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

npm un babel-plugin-transform-runtime -D

  修改 babel 配置文件

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

  然后,安裝 babel-polyfill 依賴:

npm i babel-polyfill -D

  最后,在入口文件中導(dǎo)入

// src/main.js
import "babel-polyfill"
ES6 import 引用問題

  在 ES6 中,模塊系統(tǒng)的導(dǎo)入與導(dǎo)出采用的是引用導(dǎo)出與導(dǎo)入(非簡(jiǎn)單數(shù)據(jù)類型),也就是說,如果在一個(gè)模塊中定義了一個(gè)對(duì)象并導(dǎo)出,在其他模塊中導(dǎo)入使用時(shí),導(dǎo)入的其實(shí)是一個(gè)變量引用(指針),如果修改了對(duì)象中的屬性,會(huì)影響到其他模塊的使用。

  通常情況下,系統(tǒng)體量不大時(shí),我們可以使用 JSON.parse(JSON.stringify(str)) 簡(jiǎn)單粗暴地來生成一個(gè)全新的深度拷貝的 數(shù)據(jù)對(duì)象。不過當(dāng)組件較多、數(shù)據(jù)對(duì)象復(fù)用程度較高時(shí),很明顯會(huì)產(chǎn)生性能問題,這時(shí)我們可以考慮使用 Immutable.js。

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

在 Vue 中使用 Pug 與 Less 安裝依賴

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

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

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

使用 pug 還是 pug-loadersass 兩種語法的 loader 如何設(shè)置?
--- 請(qǐng)參考 預(yù)處理器 · vue-loader

使用



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

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

簡(jiǎn)單粗暴型

  最簡(jiǎn)單的方法就是直接在 window 對(duì)象上定義一個(gè)全局方法,在組件內(nèi)使用的時(shí)候用 bind、callapply 來改變上下文。

  定義一個(gè)全局異常處理方法:

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

  在入口文件中導(dǎo)入:

// 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)
    }
  }
}
優(yōu)雅安全型

  在大型多人協(xié)作的項(xiàng)目中,污染 window 對(duì)象還是不太妥當(dāng)?shù)?。特別是一些比較有個(gè)人特色的全局方法(可能在你寫的組件中幾乎處處用到,但是對(duì)于其他人來說可能并不需要)。這時(shí)候推薦寫一個(gè)模塊,更優(yōu)雅安全,也比較自然,唯一不足之處就是每個(gè)需要使用該函數(shù)或方法的組件都需要進(jìn)行導(dǎo)入。

  使用方法與前一種大同小異,就不多作介紹了。 ̄ω ̄=

Moment.JS 與 Webpack

  在使用 Moment.js 遇到一些問題,發(fā)現(xiàn)最終打包的文件中將 Moment.js 的全部語言包都打包了,導(dǎo)致最終文件徒然增加 100+kB。查了一下,發(fā)現(xiàn)可能是 webpack 打包或是 Moment.js 資源引用問題(?),目前該問題還未被妥善處理,需要通過一些 trick 來解決這個(gè)問題。

  在 webpack 的生產(chǎn)配置文件中的 plugins 字段中添加一個(gè)插件,使用內(nèi)置的方法類 ContextReplacementPlugin 過濾掉 Moment.js 中那些用不到的語言包:

// build/webpack.prod.conf.js
new webpack.ContextReplacementPlugin(/moment[/]locale$/, /^./(zh-cn)$/)

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

自定義路徑別名

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

import Index from "@/components/Index"

  這個(gè) @ 是什么東西?后來改配置文件的時(shí)候發(fā)現(xiàn)這個(gè)是 webpack 的配置選項(xiàng)之一:路徑別名。

  我們也可以在基礎(chǔ)配置文件中添加自己的路徑別名,比如下面這個(gè)就把 ~ 設(shè)置為路徑 src/components 的別名:

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

  然后我們導(dǎo)入組件的時(shí)候就可以這樣寫:

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

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

CSS 作用域與模塊 組件內(nèi)樣式

  通常,組件中 標(biāo)簽里的樣式是全局的,在使用第三方 UI 庫(如:Element)時(shí),全局樣式很可能影響 UI 庫的樣式。

  我們可以通過添加 scoped 屬性來使 style 中的樣式只作用于當(dāng)前組件:

在有 scoped 屬性的 style 標(biāo)簽內(nèi)導(dǎo)入其他樣式,同樣會(huì)受限于作用域,變?yōu)榻M件內(nèi)樣式。復(fù)用程度較高的樣式不建議這樣使用。

另,在組件內(nèi)樣式中應(yīng)避免使用元素選擇器,原因在于元素選擇器與屬性選擇器組合時(shí),性能會(huì)大大降低。

--- 兩種組合選擇器的測(cè)試:classes selector,elements selector

導(dǎo)入樣式

  相對(duì)于 style 使用 scoped 屬性時(shí)的組件內(nèi)樣式,有時(shí)候我們也需要添加一些全局樣式。當(dāng)然我們可以用沒有 scoped 屬性的 style 來寫全局樣式。

  但是相比較,更推薦下面這種寫法:

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

  然后在入口文件中導(dǎo)入全局樣式:

// src/main.js
import "style-global.less"
獲取表單控件值

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

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

change (e) {
  let curVal = e.target.value
  if (/^d+$/.test(curVal)) {
    this.num = +curVal
  } else {
    console.error("%s is not a number!", curVal)
  }
}

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

v-for 的使用 tips

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

  基本語法就不講了,這里講個(gè)小 tips:

索引值

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

  • {{ key }} - {{ item }}

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

  • {{ k }}-{{ v }}

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

模板的唯一根節(jié)點(diǎn)

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

  我們需要用一個(gè)塊級(jí)元素把他包裹起來:

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

項(xiàng)目路徑配置

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

  這是由于 vue-cli 默認(rèn)配置的 webpack 是以站點(diǎn)根目錄引用的文件,然而有時(shí)候我們可能需要把項(xiàng)目部署到子目錄中。

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

  build.assetsSubDirectory: "static"
  build.assetsPublicPath: "/"

  dev.assetsSubDirectory: "static"
  dev.assetsPublicPath: "/"

  我們可以看到導(dǎo)出對(duì)象中 builddev 均有 assetsSubDirectory、assetsPublicPath 這兩個(gè)屬性。

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

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

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

  build.assetsSubDirectory: "static"
  build.assetsPublicPath: "./"

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

更小的 Polyfill 開銷

  在引入 Polyfill 之后,可以在 .babelrc 文件中開啟 useBulitIns 屬性。啟用該屬性后,編譯項(xiàng)目時(shí)會(huì)根據(jù)項(xiàng)目中新特性的使用情況將完整的 polyfill 拆分成獨(dú)立的模塊序列。
  啟用 useBuiltIns 屬性:

  // .babelrc
  {
    "presets": [
      ["env", {
        "modules": false,
        "useBuiltIns": true
      }],
      "es2015",
      "stage-2"
    ]
    // ...
  }

  安裝后引入 babel-polyfill

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

  [1, 2, 3].find((v => v > 2))

啟用 useBulitIns 后自動(dòng)拆分 babel-polyfill

  import "core-js/modules/es6.array.find"

  [1, 2, 3].find((v => v > 2))

經(jīng)測(cè)試最大減少了一半左右的 polyfill 體積
沒深入研究哈,猜測(cè)可能加了 core-js 跟一些基礎(chǔ)的 polyfill

使用 ESnext class 特性 對(duì)比

  默認(rèn)時(shí),Vue 單文件組件使用一個(gè)對(duì)象來描述組件內(nèi)部的實(shí)現(xiàn):

  const App = {
    // initialized data
    data () {
      return {
        init: false
      }
    }
    // lifecycle hook
    created () {}
    mounted () {}
    // ...
  }

  export default App

  我們可以通過安裝一些依賴來支持最新的 class 寫法:

  import Vue from "vue"
  import Component from "vue-class-component"

  @Component
  class App extends Vue {
    init = false;
    created () {}
    mounted () {}
  }

  export default App

不可否認(rèn),確實(shí)多些了一些代碼哈,不過個(gè)人還是比較傾向新語法特性的寫法的,畢竟標(biāo)準(zhǔn)即是燈塔
P.S 這里使用了還處于 Stage 3 的 Field declarations 來聲明組件的初始 data

使用

  下面來看看需要做哪些改動(dòng)以支持使用 class 的寫法:

首先,最明顯的就是我們需要 vue-class-component 這個(gè)依賴了。

然后,這個(gè)依賴需要 babeltransform-decorators-legacy 插件支持。

最后,如果你也想使用 Field declarations 字段聲明寫法,再添加一個(gè) transform-class-properties 就好了。

  安裝依賴:

  npm i vue-class-component -D
  npm i babel-plugin-transform-decorators-legacy -D
  npm i babel-plugin-transform-class-properties -D

  配置 babel

  // .babelrc
  {
    // ...
    "plugins": [
      "transform-runtime",
      "transform-decorators-legacy",
      "transform-class-properties"
    ]
    // ...
  }

注意transform-decorators-legacy 需放在 transform-class-properties 之前

響應(yīng)式數(shù)據(jù)失效 數(shù)組

  由于 Vue.js 響應(yīng)式數(shù)據(jù)依賴于對(duì)象方法 Object.defineProperty。但很明顯,數(shù)組這個(gè)特殊的“對(duì)象”并沒有這個(gè)方法,自然也無法設(shè)置對(duì)象屬性的 descriptor,從而也就沒有 getter()setter() 方法。所以在使用數(shù)組索引角標(biāo)的形式更改元素?cái)?shù)據(jù)時(shí)(arr[index] = newVal),視圖往往無法響應(yīng)式更新。
  為解決這個(gè)問題,Vue.js 中提供了 $set() 方法:

vm.arr.$set(0, "newVal")
// vm.arr[0] = "newVal"
對(duì)象

受現(xiàn)代 JavaScript 的限制(以及廢棄 Object.observe),Vue 不能檢測(cè)到對(duì)象屬性的添加或刪除。由于 Vue 會(huì)在初始化實(shí)例時(shí)對(duì)屬性執(zhí)行 getter/setter 轉(zhuǎn)化過程,所以屬性必須在 data 對(duì)象上存在才能讓 Vue 轉(zhuǎn)換它,這樣才能讓它是響應(yīng)的。
Ref: 深入響應(yīng)式原理 - Vue.js

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 是響應(yīng)的
vm.b = 2
// `vm.b` 是非響應(yīng)的
靜態(tài)類型檢測(cè)

  推薦在開發(fā)較復(fù)雜的組件時(shí)使用 props 靜態(tài)類型檢測(cè),提高組件的健壯性,多數(shù)情況下可以在轉(zhuǎn)碼階段提前發(fā)現(xiàn)錯(cuò)誤。

// before
prop: [
  "id",
  "multiple",
  "callback",
]
// after
props: {
  id: {
    type: [ Number, Array ],
    required: true,
  },
  multiple: {
    type: Boolean,
    default: false,
  },
  callback : Function,
}
異步組件

  使用處于 Stage.3 階段的動(dòng)態(tài)導(dǎo)入函數(shù) import(),同時(shí)借助 webpack 的代碼分割功能,在 Vue.js 中我們可以很輕松地實(shí)現(xiàn)一個(gè)異步組件。

異步路由組件
const AsyncComponent = () => import("./AsyncComponent")
異步組件工廠
Vue.component(
  "async-webpack-example",
  () => import("./my-async-component")
)

相比于異步路由組建,異步組件工廠一般適用于組件內(nèi)進(jìn)一步小顆粒度的拆分處理,如:大體量組件內(nèi)初次加載時(shí)的非必要組件(組件內(nèi)嵌套的彈窗組件或 Popover 組件等)。

To be continue...

文章還在完善中,歡迎大家一起討論 Vue.JS 開發(fā)中遇到的一些問題哈 (?▽?)/

看看你的收藏列表,你確定收藏了會(huì)記得看嗎_(:зゝ∠)_
讀一讀開發(fā)的時(shí)候至少會(huì)有個(gè)印象,點(diǎn)個(gè)贊打卡啦~

原文:VueJS 開發(fā)常見問題集錦

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/84098.html

相關(guān)文章

  • 2017-07-19 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選開發(fā)常見問題集錦前端碼農(nóng)的自我修養(yǎng)虛擬內(nèi)部是如何工作的譯知乎專欄并不慢,只是你使用姿勢(shì)不對(duì)一份優(yōu)化指南掘金老司機(jī)帶你秒懂內(nèi)存管理第一部中文免費(fèi)公開課前端面試的大關(guān)鍵點(diǎn),你到了嗎知乎專欄高效開發(fā)與設(shè)計(jì)姐的圖片二三 2017-07-19 前端日?qǐng)?bào) 精選 VueJS 開發(fā)常見問題集錦 - 前端碼農(nóng)的自我修養(yǎng) - SegmentFault虛擬 DOM 內(nèi)部是如何工作的?[譯]Hig...

    iflove 評(píng)論0 收藏0
  • 2016年總結(jié) - 收藏集 - 掘金

    摘要:然而這次的文章,就像賀師俊所說的這篇文章是從程序員這個(gè)老年度總結(jié)前端掘金年對(duì)我來說,是重要的一年。博客導(dǎo)讀總結(jié)個(gè)人感悟掘金此文著筆之時(shí),已經(jīng)在眼前了。今天,我就來整理一篇,我個(gè)人認(rèn)為的年對(duì)開發(fā)有年終總結(jié)掘金又到 2016 Top 10 Android Library - 掘金 過去的 2016 年,開源社區(qū)異?;钴S,很多個(gè)人與公司爭(zhēng)相開源自己的項(xiàng)目,讓人眼花繚亂,然而有些項(xiàng)目只是曇花一...

    DataPipeline 評(píng)論0 收藏0
  • Java開發(fā)常見問題集錦

    摘要:下面是一些常見的理解性問題,每一個(gè)問題盡量用圖或代碼去描述。內(nèi)容全部來自,包括基本語法數(shù)組集合類泛型面向?qū)ο罄厥债惓?刂戚斎胼敵龊蛢?nèi)存。不斷更新,歡迎大家提出有趣味的問題和意見。 程序員經(jīng)??梢酝ㄟ^搜索或者記憶來完成代碼,但是許多時(shí)候并不真正理解為什么那樣寫。也就是說,有一定經(jīng)驗(yàn)的程序員不會(huì)犯一些低級(jí)的語法錯(cuò)誤,但是因?yàn)椴簧钊肜斫庥锌赡茉斐梢恍└呒?jí)錯(cuò)誤,比如說運(yùn)行無效率,代碼難De...

    MSchumi 評(píng)論0 收藏0
  • 微信小程序知識(shí)總結(jié)及案例集錦

    摘要:對(duì)微信小程序進(jìn)行全局配置,決定頁面文件的路徑窗口表現(xiàn)設(shè)置網(wǎng)絡(luò)超時(shí)時(shí)間設(shè)置多等。 微信小程序知識(shí)總結(jié)及案例集錦 微信小程序的發(fā)展會(huì)和微信公眾號(hào)一樣,在某個(gè)時(shí)間點(diǎn)爆發(fā) 學(xué)習(xí)路徑 微信小程序最好的教程肯定是官方的文檔啦,點(diǎn)擊這里直達(dá) 微信官方文檔 認(rèn)真跟著文檔看一遍,相信有vue前端經(jīng)驗(yàn)的看下應(yīng)該就能上手了,然后安裝 微信小程序開發(fā)者工具 新建一個(gè)quick start項(xiàng)目,了解代碼結(jié)構(gòu),...

    sean 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<