# vue-loader解析

资料:vue-loader (opens new window)

# 1、vue-loader

vue-loader是一个webpack的loader,允许以单文件(SFCs)格式写vue组件。

# 1、使用

  • vue-cli会全部设置完成
  • 手动设置:npm install -D vue-loader vue-template-compiler
// webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')

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: [
    /* 必须引入:将你定义过的其它规则复制并应用到 .vue 文件里相应语言的块。例如,如果你有一条匹配 /\.js$/ 的规则,那么它会应用到 .vue 文件里的 <script> 块 */
    new VueLoaderPlugin()
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

# 2、处理资源路径

当 Vue Loader 编译单文件组件中的 <template> 块时,它也会将所有遇到的资源 URL 转换为 webpack 模块请求,转换规则如下:

  • 如果路径是绝对路径 (例如 /images/foo.png),会原样保留。
  • 如果路径以 . 开头,将会被看作相对的模块依赖,并按照你的本地文件系统上的目录结构进行解析。
  • 如果路径以 ~ 开头,其后的部分将会被看作模块依赖,这意味着你可以用该特性来引用一个 Node 依赖中的资源。
  • 如果路径以 @ 开头,也会被看作模块依赖,使用vue配置的alias

.png文件非模块,需在webpack中配置file-loader、url-loader进行加载。

<img src="../image.png">
createElement('img', {
  attrs: {
    src: require('../image.png') // 现在这是一个模块的请求了
  }
})
1
2
3
4
5
6

# 3、预处理器

# 1、scss

// npm install -D sass-loader node-sass
module.exports = {
  module: {
    rules: [
      // 普通的 `.scss` 文件和 `*.vue` 文件中的
      // `<style lang="scss">` 块都应用它
      {
        test: /\.scss$/,
        use: [
          'vue-style-loader',
          'css-loader',
          'sass-loader'
        ]
      }
    ]
  },
}

/* 
<style lang="scss">
// 在这里撰写 SCSS
</style>
这个块里的任何内容都会被 webpack 当作在一个 *.scss 文件中一样被处理
*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 2、less

// npm install -D less less-loader
// webpack.config.js -> module.rules
{
  test: /\.less$/,
  use: [
    'vue-style-loader',
    'css-loader',
    'less-loader'
  ]
}
1
2
3
4
5
6
7
8
9
10

# 4、scoped css

<style> 标签有 scoped 属性时,它的 CSS 只作用于当前组件中的元素。

# 1、使用

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

<style>
/* 全局样式 */
</style>

<style scoped>
/* 本地样式 */
.example {
  color: red;
}
.a >>> .b { /* ... */ }
</style>

<!-- 转译为:
<style>
.example[data-v-f3f3eg9] {
  color: red;
}

.a[data-v-f3f3eg9] .b { /* ... */ }
</style>
-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 2、深度作用选择器

使用 scoped 后,父组件的样式将不会渗透到子组件中。

  • 特殊:一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。
  • 希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,可以使用 >>> 操作符,预处理器可以使用 /deep/::v-deep 操作符取而代之。

# 5、热重载

“热重载”不只是当你修改文件的时候简单重新加载页面。启用热重载后,当你修改 .vue 文件时,该组件的所有实例将在不刷新页面的情况下被替换。

# 1、规则

  • 当编辑一个组件的 <template> 时,这个组件实例将就地重新渲染,并保留当前所有的私有状态。
  • 当编辑一个组件的 <script> 时,这个组件实例将就地销毁并重新创建,应用中其它组件的状态将会被保留
  • <style> 会通过 vue-style-loader 自行热重载,所以它不会影响应用的状态

# 2、关闭热重载

module: {
  rules: [
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: {
        hotReload: false // 关闭热重载
      }
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11

# 6、css提取

//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: [
    new MiniCssExtractPlugin({
      filename: 'style.css'
    })
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 7、代码校验

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

//npm install -D eslint eslint-loader
//webpack.config.js,确保它是作为一个pre-loader运用的
module.exports = {
  // ... 其它选项
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.(js|vue)$/,
        loader: 'eslint-loader',
        exclude: /node_modules/
      }
    ]
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 2、单文件组件(SFC)规范

# 1、简介

.vue 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Vue 组件。每个 .vue 文件包含三种类型的顶级语言块 <template><script><style>,还允许添加可选的自定义块。

  • vue-loader 会解析文件,提取每个语言块,如有必要会通过其它 loader 处理,最后将他们组装成一个 ES Module,它的默认导出是一个 Vue.js 组件选项的对象
  • vue-loader 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性
<!-- 注释解析:
在语言块中使用该语言块对应的注释语法 (HTML、CSS、JavaScript、Jade 等)。
顶层注释使用 HTML 注释语法:`<! -- comment contents here -- >`
-->
<template>
  <div class="example">{{ msg }}</div>
</template>

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

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

<custom1>
  This could be e.g. documentation for the component.
</custom1>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

# 2、语言块

# 1、模版

  • 每个 .vue 文件最多包含一个 <template> 块。
  • 内容将被提取并传递给 vue-template-compiler 为字符串,预处理为 JavaScript 渲染函数,并最终注入到从 <script> 导出的组件中。

# 2、脚本

  • 每个 .vue 文件最多包含一个 <script> 块。
  • 这个脚本会作为一个 ES Module 来执行。
  • 它的默认导出应该是一个 Vue.js 的组件选项对象 (opens new window)。也可以导出由 Vue.extend() 创建的扩展对象,但是普通对象是更好的选择。
  • 任何匹配 .js 文件 (或通过它的 lang 特性指定的扩展名) 的 webpack 规则都将会运用到这个 <script> 块的内容中。

# 3、样式

  • 默认匹配:/\.css$/
  • 一个 .vue 文件可以包含多个 <style> 标签。
  • <style> 标签可以有 scoped 或者 module 属性,具有不同封装模式的多个 <style>标签可以在同一个组件中混合使用。
  • 任何匹配 .css 文件 (或通过它的 lang 特性指定的扩展名) 的 webpack 规则都将会运用到这个 <style> 块的内容中。

# 4、自定义块

可以在 .vue 文件中添加额外的自定义块来实现项目的特定需求,例如 <docs> 块。vue-loader 将会使用标签名来查找对应的 webpack loader 来应用在对应的块上。webpack loader 需要在 vue-loader 的选项 loaders 中指定。

# 5、src导入

.vue 文件分隔到多个文件中,你可以通过 src 属性导入外部文件, src 导入遵循和 webpack 模块请求相同的路径解析规则:

  • 相对路径需要以 ./ 开始
  • 你可以从 NPM 依赖中导入资源
  • 自定义块上同样支持 src 导入
<template src="./template.html"></template>
<style src="./style.css"></style>
<script src="./script.js"></script>

<!-- import a file from the installed "todomvc-app-css" npm package -->
<style src="todomvc-app-css/index.css">

<!-- 自定义模块导入外部文件 -->
<unit-test src="./unit-test.js">
</unit-test>
1
2
3
4
5
6
7
8
9
10
Last Updated: 8/1/2021, 11:39:39 AM