目录
后续项目中,我们会使用 Vue 进行开发,而且会以特殊的文件来组织 Vue 的组件。所以,下面我们来学习一下如何在我们的 webpack 环境中集成 Vue。
现在,我们希望在项目中使用 Vue,那么需要对其有依赖,所以需要先进行安装:
npm install vue --save
注:因为我们后续是在实际项目中也会使用 Vue 的,所以并不是开发时依赖。
index.js
import Vue from 'vue'
new Vue({
el : '#app',
data:{
msg: 'hello vue'
}
})
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="app">
{{ msg }}
</div>
<script src="./dist/index.js" type="text/javascript"></script>
</body>
</html>
html
接下来,打包运行发现没有显示出来,从控制台看到报错:
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.<br/>
(found in <Root>)
意思是说:你正在使用 Vue 的仅运行时版本,但模板编译器不可用。 可以将模板预编译为渲染函数,也可以使用包含编译器的内部版本。
在 NPM 包的 dist/
目录你将会找到很多不同的 Vue.js 构建版本。这里列出了它们之间的差别:
UMD | CommonJS | ES Module (基于构建工具使用) | ES Module (直接用于浏览器) | |
---|---|---|---|---|
完整版 | vue.js | vue.common.js | vue.esm.js | vue.esm.browser.js |
只包含运行时版 | vue.runtime.js | vue.runtime.common.js | vue.runtime.esm.js | - |
完整版 (生产环境) | vue.min.js | - | - | vue.esm.browser.min.js |
只包含运行时版 (生产环境) | vue.runtime.min.js | - | - | - |
完整版:同时包含编译器和运行时的版本。
编译器:用来将模板字符串编译成为 JavaScript 渲染函数的代码。
运行时:用来创建 Vue 实例、渲染并处理虚拟 DOM 等的代码。基本上就是除去编译器的其它一切。
UMD:UMD 版本可以通过 <script>
标签直接用在浏览器中。jsDelivr CDN 的 https://cdn.jsdelivr.net/npm/vue 默认文件就是运行时 + 编译器的 UMD 版本 (vue.js
)。
CommonJS:CommonJS 版本用来配合老的打包工具比如 Browserify 或 webpack 1。这些打包工具的默认文件 (pkg.main
) 是只包含运行时的 CommonJS 版本 (vue.runtime.common.js
)。
ES Module:从 2.6 开始 Vue 会提供两个 ES Modules (ESM) 构建文件:
因为运行时版本相比完整版体积要小大约 30%,所以应该尽可能使用这个版本。如果你仍然希望使用完整版,则需要在打包工具 webpack 里配置一个别名:
module.exports = {
// ...
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js' // 用 webpack 1 时需用 'vue/dist/vue.common.js'
}
}
}
重新打包运行可以看出效果。
el
和 template
区别正常运行之后,我们来考虑另外一个问题: 如果我们希望将 data
中的数据显示在界面中,就必须是修改 index.html,如果我们后面自定义了组件,也必须修改 index.html 来使用组件。但是 html 模板在之后的开发中,我并不希望手动的来频繁修改,是否可以做到呢? 定义 template
属性: 在前面的 Vue 实例中,我们定义了el
属性,用于和 index.html 中的 #app
进行绑定,让 Vue 实例之后可以管理它其中的内容。
这里,我们可以将 div 元素中的 {{ msg }}
内容删掉,只保留一个基本的 id 为 div 的元素,但是如果我依然希望在其中显示 {{ msg }}
的内容,应该怎么处理呢?
我们可以再定义一个 template
属性,代码如下:
import Vue from 'vue'
new Vue({
el : '#app',
template: `
<div id="#app">{{ msg }}</div>
`,
data:{
msg: 'hello vue'
}
})
重新打包,运行程序,可以发现显示一样的结果和 HTML 代码结构。
那么,el
和 template
模板的关系是什么呢?
在我们之前的学习中,我们知道 el
用于指定 Vue 要管理的 DOM,可以帮助解析其中的指令、事件监听等等。 而如果 Vue 实例中同时指定了 template
,那么 template
模板的内容会替换掉挂载的对应 el
的模板。
这样做有什么好处呢?
这样做之后我们就不需要在以后的开发中再次操作 index.html,只需要在 template 中写入对应的标签即可。
但是,书写 template
模块非常麻烦怎么办呢?
后面我们会将 template
模板中的内容进行抽离。会分成三部分书写:template、script、style,结构变得非常清晰。
在学习组件化开发的时候,我说过以后的 Vue 开发过程中,我们都会采用组件化开发的思想。那么,在当前项目中,如果我也想采用组件化的形式进行开发,应该怎么做呢?
我们可以将下面的代码抽取到一个 js 文件中,并且导出:
import Vue from 'vue'
const App = {
template: '<p>{{ msg }}</p>',
data() {
return {
msg: '我是 app 组件'
}
}
}
new Vue({
el : '#app',
template: `
<div id="#app">
<h1>{{ msg }}</h1>
<App />
</div>
`,
data:{
msg: 'hello vue'
},
components: {
App
}
})
src/vue/app.js
export default {
template: '<p>{{ msg }}</p>',
data() {
return {
msg: '我是 app 组件'
}
}
}
src/index.js
import Vue from 'vue'
import App from './vue/app'
new Vue({
el : '#app',
template: `
<div id="#app">
<h1>{{ msg }}</h1>
<App />
</div>
`,
data:{
msg: 'hello vue'
},
components: {
App
}
})
但是一个组件以一个 js 对象的形式进行组织和使用的时候是非常不方便的。一方面编写 template
模块非常的麻烦,另外一方面如果有样式的话,我们写在哪里比较合适呢? 现在,我们以一种全新的方式来组织一个 vue 的组件App.vue
:
<template>
<p class="color">{{ msg }}</p>
</template>
<script>
export default {
name: 'App',
data() {
return {
msg: '我是 app 组件'
}
}
}
</script>
<style>
.color {color:green;}
</style>
但是,这种特殊的文件以及特殊的格式,必须有人帮助我们处理。这时使用 vue-loader
以及 vue-template-compiler
。
安装 vue-loader
和 vue-template-compiler
:
npm install vue-loader vue-template-compiler --save-dev
已安装过可以忽略。
安装完成后可能会发现控制台有个警告:
npm WARN vue-loader@15.9.6 requires a peer of css-loader@ but none is installed. You must install peer dependencies you
说明需要安装
css-loader
等相关依赖,否则无法正常打包。npm install style-loader css-loader --save-dev
修改 webpack 的配置文件:
const path = require('path')
const {VueLoaderPlugin} = require('vue-loader')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.vue$/,
use : 'vue-loader'
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins:[
new VueLoaderPlugin()
]
}
Vue Loader v15 需要配合一个 webpack 插件才能正确使用:
// webpack.config.js const { VueLoaderPlugin } = require('vue-loader') module.exports = { // ... plugins: [ new VueLoaderPlugin() ] }