「这是我参与11月更文挑战的第23天,活动详情查看:2021最后一次更文挑战」
1. 编写 App.vue 文件
前面说到,我们要把 template 选项中的内容、data 选项中的内容以及样式代码都放在一个文件中,就可以使用 .vue 文件。具体怎么编写呢?我们可以这样来做:比如在 src 目录下新建 vue 文件夹,在 vue 文件夹下新建 App.vue 文件,文件内容如下:
<template>
<h2>我是 Vue 渲染出来的</h2>
<h2>{{ title }}</h2>
</template>
<script>
// 在当前文件中导出对象,之后在其它文件中就可以导入使用了
export default {
data() {
return {
title: '你好'
}
},
// 还可以有其它选项
methods: {
}
};
</script>
<style>
h2 {
color: #f66;
}
</style>
把模板、脚本和样式代码都编写到这个 App.vue 文件中后,之前的有关代码就可以不要了,我们来对 src/main.js 文件做修改:
// 第三方库的导入可以放最上面(个人习惯)
import { createApp } from 'vue/dist/vue.esm-bundler';
import { sum } from './js/math';
const { formatPrice } = require('./js/format');
// 导入 App.vue 文件中导出的对象(你可能会问,App.vue 导出的对象中没有 template 啊?不用担心,我们后面会使用 loader 对这个 .vue 文件做编译,编译之后,会自动把 template 中的内容放进 script 中的),注意:这里的 .vue 文件扩展名不能省略哦
import App from './vue/App.vue';
import './js/element';
console.log(sum(10, 20));
console.log(formatPrice(100));
// 编写 Vue 相关的代码
// const app = createApp({
// template: '#my-app',
// data() {
// return {
// title: '你好'
// }
// }
// });
const app = createApp(App);
app.mount('#app');
修改完成后,我们来运行 npm run build 命令对项目代码编译打包:
你会发现打包报错了,很显然,这是因为我们没有给 webpack 配置相应的 loader 来处理 .vue 类型的文件。那么我们需要哪个 loader 来帮助我们处理 .vue 文件呢?没错,正是 vue-loader,我们先来安装它:
npm install vue-loader@next -D
注意:
vue-loader是用来处理Vue2的代码的,而我们现在写的是Vue3的代码,所以需要使用vue-loader@next。因为处理
.vue文件的过程只存在于开发时,所以这里使用-D。
安装好之后,我们再去 webpack.config.js 中添加配置:
...
module.exports = {
...
module: {
rules: [
...
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
...
}
再来进行打包之前,为了便于讲解,我们先重新安装一下 Vue,这次指定安装的版本为 3.2.12:
npm install vue@3.2.12
重新安装完成后,我们来运行 npm run build 命令进行打包:
你会发现,仍然有一个错误需要解决,这次错误的大意是:我们当前使用的 Vue 需要是 3.2.13 以上的版本(包括 3.2.13 版本),或者需要在依赖树中有 @vue/compiler-sfc。也就是说,要解决这个错误,我们有两种方案:
- 重新安装
>=3.2.13版本的Vue; - 仍然用当前
3.2.12版本的Vue,但需要再手动安装@vue/compiler-sfc这个包;
1.1 <=3.2.12 版本的 Vue
我们先采用第 2 种方案,安装 @vue/compiler-sfc:
npm install @vue/compiler-sfc -D
@vue/compiler-sfc这个包其实就是用来解析整个SFC文件的(包括SFC文件中的template,其实都是通过这个包来解析的)。而在
Vue2时,对template做解析则是通过vue-template-compiler这个包来完成的。
安装完成后,我们再来运行 npm run build 命令进行打包:
你会发现,又出现了新的错误,从其中最后一个错误中我们可以看到,vue-loader 在使用时没有使用相应的插件,我们需要在 webpack 配置中配置 VueLoaderPlugin 插件。
也就是说,对于 .vue 文件的解析,除了配置 vue-loader,还需要使用 vue-loader 中的 VueLoaderPlugin(因为 plugin 是贯穿 webpack 的整个生命周期的,所以它可以在某个时刻帮助 vue-loader 做一些事情)。所以我们来到 webpack.config.js 文件中添加插件的配置:
...
// 从 vue-loader 中引入 VueLoaderPlugin
const { VueLoaderPlugin } = require('vue-loader/dist/index');
module.exports = {
...
module: {
rules: [
...
{
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
plugins: [
...
new VueLoaderPlugin() // 使用 VueLoaderPlugin
]
}
添加完配置后,我们再来打包:
可以看到,这次打包成功了,这就意味着 SFC 文件中的代码已经成功编译了。再来通过 Live Server 插件在浏览器中打开 build/index.html 文件,页面效果如下:
可以看到,App.vue 文件中的模板内容、数据、样式都成功进行了显示。
而且,我们可以回顾一下之前我们讲过的组件化,在真实开发中,我们会按照组件化的方式进行开发。当我们想要创建一个组件时,就可以通过新建一个 .vue 文件来实现,比如我们这里在 src/vue/ 目录下新建 HelloWorld.vue 文件:
<template>
<h2>HelloWorld 组件</h2>
</template>
<script>
export default {
data() {
return {}
}
}
</script>
<style>
</style>
然后通过最常用的局部注册组件的方式(当然,你也可以全局注册(app.component(...)))对这个 HelloWorld 组件进行注册,我们在 App.vue 中进行局部注册:
<template>
<h2>我是 Vue 渲染出来的</h2>
<h2>{{ title }}</h2>
<!-- 使用 HelloWorld 组件(如果是以 Pascal 格式命名的组件,使用时可以用短横线分隔的形式使用) -->
<hello-world></hello-world>
</template>
<script>
// 在 App.vue 中引入 HelloWorld 组件
import HelloWorld from './HelloWorld.vue';
// 在当前文件中导出对象,之后在其它文件中就可以导入使用了
export default {
// 局部注册组件
components: {
// 局部注册 HelloWorld 组件
// HelloWorld: HelloWorld
// ES6 中增强了对象语法,变量名和属性名一样时,属性值可以简写:
HelloWorld
},
data() {
return {
title: '你好'
}
},
// 还可以有其它选项
methods: {
}
};
</script>
<style>
h2 {
color: #f66;
}
</style>
然后再来运行 npm run build 命令打包,打包成功后来看浏览器中的页面效果:
可以看到,HelloWorld 组件的内容成功显示出来了。但是,你会发现 HelloWorld 组件中的字体颜色也变成了 #f66 色,如果希望这个在 App.vue 中设置的样式只作用于 App.vue(而不会穿透进子组件中),我们可以这样做:
-
给
App.vue中的style添加scoped属性;... <style scoped> h2 { color: #f66; } </style> -
给
HelloWorld.vue中template中的元素包一层根元素,比如用一个<div>元素作为根元素:<template> <div> <h2>HelloWorld 组件</h2> </div> </template> ...
修改完这两个文件后,我们再来打包看下效果:
这次,子组件 HelloWorld.vue 中的 <h2> 元素中的文字颜色就没有再被设置为 #f66 了。
1.2 >=3.2.13 版本的 Vue
我们再来采用第 1 种方案,即重新安装 >=3.2.13 版本的 Vue,我们这里直接安装最新版本的 Vue3:
npm install vue@next
然后,我们可以把之前手动安装的 @vue/compiler-sfc 卸载掉:
npm uninstall @vue/compiler-sfc
再来运行 npm run build 命令进行打包,你会发现,使用了 vue 最新版本后,即使没有手动安装 @vue/compiler-sfc,也可以成功打包,而且页面效果也没问题:
那为什么使用了 vue 最新版本后就可以不用自己来安装 @vue/compiler-sfc 了呢?这是因为 Vue 3.2.13+ 版本之后已经把 SFC 文件的编译器(即 @vue/compiler-sfc 这个包)直接放到了 vue 的包下。我们可以从 Vue 3.2.13+ 之后源码的依赖中找到依据:
vue@3.2.13 版本中的依赖:
当前(2021-11-22)最新版本的 Vue(vue@3.2.22)中的依赖:
再来看 vue@3.2.12 版本中的依赖:
可以看到,vue 在 3.2.12 版本时,还没有在依赖中添加 @vue/compiler-sfc,在 3.2.13 版本之后就做了添加。
此外,我们也可以在 vue-loader 的源码中找到有关说明:
总之,现在我们就可以编写很多组件,然后如果在另外一个组件中需要使用某个组件,就可以导入它,接着进行局部注册,之后就可以使用它了。
以上,就是 Webpack 中对 .vue 文件的支持方式,需要做的主要有三点:
- 安装
vue-loader@next; - 安装
@vue/compiler-sfc(vue的版本>=3.2.13之后,则不需要再进行手动安装); - 配置
VueLoaderPlugin插件;