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),会原样保留

    扫描二维码关注公众号,回复: 4528189 查看本文章
  • 如果路径以 . 开头,将会被看作相对的模块依赖,并按照你的本地文件系统上的目录结构进行解析。

  • 如果路径以 ~ 开头,其后的部分将会被看作模块依赖。这意味着你可以用该特性来引用一个 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 的设置。

猜你喜欢

转载自blog.csdn.net/qq_37021554/article/details/83242580
今日推荐