Vue-loader 是什么?
vue-loader
是一個加載器,能把如下格式的 Vue 組件轉化成JavaScript模塊。
vue-loader
提供了一些非常酷炫的特性:
- ES2015默認可用;
- 在每個 Vue 組件內支持其他的 Webpack 加載器,如用於
<style>
的 SASS 和用於<template>
的 Jade。 - 把
<style>
和<template>
內引用的靜態資源作為模塊依賴項對待,並用Webpack 加載器處理。 - 對每個組件模擬有作用域的CSS。
- 開發階段支持組件的熱加載。
簡單來說,webpack 和 vue-loader 的組合為你創作Vue應用的一個更先進、更靈巧的極其強大的前端開發模式。
Webpack 是什么?
如果你熟悉 Webpack 那就跳過這部分吧,但對於那些新手們,請看下這個簡單介紹吧:
Webpack 是一個模塊打包工具。在開發中,它把一堆文件中每個都作為一個模塊處理,找出它們間的依賴關系,並打包成待發布的靜態資源。
列舉一個基本例子,設想我們有一堆的 CommonJS 的引用。它們是不能在瀏覽器直接運行,所以需要把它們 捆綁 成 <script>
標記內的單一文件。Webpack 就能按照 require()
調用的依賴關系為我們做到這點。
實際上,Webpack 能做的更多,通過 "loaders"
我們能讓 Webpack 按照我們想要的任何方式打包輸出。例如:
-
編譯 ES2015、CoffeeScript 或 TypeScript 模塊成 ES5 CommonJS 的模塊;
-
編譯之前,可以通過 linter 校驗源代碼。
-
編譯 Jade 模板成 HTML 並內聯 JavaScript 字符串。
-
編譯 SASS 文件成 CSS,然后把生成的CSS插入到
<style>
標簽內,然后再轉譯成 JavaScript 代碼段。 -
處理在 HTML 或 CSS 文件中引用的圖片文件,根據配置路徑把它們移動到任意位置,根據 MD5 hash 命名。
-
如果你學會了Webpack,就會知道它有多么強大,它非常顯著地改善你前端開發的效率。它主要的缺點是配置方式有點麻煩,但是有了我這份使用指南,那使用
Webpack + Vue + vue-loader
的時候,基本上就掃清了大多數障礙了。
Vue 組件規格
*.vue
文件是用戶用 HTML-like 的語法編寫的 Vue 組件。每個 *.vue
文件都包括三部分 <template>
, <script>
和 <style>
:
<template>
<div class="example">{{ msg }}</div>
</template>
<script>
export default {
data () {
return {
msg: 'Hello world!'
}
}
}
</script>
<style>
.example {
color: red;
}
</style>
vue-loader
解析文件,提取每個語言塊,讓他們通過需要的其他 loaders ,最后組裝起來,放回 CommonJS 的模塊,此模塊的 module.exports
就是個 Vue.js 組件對象。
vue-loader
默認用沒有用語言編譯器,想CSS 預編譯和HTML模板編譯語言等,如果想用這些功能,需要設置 lang
屬性的來實現。例如,你可以在組件的樣式中這樣用 SASS :
<style lang="sass">
/* 編寫 SASS! */
</style>
更多細節查看 [使用預編譯器]。
語言塊
<template>
-
默認語言:
html
。 -
每個
*.vue
文件幾乎都包含一個<template>
塊。 -
<template>
內的內容字符串會被提取出來,用來編譯進 Vue 組件內的template
選項。
<script>
-
默認語言:
js
(默認ES2015也會通過Babel支持)。 -
每個
*.vue
文件幾乎都包含一個<script>
塊。 -
腳本就像在CommonJS的環境中一樣被執行(就像通過WebPACK中捆綁一個正常的.js模塊)。就是說你可以
require()
其他的依賴項。由於默認支持 ES2015 ,你也可以用import
和export
語法。 -
該腳本必須導出一個 Vue.js 組件選項對象,也支持導出一個用
Vue.extend()
創建的擴展構造函數,但首先是導出普通對象。
<style>
-
默認語言:
css
。 -
每個
*.vue
文件支持多個<style>
標簽。 -
默認,會通過
style-loader
把內容提取並加載到文檔的<head>
內的<style>
標簽內。這也是可以[通過配置 Webpack 使組件內所有樣式提取到一個單一的CSS文件]。
Src Imports
如果你喜歡把你的 *.vue
組件拆分成多個文件,那么你可以用 src
屬性導入外部文件,代碼如下:
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>
需要注意的是 src
導入要遵循和 CommonJS 的 require()
調用一樣的路徑解析規則,這就是說你需要用以 ./
開頭的相對路徑,並且你可以直接從已安裝的 NPM 包內導入資源,例如:
<!-- 從已安裝的 "todomvc-app-css" NPM 包內導入文件 -->
<style src="todomvc-app-css/index.css">
語法高亮顯示
開發中的第一件事,你可能想讓 *.vue
組件能高亮顯示。現階段,在 Sublime Text , Atom , Vim , Visual Studio Code , Brackets ,和 JetBrains products (WebStorm,PhpStorm,等)都有支持語法高亮顯示的插件。如果在 Vue 組件內沒有使用任何預編譯器,那么編輯器就把 *.vue
文件當成普通的 HTML 文件一樣。
注釋
在每個代碼塊內,注釋的時候,需要使用各自語言的注釋語法去注釋(HTML、CSS、JavaScript、Jade 等)。在文件最頂部注釋的時候用HTML的注釋語法:<!— 在這里寫注釋的內容 -->
。
項目設置
語法高亮
開發中的第一件事,你可能想讓 *.vue
組件能高亮顯示。現階段,在 Sublime Text , Atom , Vim , Visual Studio Code , Brackets ,和 JetBrains products (WebStorm,PhpStorm,等)都有支持語法高亮顯示的插件。如果在 Vue 組件內沒有使用任何預編譯器,那么編輯器就把 *.vue
文件當成普通的 HTML 文件一樣。
使用 vue-cli
創建項目的時候推薦使用腳手架工具,可以用 vue-loader
和 vue-cli
,命令行如下:
npm install -g vue-cli
vue init webpack-simple hello-vue
cd hello-vue
npm install
npm run dev # 一切就緒!
ES2015
當 vue-loader
檢測到 babel-loader
或者 buble-loader
在項目中存在的時候,將會用它們去處理所有 *.vue
文件的 <script>
部分,所以我們就可以在 Vue 組件中用 ES2015 。 如果你還不熟悉這個新語言的話,最好去學一下:
這里是一個引用其他 Vue 組件的典型模式,
<script>
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'
export default {
components: {
ComponentA,
ComponentB
}
}
</script>
在這里用的就是 ES2015 精簡的語法定義個子組件。{ ComponentA }
是指 { ComponentA: ComponentA }
。Vue會被自動轉為 component-a
, 所以你就能在模板中引入組件 <component-a>
。
轉譯正常的 .js
文件
由於 vue-loader
只能處理 *.vue
文件,你需要在配置文件中告訴 Webpack 用 babel-loader
或者 buble-loader
。這點,可以用項目腳手架工具 vue-cli
。
用 .babelrc
文件來配置 Babel
.babelrc
可以控制 babel-loader
,並推薦這種方式來配置 Babel 預設插件。
Scoped CSS
當 <style>
標簽有 scoped
屬性的時候,它的 CSS 就只能作用於當前的組件。這就像樣式被封裝在 Shadow DOM 內。這是用 PostCSS 轉譯實現的。如下:
<style scoped>
.example {
color: red;
}
</style>
<template>
<div class="example">hi</div>
</template>
轉換成:
<style>
.example[_v-f3f3eg9] {
color: red;
}
</style>
<template>
<div class="example" _v-f3f3eg9>hi</div>
</template>
注意
- 在同一組件內,你能同時用有作用域和無作用域的樣式:
<style>
/* global styles */
</style>
<style scoped>
/* local styles */
</style>
-
父組件的有作用域的CSS和子組件的有作用域的CSS將同時影響子組件。
-
有作用域的樣式對其他部分沒有影響。
-
有作用域限定的樣式不排除類的需要. 由於瀏覽器渲染方式支持多種不同的CSS選擇器,加了作用域的
p { color: red }
會慢好多倍 (即,和屬性選擇器組合時候的時候)。如果你用類或者id選擇器,比如.example { color: red }
,你就能消除性能損失。這里有個練習場 ,你可以比較測試下其中的差異。 -
在遞歸組件中小心后代選擇器! 對於 CSS 規則的選擇器
.a .b
,如果匹配.a
的元素內包含一個遞歸子組件,那么子組件中所有包含.b
的元素都會被匹配到。
PostCSS
任何通過 vue-loader
處理過的 CSS 都再用 PostCSS重寫有作用域限制的 CSS 部分。你也能添加自定義的 PostCSS 插件處理,例如, autoprefixer 或 CSSNext。
在 Webpack 1.x 中的用法如下:
// webpack.config.js
module.exports = {
// 其他配置...
vue: {
// 使用用戶自定義的 postcss 插件
postcss: [require('postcss-cssnext')()]
}
}
Webpack 2.x 中的用法:
// webpack.config.js
module.exports = {
// 其他配置...
plugins: [
new webpack.LoaderOptionsPlugin({
vue: {
// 使用用戶自定義插件
postcss: [require('postcss-cssnext')()]
}
})
]
}
除了接受插件的數組,postcss
選項也接受:
-
返回值是插件數組的方法;
-
包含被傳遞到PostCSS處理器選項的對象。當你的項目依賴於自定義解析器或編譯器的時候,這就會很有用。
postcss: {
plugins: [...], // list of plugins
options: {
parser: sugarss // use sugarss parser
}
}
熱加載
“熱加載” 不只是當你修改了文件簡單地重新加載下頁面。當啟用了熱加載功能,編寫完 *.vue
文件后,組件的所有的實例對象被替換,而頁面並沒有重新加載。仍然保持應用原有的狀態。這在你調整模板或修改組件樣式的時候,大大改善了開發體驗。
當使用項目的腳手架工具 vue-cli
,熱加載自動啟用。