# vue-loader解析
# 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()
]
}
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') // 现在这是一个模块的请求了
}
})
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 文件中一样被处理
*/
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'
]
}
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>
-->
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 // 关闭热重载
}
}
]
}
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'
})
]
}
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 (opens new window) 同时支持在 Vue 单文件组件的模板和脚本部分的代码校验,执行命令:
另一个选项是使用 eslint-loader (opens new window) 那么你的
*.vue
文件在开发过程中每次保存的时候就会自动进行代码校验
//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/
}
]
}
}
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>
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>
2
3
4
5
6
7
8
9
10