一、使用vue-cli脚手架创建一个最简单项目
我们通过vue的脚手架工具,执行vue create vue-demo 可以生成最初项目。从最初的脚手架初始化项目中,我们可以看到项目根目录下主要有一个public目录和src目录,其中public目录下主要就是一个index.html文件,这个index.html文件的作用就是为当前vue项目提供一个html模板,因为Vue实例要想挂载,即要想显示到html模板上,必须给其提供一个挂载点,所以模板中必须存在一个<div id="app"></div>,如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue-webpack</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
接下来,看一下src目录,该目录下主要有main.js和App.vue两个文件,其中main.js就是整个Vue项目的入口文件,App.vue就是整个Vue项目的首页,即当前单页面应用的首页。整个Vue项目是通过webpack打包来启动项目,但是我们发现,整个项目中并没有webpack的配置文件。因为其并没有对外暴露webpack的配置文件,如果我们需要修改webpack的配置文件,那么可以在项目根目录下新建一个vue.config.js文件, 然后在configureWebpack中进行配置文件的修改,内容如下:
// vue.config.js
module.exports = {
configureWebpack: {
mode: "development",
plugins: [
new MyAwesomeWebpackPlugin()
]
}
}
当然,如果想要查看默认的webpack文件到底给我们配置了什么,我们可以通过在项目根目录下执行 vue inspect > output.txt来大体查看webpack配置文件内容。
二、vue项目的启动过程
vue项目的启动过程就是,首先以src目录下的main.js为项目入口进行打包,然后将打包后的js文件,自动插入到public目录下的index.html模板中,然后加载index.html文件并执行打包后的js文件。首先看一下main.js中的具体内容,如:
// vue.config.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false // 禁用生产模式下的提示信息
new Vue({
render: (h) => {
return h(App)
},
}).$mount('#app')
我们可以看到main.js中就是引入了一下vue.js并创建一个Vue实例对象,然后调用$mount()方法进行了一下mount。
需要注意的是,传入$mount()方法的参数,必须和public目录下的index.html中的id值一致,否则Vue实例将找不到挂载点挂载。
那么Vue实例挂载到页面后显示什么内容呢?答案就是,创建Vue实例的时候配置的render()函数,当Vue实例创建完成后,通过调用$mount()函数开始Vue实例的挂载,挂载的过程中,会执行render()函数,render()函数执行会产生一个虚拟节点,然后将虚拟节点转换为真实DOM节点并挂载到页面中。需要注意的时候,Vue实例挂载后,public目录下的index.html文件中的<div id="app"></div>
会被渲染结果替换掉,即覆盖掉。
其中有一行Vue.config.productionTip = false
,该行代码的作用就是禁用生产模式下的提示警告,简单说就是,如果当前项目是在production模式下,那么就禁用一些无用的警告信息提示;如果当前项目是在development模式下,那么就不禁用,而是正常提示警告信息,通常就是禁用如下提示,如:
You are running Vue in development mode.
Make sure to turn on production mode when deploying for production.
See more tips at https://vuejs.org/guide/deployment.html
再看一下App.vue,App.vue就是一个Vue的组件,其会被vue-loader处理,然后交给render()渲染函数处理并渲染。
// App.vue
<template>
<div id="app">
{{msg}}
</div>
</template>
<script>
export default {
data() {
return {
msg: "hello msg"
}
}
}
</script>
项目中通过import Vue from "vue"
引入的其实是运行时的vue,因为我们可以通过查看vue的webpack配置文件,我们可以看到,其配置了一个alias别名,所以当引入vue的时候,找的是vue/dist/vue.runtime.esm.js,这是一个runtime运行时的版本,而运行时的vue版本,是不支持template配置的,因为运行时的版本没有编译器,所以无法将template模板内容编译为渲染函数。
resolve: {
vue$: 'vue/dist/vue.runtime.esm.js' // $表示精确匹配
}
如果使用的是运行时的版本,那么当配置了template的时候,项目运行就会输出如下警告信息,即你当前使用的是运行时的vue,此时编译器不可用,即不包含编译器,因为编译器的作用就是,将template模板编译为渲染函数,所以你可以自己手动配置一个render渲染函数或者使用带编译器的vue进行构建。
[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
如果想要使用带编译器的版本,我们可以引入 "vue.esm.js"。这里有点比较难于理解的地方就是,我们引入的App.vue可以直接交给渲染函数的createElement(App)函数进行处理,因为vue-loader对.vue文件进行了转换,我们可以以下面的方式理解,如:
import Vue from "vue";
// App.vue start
const _vm = new Vue({
data() {
return {
msg: "hello msg."
}
}
});
// import App from "./App.vue"; 引入后等价于如下
const App = ["div", {attrs: {"id":"app"}},_vm.msg];
// App.vue end
let vm = new Vue({
render: (h) => {
return h(...App);
}
});
vm.$mount("#app")
当然,我们不需要知道vue-loader具体是怎么转换的,为什么转换后的内容可以直接被createElement()函数直接渲染。我们只需要知道vue-loader会对.vue文件中的<template></template>
模板进行预编译即可。
三、自己配置webpack
为了更好的理解vue-cli生成的项目,我们可以自己配置webpack,然后实现vue-cli生成项目的运行,即自己创建一个新的项目,然后在src目录下加入main.js和App.vue以及在public目录下加入index.html文件,然后通过自己配置的webpack让项目运行起来,其webpack.config.js内容如下
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
mode: "development",
target: "web",
entry: {
main: "./src/main.js"
},
output: {
path: path.resolve(__dirname, "./dist"),
filename: "[name].js"
},
devServer: {
port: 3000, // 让devServer监听3000端口
contentBase: "./dist", // 将当前项目的dist目录作为devServer的根目录
progress: true, // 显示打包进度条
compress: true // 是否启用Gzip压缩,默认为false
},
module: {
rules: [
{
test: /\.vue$/, // 处理.vue文件
use: [
{
loader: "vue-loader"
}
]
},
{
test: /\.css$/, // 处理.css文件,包括.vue文件中的<style></style>部分
use: [
'style-loader',
'css-loader'
]
}
]
},
plugins: [
new HtmlWebpackPlugin({ // 将打包后的js文件自动注入到public目录下的index.html文件中
template: "./public/index.html",
filename: "index.html"
}),
new VueLoaderPlugin() // 处理.vue文件
]
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。