1. 程式人生 > >Vue Loader 學習記錄

Vue Loader 學習記錄

Vue Loader 是什麼?

webpack的lodaer. 單檔案元件 (SFCs)的格式撰寫元件。

 

<template>
  <div class="example">{{ msg }}</div>
</template>

<script>
export default {
  data () {
    return {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>
  • 允許為 Vue 元件的每個部分使用其它的 webpack loader,例如在 <style> 的部分使用 Sass 和在 <template> 的部分使用 Pug;
  • 允許在一個 .vue 檔案中使用自定義塊,並對其運用自定義的 loader 鏈;
  • 使用 webpack loader 將 <style> 和 <template> 中引用的資源當作模組依賴來處理;
  • 為每個元件模擬出 scoped CSS
  • 在開發過程中使用熱過載
    來保持狀態。

 

Vue CLI

腳手架

 

手動配置

// webpack.config.js
const path = require('path')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  mode: 'development',
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      // 它會應用到普通的 `.js` 檔案
      // 以及 `.vue` 檔案中的 `<script>` 塊
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      // 它會應用到普通的 `.css` 檔案
      // 以及 `.vue` 檔案中的 `<style>` 塊
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    // 請確保引入這個外掛來施展魔法
    new VueLoaderPlugin()
  ]
}

處理資源路徑

 

當 Vue Loader 編譯單檔案元件中的 <template> 塊時,它也會將所有遇到的資源 URL 轉換為 webpack 模組請求

<img src="../image.png">
createElement('img', {
  attrs: {
    src: require('../image.png') // 現在這是一個模組的請求了
  }
})

 

 

轉換規則

資源 URL 轉換會遵循如下規則:

  • 如果路徑是絕對路徑 (例如 /images/foo.png),會原樣保留

  • 如果路徑以 . 開頭,將會被看作相對的模組依賴,並按照你的本地檔案系統上的目錄結構進行解析。

  • 如果路徑以 ~ 開頭,其後的部分將會被看作模組依賴。這意味著你可以用該特性來引用一個 Node 依賴中的資源

  • 如果路徑以 @ 開頭,也會被看作模組依賴。如果你的 webpack 配置中給 @ 配置了 alias,這就很有用了。所有 vue-cli 建立的專案都預設配置了將 @ 指向 /src

 

相關的 Loader

 file-loader 或者 url-loader

 

使用前處理器

Sass

需要先進行安裝以及在webpack中進行配置,就可以在css部分解析sass型別的檔案

 

sass-loader 會預設處理不基於縮排的 scss 語法。

 

共享全域性變數

sass-loader 也支援一個 data 選項,這個選項允許你在所有被處理的檔案之間共享常見的變數,而不需要顯式地匯入它們:

// webpack.config.js -> module.rules
{
  test: /\.scss$/,
  use: [
    'vue-style-loader',
    'css-loader',
    {
      loader: 'sass-loader',
      options: {
        // 你也可以從一個檔案讀取,例如 `variables.scss`
        data: `$color: red;`
      }
    }
  ]
}

Less

less-loader

 

Stylus

stylus-loader

 

PostCSS

postcss-loader

 

Babel

babel的配置可以通過.babelrc 或babel-loader來完成

 

TypeScript

type-lodaer ->tsconfig.json來配置完成

 

Pug

HTML 字串的 loader,例如 pug-plain-loader

 

Scoped CSS

<style scoped>
.example {
  color: red;
}
</style>

<template>
  <div class="example">hi</div>
</template>

style scoped 只作用於當前元件中。

 

混用本地和全域性樣式

可以在一個元件中混合使用 本地樣式和全域性樣式(stlye帶不帶scpoed)

 

子元件的根元素

使用scoped以後,父元件的樣式不會滲透到子元件中。子元件的根節點受到父元件和其他元件樣式的影響。

 

深度作用選擇器

<style scoped>
.a >>> .b { /* ... */ }
</style>

>>>

 

留意點:

1.scoped不能代替class  會比class渲染的慢

2.在遞迴子元件中小心使用後代選擇器

 

CSS Modules

模組化和組合css的系統

 

css modules 需要css-loader中的modules為true.

// webpack.config.js
{
  module: {
    rules: [
      // ... 其它規則省略
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          {
            loader: 'css-loader',
            options: {
              // 開啟 CSS Modules
              modules: true,
              // 自定義生成的類名
              localIdentName: '[local]_[hash:base64:8]'
            }
          }
        ]
      }
    ]
  }
}

在html中的部署 需要加上module

<style module>
.red {
  color: red;
}
.bold {
  font-weight: bold;
}
</style>

從而使得該style 成為一個vue-loader下的計算書型$style

可以進行繫結,也可以在 JS中訪問到它。

 

<template>
  <p :class="$style.red">
    This should be red
  </p>
</template>
<template>
  <div>
    <p :class="{ [$style.red]: isRed }">
      Am I red?
    </p>
    <p :class="[$style.red, $style.bold]">
      Red and bold
    </p>
  </div>
</template>
<script>
export default {
  created () {
    console.log(this.$style.red)
    // -> "red_1VyoJ-uZ"
    // 一個基於檔名和類名生成的識別符號
  }
}
</script>

可選用法

oneOf 匹配一部分的modules

// webpack.config.js -> module.rules
{
  test: /\.css$/,
  oneOf: [
    // 這裡匹配 `<style module>`
    {
      resourceQuery: /module/,
      use: [
        'vue-style-loader',
        {
          loader: 'css-loader',
          options: {
            modules: true,
            localIdentName: '[local]_[hash:base64:5]'
          }
        }
      ]
    },
    // 這裡匹配普通的 `<style>` 或 `<style scoped>`
    {
      use: [
        'vue-style-loader',
        'css-loader'
      ]
    }
  ]
}

和前處理器配合使用

可以與sass-loader 等其他處理器一起配合使用

自定義的注入名稱

<style module="a">
  /* 注入識別符號 a */
</style>

<style module="b">
  /* 注入識別符號 b */
</style>

 

熱過載

特別好的一點!!。可以在不重新整理頁面的情況下可以看到你修改的部分!!

 

狀態保留規則

  • <template>重新渲染,保留私有狀態。
  • <script>銷燬了並重新建立。元件狀態會保留,但可能含有其他鉤子,重新載入是必須的,保持一致性
  • <style>會通過vue-style-loader自行熱過載。

 

關閉熱過載

  • webpack 的 target 的值是 node (服務端渲染)
  • webpack 會壓縮程式碼
  • process.env.NODE_ENV === 'production'
module: {
  rules: [
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
        hotReload: false // 關閉熱過載
      }
    }
  ]
}

 

函式式元件

函式式的元件需要新增functional特性

<template functional>
  <div>{{ props.foo }}</div>
</template>
<template functional>
  <div>{{ parent.$someProperty }}</div>
</template>

 

自定義塊

自定義語言塊。

resourceQuery 來為一個沒有 lang 的自定義塊匹配一條規則。

{
  module: {
    rules: [
      {
        resourceQuery: /blockType=foo/,
        loader: 'loader-to-use'
      }
    ]
  }
}

 

為了注入自定義塊的內容,我們將會撰寫一個自定義 loader:

module.exports = function (source, map) {
  this.callback(
    null,
    `export default function (Component) {
      Component.options.__docs = ${
        JSON.stringify(source)
      }
    }`,
    map
  )
}
<!-- ComponentB.vue -->
<template>
  <div>Hello</div>
</template>

<docs>
This is the documentation for component B.
</docs>
<!-- ComponentA.vue -->
<template>
  <div>
    <ComponentB/>
    <p>{{ docs }}</p>
  </div>
</template>

<script>
import ComponentB from './ComponentB.vue';

export default {
  components: { ComponentB },
  data () {
    return {
      docs: ComponentB.__docs
    }
  }
}
</script>

 

CSS 提取

請只在生產環境下使用 CSS 提取,這將便於你在開發環境下進行熱過載。

 

webpack 4

npm install -D mini-css-extract-plugin
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  // 其它選項...
  module: {
    rules: [
      // ... 忽略其它規則
      {
        test: /\.css$/,
        use: [
          process.env.NODE_ENV !== 'production'
            ? 'vue-style-loader'
            : MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    // ... 忽略 vue-loader 外掛
    new MiniCssExtractPlugin({
      filename: style.css
    })
  ]
}

 

webpack 3

npm install -D extract-text-webpack-plugin
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {
  // 其它選項...
  module: {
    rules: [
      // ...其它規則忽略
      {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract({
          use: 'css-loader',
          fallback: 'vue-style-loader'
        })
      }
    ]
  },
  plugins: [
    // ...vue-loader 外掛忽略
    new ExtractTextPlugin("style.css")
  ]
}

 

程式碼校驗 (Linting)

 

ESLint

便於統一風格。規範程式碼格式。

Eslint 配置檔案

// .eslintrc.js
module.exports = {
  extends: [
    "plugin:vue/essential"
  ]
}
eslint --ext js,vue MyComponent.vue

或者:loader

npm install -D eslint eslint-loader
// webpack.config.js
module.exports = {
  // ... 其它選項
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ]
  }
}

stylelint

stylelint 支援在 Vue 單檔案元件的樣式部分的程式碼校驗。

stylelint MyComponent.vue

或者:

npm install -D stylelint-webpack-plugin
// webpack.config.js
const StyleLintPlugin = require('stylelint-webpack-plugin');
module.exports = {
  // ... 其它選項
  plugins: [
    new StyleLintPlugin({
      files: ['**/*.{vue,htm,html,css,sss,less,scss,sass}'],
    })
  ]
}

測試

  • Vue CLI 提供了預配置的單元測試和 e2e 測試安裝。

  • 如果你有興趣為 *.vue 檔案手動設定單元測試,請查詢 @vue/test-utils 的文件,這份文件涵蓋了對 mocha-webpack 或 Jest 的設定。