对vueloader的研究

vue-loaderwebpack的加载器,允许您以称为单文件组件(SFC)的格式创作Vue组件:

<template>
  <div class="example">{{ msg }}</div> </template> <script> export default { data () { return { msg: 'Hello world!' } } } </script> <style> .example { color: red; } </style>

有许多很酷的功能提供vue-loader

  • 允许对Vue组件的每个部分使用其他webpack加载器,例如Sass for <style>和Pug for <template>;
  • 允许.vue文件中的自定义块可以应用自定义加载器链;
  • 处理在模块依赖项中引用的静态资产,<style><template>使用webpack加载器处理它们;
  • 模拟每个组件的范围CSS;
  • 在开发过程中保持国家的热再加载。

简而言之,webpack的组合vue-loader为您提供了一个现代,灵活且极其强大的前端工作流程,用于创作Vue.js应用程序。

Vue的CLI

如果您对手动设置webpack不感兴趣,建议使用Vue CLI构建项目。Vue CLI创建的项目预先配置了大多数开箱即用的常见开发需求。

如果Vue CLI的内置配置不符合您的需要,请遵循本指南,或者您更愿意从头开始创建自己的webpack配置。

手动配置

Vue Loader的配置与其他加载器略有不同。除了适用vue-loader于任何带扩展名的文件的规则外,请.vue务必将Vue Loader的插件添加到webpack配置中:

// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { module: { rules: [ // ... other rules { test: /\.vue$/, loader: 'vue-loader' } ] }, plugins: [ // make sure to include the plugin! new VueLoaderPlugin() ] } 

这个插件是必需的!它负责克隆您定义的任何其他规则并将它们应用于.vue文件中的相应语言块。例如,如果您有规则匹配/\.js$/,则它将应用于文件中的<script>.vue

一个更完整的webpack配置示例如下所示:

// 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' }, // this will apply to both plain `.js` files // AND `<script>` blocks in `.vue` files { test: /\.js$/, loader: 'babel-loader' }, // this will apply to both plain `.css` files // AND `<style>` blocks in `.vue` files { test: /\.css$/, use: [ 'vue-style-loader', 'css-loader' ] } ] }, plugins: [ // make sure to include the plugin for the magic new VueLoaderPlugin() ] }

资产URL处理

当Vue Loader <template>在SFC中编译块时,它还会将遇到的任何资产URL转换为webpack模块请求。

例如,以下模板代码段:

<img src="../image.png"> 

将编译成:

createElement('img', { attrs: { src: require('../image.png') // this is now a module request } }) 

默认情况下,将转换以下标记/属性组合,并可使用transformAssetUrls选项进行配置。

{
  video: ['src', 'poster'], source: 'src', img: 'src', image: 'xlink:href' } 

此外,如果您已配置为块使用css-loader,则<style>CSS中的资产URL也将以类似的方式处理。

转换规则

资产URL转换遵循以下规则:

  • 如果URL是绝对路径(例如/images/foo.png),则它将按原样保留。

  • 如果URL以#开头.,则将其解释为相对模块请求,并根据文件系统上的文件夹结构进行解析。

  • 如果URL以...开头~,则将其解释为模块请求。这意味着您甚至可以引用节点模块内的资产:

    <img src="~some-npm-package/foo.png"> 
  • 如果URL以@,它也被解释为模块请求。如果您的webpack配置具有别名@,这非常有用,默认情况下,该别名指向/src由其创建的任何项目vue-cli

因为扩展.png不是JavaScript模块,所以您需要配置webpack以使用file-loaderurl-loader来正确处理它们。使用Vue CLI创建的项目已预先配置。

为什么

资产URL转换的好处是:

  1. file-loader允许您指定复制和放置资产文件的位置,以及如何使用版本哈希命名它以获得更好的缓存。此外,这也意味着您只需将图像放在*.vue文件旁边,并根据文件夹结构使用相对路径,而不必担心部署URL。通过适当的配置,webpack将自动将文件路径重写为捆绑输出中的正确URL。

  2. url-loader允许您有条件地将文件内联为base-64数据URL(如果它们小于给定阈值)。这可以减少普通文件的HTTP请求数量。如果文件大于阈值,则会自动回退到file-loader

使用预处理器

在webpack中,所有预处理器都需要应用相应的加载器。vue-loader允许您使用其他webpack加载器来处理Vue组件的一部分。它将根据lang语言块的属性和webpack配置中的规则自动推断要使用的正确加载器。

SASS

例如,要<style>使用SASS / SCSS 编译我们的标记:

npm install -D sass-loader node-sass

在您的webpack配置中:

module.exports = {
  module: { rules: [ // ... other rules omitted // this will apply to both plain `.scss` files // AND `<style lang="scss">` blocks in `.vue` files { test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', 'sass-loader' ] } ] }, // plugin omitted }

现在除了能够之外import 'style.scss',我们还可以在Vue组件中使用SCSS:

<style lang="scss"> /* write SCSS here */ </style> 

块中的任何内容都将由webpack处理,就像它在*.scss文件中一样。

上海社会科学院VS SCSS

请注意,默认情况下sass-loader处理非基于缩进的scss语法。要使用基于缩进的sass语法,您需要将选项传递给加载器:

// webpack.config.js -> module.rules
{
  test: /\.sass$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { indentedSyntax: true } } ] }

共享全局变量

sass-loader还支持一个data选项,允许您在所有已处理文件之间共享公共变量,而无需显式导入它们:

// webpack.config.js -> module.rules
{
  test: /\.scss$/, use: [ 'vue-style-loader', 'css-loader', { loader: 'sass-loader', options: { // you can also read from a file, e.g. `variables.scss` data: `$color: red;` } } ] }

LESS

npm install -D less less-loader
// webpack.config.js -> module.rules
{
  test: /\.less$/, use: [ 'vue-style-loader', 'css-loader', 'less-loader' ] }

手写笔

npm install -D stylus stylus-loader
// webpack.config.js -> module.rules
{
  test: /\.styl(us)?$/, use: [ 'vue-style-loader', 'css-loader', 'stylus-loader' ] }

PostCSS

小费

Vue Loader v15默认不再适用PostCSS变换。您需要使用PostCSS postcss-loader

npm install -D postcss-loader
// webpack.config.js -> module.rules
{
  test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { importLoaders: 1 } }, 'postcss-loader' ] } 

PostCSS的配置可以通过postcss.config.jspostcss-loader选项完成。有关详细信息,请参阅postcss-loader docs

postcss-loader 也可以与上述其他预处理器结合使用。

巴贝尔

npm install -D babel-core babel-loader
// webpack.config.js -> module.rules
{
  test: /\.js?$/, loader: 'babel-loader' } 

Babel的配置可以通过.babelrcbabel-loader选项完成。

不包括node_modules

exclude: /node_modules/对于babel-loader适用于.js文件的JS转换规则(例如)通常是常见的。由于v15的推断变化,如果在内部导入Vue SFC node_modules,其<script>部分也将被排除在转换之外。

为了确保将JS转换应用于Vue SFC node_modules,您需要使用exclude函数将它们列入白名单:

{
  test: /\.js$/,
  loader: 'babel-loader', exclude: file => ( /node_modules/.test(file) && !/\.vue\.js/.test(file) ) } 

打字稿

npm install -D typescript ts-loader
// webpack.config.js
module.exports = {
  resolve: { // Add `.ts` as a resolvable extension. extensions: ['.ts', '.js'] }, module: { rules: [ // ... other rules omitted { test: /\.ts$/, loader: 'ts-loader', options: { appendTsSuffixTo: [/\.vue$/] } } ] }, // ... plugin omitted } 

TypeScipt的配置可以通过tsconfig.json。另请参阅ts-loader的文档。

帕格

处理模板有点不同,因为大多数webpack模板加载器如pug-loader返回模板函数而不是编译的HTML字符串。pug-loader我们需要使用一个返回原始HTML字符串的加载器,而不是使用,例如pug-plain-loader

npm install -D pug pug-plain-loader
// webpack.config.js -> module.rules
{
  test: /\.pug$/, loader: 'pug-plain-loader' } 

然后你可以写:

<template lang="pug"> div h1 Hello world! </template> 

如果您还打算使用它.pug在JavaScript中将文件作为HTML字符串导入,则需要raw-loader在预处理加载器之后进行链接。但请注意,添加raw-loader会破坏Vue组件中的使用,因此您需要有两个规则,其中一个使用a定位Vue文件resourceQuery,另一个(回退)定位JavaScript导入:

// webpack.config.js -> module.rules
{
  test: /\.pug$/, oneOf: [ // this applies to `<template lang="pug">` in Vue components { resourceQuery: /^\?vue/, use: ['pug-plain-loader'] }, // this applies to pug imports inside JavaScript { use: ['raw-loader', 'pug-plain-loader'] } ] }

作用域CSS

<style>标签具有该scoped属性时,其CSS将仅应用于当前组件的元素。这类似于Shadow DOM中的样式封装。它有一些警告,但不需要任何polyfill。通过使用PostCSS转换以下内容来实现:

<style scoped> .example { color: red; } </style> <template> <div class="example">hi</div> </template> 

进入以下:

<style> .example[data-v-f3f3eg9] { color: red; } </style> <template> <div class="example" data-v-f3f3eg9>hi</div> </template> 

混合本地和全局样式

您可以在同一组件中包含范围和非范围样式:

<style> /* global styles */ </style> <style scoped> /* local styles */ </style> 

子组件根元素

使用时scoped,父组件的样式不会泄漏到子组件中。但是,子组件的根节点将受父级作用域CSS和子级作用域CSS的影响。这是设计的,以便父级可以设置子根元素的样式以进行布局。

深度选择器

如果您希望scoped样式中的选择器“深入”,即影响子组件,则可以使用>>>组合器:

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

以上将编译成:

.a[data-v-f3f3eg9] .b { /* ... */ } 

某些预处理器(如Sass)可能无法>>>正确解析。在这些情况下,您可以使用/deep/组合器 - 它是别名,>>>并且完全相同。

动态生成的内容

创建的DOM内容v-html不受范围样式的影响,但您仍然可以使用深度选择器设置它们的样式。

也记住

  • 范围样式不会消除类的需要。由于浏览器呈现各种CSS选择器的方式,p { color: red }在作用域时(即与属性选择器结合时)会慢很多倍。如果您使用类或ID,例如in .example { color: red },那么您几乎可以消除性能损失。这是一个游乐场,您可以自己测试差异。

  • 在递归组件中注意后代选择器!对于带有选择器的CSS规则.a .b,如果匹配的元素.a包含递归子组件,则.b该子组件中的所有组件都将与规则匹配。

 

CSS模块

CSS模块是用于模块化和组合CSS的流行系统。vue-loader提供与CSS模块的一流集成,作为模拟范围CSS的替代方案。

用法

首先,必须通过传递modules: truecss-loader

// webpack.config.js
{
  module: {
    rules: [ // ... other rules omitted { test: /\.css$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { // enable CSS Modules modules: true, // customize generated class names localIdentName: '[local]_[hash:base64:8]' } } ] } ] } } 

然后,将module属性添加到您的<style>

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

module属性指示Vue Loader将CSS模块locals对象作为具有名称的计算属性注入组件$style。然后,您可以在模板中使用动态类绑定:

<template>
  <p :class="$style.red"> This should be red </p> </template> 

由于它是一个计算属性,它也可以使用以下对象/数组语法:class

<template>
  <div> <p :class="{ [$style.red]: isRed }"> Am I red? </p> <p :class="[$style.red, $style.bold]"> Red and bold </p> </div> </template> 

您还可以从JavaScript访问它:

<script> export default { created () { console.log(this.$style.red) // -> "red_1VyoJ-uZ" // an identifier generated based on filename and className. } } </script> 

有关模式详细信息(如全局异常组合),请参阅CSS模块规范

选择使用

如果您只想在某些Vue组件中使用CSS模块,则可以使用oneOf规则并检查module字符串resourceQuery

// webpack.config.js -> module.rules
{
  test: /\.css$/, oneOf: [ // this matches `<style module>` { resourceQuery: /module/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { modules: true, localIdentName: '[local]_[hash:base64:5]' } } ] }, // this matches plain `<style>` or `<style scoped>` { use: [ 'vue-style-loader', 'css-loader' ] } ] } 

与预处理器一起使用

CSS模块可以与其他预处理器一起使用:

// webpack.config.js -> module.rules
{
  test: /\.scss$/, use: [ 'vue-style-loader', { loader: 'css-loader', options: { modules: true } }, 'sass-loader' ] } 

自定义进样名称

您可以<style>在单个*.vue组件中包含多个标记。为避免注入样式相互覆盖,可以通过为module属性赋值来自定义注入的计算属性的名称:

<style module="a"> /* identifiers injected as a */ </style> <style module="b"> /* identifiers injected as b */ </style>

热刷新

“Hot Reload”不仅仅是在编辑文件时重新加载页面。启用热重新加载后,在编辑*.vue文件时,将交换该组件的所有实例,而无需重新加载页面。它甚至可以保留您的应用程序和这些交换组件的当前状态!当您调整组件的模板或样式时,这可以显着改善开发体验。

热重装

州保存规则

  • 编辑<template>组件时,已编辑组件的实例将重新呈现,保留所有当前的私有状态。这是可能的,因为模板被编译成新的渲染函数,不会产生副作用。

  • 编辑<script>组件的一部分时,将销毁并重新创建已编辑组件的实例。(保留应用程序中其他组件的状态)这是因为<script>可能包含可能产生副作用的生命周期钩子,因此需要“重新加载”而不是重新呈现以确保一致的行为。这也意味着您需要注意全局副作用,例如组件生命周期钩子中的计时器。如果您的组件产生全局副作用,有时您可能需要执行整页重新加载。

  • <style>热重载依次运行vue-style-loader,因此不会影响应用程序状态。

用法

搭建项目时vue-cli,Hot Reload可以开箱即用。

手动设置项目时,在使用项目服务时会自动启用热重新加载webpack-dev-server --hot

高级用户可能想要查看内部使用的vue-hot-reload-apivue-loader

禁用热重新加载

除以下情况外,始终启用热重新加载:

  • webpack targetnode(SSR)
  • webpack缩小了代码
  • process.env.NODE_ENV === 'production'

您可以使用hotReload: false选项明确禁用热重新加载:

module: {
  rules: [
    { test: /\.vue$/, loader: 'vue-loader', options: { hotReload: false // disables Hot Reload } } ] }

功能组件

*.vue文件中定义为单文件组件的功能组件也接收适当的模板编译,Scoped CSS和热重载支持。

要表示应编译为功能组件functional的模板,请将该属性添加到模板块。这也允许省略块中的functional选项<script>

模板中的表达式在功能渲染上下文中进行评估。这意味着需要像props.xxx在模板中一样访问props :

<template functional> <div>{{ props.foo }}</div> </template> 

如果需要访问全局定义的属性Vue.prototype,可以在parent以下位置访问它们:

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

自定义块

您可以在*.vue文件中定义自定义语言块。应用于自定义块的加载器将根据块的lang属性,块的标记名称以及webpack配置中的规则进行匹配。

如果lang指定了属性,则自定义块将作为文件lang与其扩展名匹配。

您还可以使用resourceQuery匹配自定义块的规则lang。例如,要匹配<foo>自定义块:

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

如果为自定义块找到匹配规则,则会对其进行处理; 否则将自动忽略自定义块。

此外,如果自定义块在所有匹配的加载器处理后将函数导出为最终结果,则将使用*.vue文件的组件作为参数调用该函数。

例子

下面是将<docs>自定义块注入组件的示例,以便在运行时可用。

为了注入自定义块内容,我们将编写一个自定义加载器:

module.exports = function (source, map) { this.callback( null, `export default function (Component) { Component.options.__docs = ${ JSON.stringify(source) } }`, map ) } 

现在我们将配置webpack以使用我们的自定义加载器来<docs>定制块。

// wepback.config.js
module.exports = {
  module: { rules: [ { resourceQuery: /blockType=docs/, loader: require.resolve('./docs-loader.js') } ] } } 

我们现在能够<docs>在运行时访问块的导入组件的内容。

<!-- 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提取,以便在开发期间获得CSS热重新加载。

的WebPack 4

npm install -D mini-css-extract-plugin
// webpack.config.js
var MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { // other options... module: { rules: [ // ... other rules omitted { test: /\.css$/, use: [ process.env.NODE_ENV !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader, 'css-loader' ] } ] }, plugins: [ // ... Vue Loader plugin omitted new MiniCssExtractPlugin({ filename: 'style.css' }) ] } 

另请参阅mini-css-extract-plugin文档

的WebPack 3

npm install -D extract-text-webpack-plugin
// webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin") module.exports = { // other options... module: { rules: [ // ... other rules omitted { test: /\.css$/, loader: ExtractTextPlugin.extract({ use: 'css-loader', fallback: 'vue-style-loader' }) } ] }, plugins: [ // ... Vue Loader plugin omitted new ExtractTextPlugin("style.css") ] }

Linting

#ESLint

The official eslint-plugin-vue supports linting both the template and script parts of Vue single file components.

Make sure to use the plugin's included config in your ESLint config:

// .eslintrc.js
module.exports = {
  extends: [ "plugin:vue/essential" ] } 

Then from the command line:

eslint --ext js,vue MyComponent.vue

Another option is using eslint-loader so that your *.vue files are automatically linted on save during development:

npm install -D eslint eslint-loader

Make sure it's applied as a pre-loader:

// webpack.config.js
module.exports = {
  // ... other options module: { rules: [ { enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /node_modules/ } ] } } 

#stylelint

stylelint supports linting style parts of Vue single file components.

Make sure that your stylelint config is right.

Then from the command line:

stylelint MyComponent.vue

Another option is using stylelint-webpack-plugin:

npm install -D stylelint-webpack-plugin

Make sure it's applied as a plugin:

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

测试




















































































 

转载于:https://www.cnblogs.com/zhouyideboke/p/9562191.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值