1.安装node环境
Node.js是-一个基于Chrome V8引擎的JavaScript 运行环境。
- 直接简单粗暴,下载对应版本的node包http://nodejs.cn/download/
- 使用node版本管理工具
nvm全名node.js version management,顾名思义是一个nodejs的版本管理工具。
nvm install 11.13.0 // 安装node版本
nvm list // 查看已安装的node版本
nvm use 11.13.0 // 使用某个特定的版本
nvm uninstall 11.13.0 // 卸载
npm,全称是 Node Package Manager =>node 包管理器
// npm(国外受限制)可能下载包失败,直接指定源,改成国内镜像
npm set registry https://registry.npm.taobao.org/ //直接使用npm i 即可
// 或者安装cnpm
npm install -g cnpm --registry=http://registry.npm.taobao.org
// 检测是否切换到了淘宝源
npm info underscore
// nrm是专门用来管理和快速切换私人配置的registry ls add use ls
npm install nrm -g
号外~~~
npm和yarn的区别:
“Yarn是由Facebook、Google、Exponent 和 Tilde 联合推出了一个新的 JS 包管理工具 ,正如官方文档中写的,Yarn 是为了弥补 npm 的一些缺陷而出现的。”这句话让我想起了使用npm时的坑了:
npm install的时候巨慢。特别是新的项目拉下来要等半天,删除node_modules,重新install的时候依旧如此。
同一个项目,安装的时候无法保持一致性。由于package.json文件中版本号的特点,下面三个版本号在安装的时候代表不同的含义。
Yarn的优点:
速度快 : 并行安装:无论 npm 还是 Yarn 在执行包的安装时,都会执行一系列任务。npm 是按照队列执行每个 package,也就是说必须要等到当前 package 安装完成之后,才能继续后面的安装。而 Yarn 是同步执行所有任务,提高了性能;离线模式:如果之前已经安装过一个软件包,用Yarn再次安装时之间从缓存中获取,就不用像npm那样再从网络下载了。
安装版本统一:为了防止拉取到不同的版本,Yarn 有一个锁定文件 (lock file) 记录了被确切安装上的模块的版本号。每次只要新增了一个模块,Yarn 就会创建(或更新)yarn.lock 这个文件。这么做就保证了,每一次拉取同一个项目依赖时,使用的都是一样的模块版本。npm 其实也有办法实现处处使用相同版本的 packages,但需要开发者执行 npm shrinkwrap 命令。这个命令将会生成一个锁定文件,在执行 npm install 的时候,该锁定文件会先被读取,和 Yarn 读取 yarn.lock 文件一个道理。npm 和 Yarn 两者的不同之处在于,Yarn 默认会生成这样的锁定文件,而 npm 要通过 shrinkwrap 命令生成 npm-shrinkwrap.json 文件,只有当这个文件存在的时候,packages 版本信息才会被记录和更新。
更简洁的输出:npm 的输出信息比较冗长。在执行 npm install 的时候,命令行里会不断地打印出所有被安装上的依赖。相比之下,Yarn 简洁太多:默认情况下,结合了 emoji直观且直接地打印出必要的信息,也提供了一些命令供开发者查询额外的安装信息。
多注册来源处理:所有的依赖包,不管他被不同的库间接关联引用多少次,安装这个包时,只会从一个注册来源去装,要么是 npm 要么是 bower, 防止出现混乱不一致。
更好的语义化: yarn改变了一些npm命令的名称,比如 yarn add/remove,感觉上比 npm 原本的 install/uninstall 要更清晰。
前期工作准备就绪,切入正题。
2.全局安装vue-cli
- 前期准备
vue -V // 可以通过命令查看你以前有没有安装过vue-cli
//或者
vue -version
npm install -g @vue/cli
//安装3.0以上指定版本
// npm install -g @vue/cli@版本号
如过之前已经安装过其他版本的vue-cli,在安装新版本或者指定版本的vu-cli,需要通过命令卸载之前的,命令:
//卸载3.0之前的版本
npm uninstall -g vue-cli
//卸载3.0之后的版本(可以统一使用此指令卸载)
npm uninstall -g @vue/cli
安装了vue-cli后会默认帮我们安装最新版本的vue,我们可以通过npm list vue命令查看默认安装的vue版本。如果我们不想要此版本的vue,我们可以另外安装我们指定版本的vue
npm install vue -g@版本号
2.项目搭建
新建文件夹存放此前端项目
npm install -g @vue/cli-init
//vue-cli2.x的初始化方式,可以使用githab上面的一些模板来初始化项目,webpack是官方推荐的标准模板名
vue init webpack 项目名称 // 创建一个基于 webpack 模板的新项目 old
//vue-cli3.x的初始化方式,目前模板是固定的,模板选项可自由配置
vue create 项目名称
这个自行选择配置,按上下键切换目标选项,按空格键勾选和取消,按a全选,按i反选,选好后回车确定
//1、Babel,转译成浏览器可识别的语言,可以让你的项目支持最新的语法,如es6\es7等
//2、TypeScript,新增的选项卡
//3、PWA,模拟原生app,渐进式网络应用程序(渐进式增强WEB应用)
//4、路由
//5、vuex管理模式
//6、css预处理语言
//7、代码规范
//8、组件单元测试
//9、端对端测试,模拟用户真实场景
3.开发用到的资源包
–save:将保存配置信息到pacjage.json的dependencies节点中。
–save-dev:将保存配置信息到pacjage.json的devDependencies节点中。
dependencies:运行时的依赖,发布后,即生产环境下还需要用的模块
devDependencies:开发时的依赖。里面的模块是开发时用的,发布时用不到它。
// dependencies依赖的包不仅开发环境能使用,生产环境也能使用
"axios": "接口请求",
"babel-polyfill": "语法的解析",
"vue": "vue框架",
"vue-router": "路由跳转",
"vuex": "状态管理器"
"file-saver“:"文件导出"
"vue-count-to": "数字滚动"
....
// devDependencies
// Babel 是一个JavaScript 编译器
"@babel/core": "7.0.0", // es6+语法转换低版本js,以便能够运行在当前和旧版本的浏览器或其他环境中
"@babel/register": "7.0.0", //另一个使用 Babel 的方法是通过 require 钩子(hook)。require 钩子 将自身绑定到 node 的
"@vue/cli-plugin-babel": "3.6.0",
"@vue/cli-plugin-eslint": "^3.12.1",
"@vue/cli-plugin-unit-jest": "3.6.3",
"@vue/cli-service": "3.6.0",
"@vue/test-utils": "1.0.0-beta.29",
"autoprefixer": "^9.7.4", // CSS将仅包含实际的浏览器前缀
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"babel-jest": "23.6.0", // 单元测试
"chalk": "2.4.2", // 颜色模块 chalk 这个包是为了使输出不再单调,添加文字背景什么的,改变字体颜色什么的,
"connect": "3.6.6", // 其作用是基于Web服务器做中间件管理
"eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2", // 自动修复eslint报错
//html-webpack-plugin 该插件的两个主要作用:
//为html文件中引入的外部资源如script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题
// 可以生成创建html入口文件,比如单页面可以生成一个html文件入口,配置N个html-webpack-plugin可以生成N个页面入口
"html-webpack-plugin": "3.2.0",
"less": "^4.1.1",
"less-loader": "^7.3.0", // 将 Less 编译为 CSS 的 loader
"lodash": "^4.17.20",
"mockjs": "1.0.1-beta3",
"sass-loader": "^7.3.1",
"script-ext-html-webpack-plugin": "2.1.3", // HTML Webpack 插件的脚本扩展
"script-loader": "^0.7.2", //在全局上下文(global context)执行一次 JS 脚本。
"serve-static": "^1.13.2", // 静态资源访问
"svg-sprite-loader": "4.1.3", // 处理svg图片
"svgo": "1.2.2", // 用于优化 SVG 矢量图形文件的工具
"vue-skeleton-component": "^1.1.2", // 骨架屏
"vue-template-compiler": "2.6.10", // 该模块可用于将 Vue 2.0 模板预编译为渲染函数(template => ast => render),以避免运行时编译开销和 CSP 限制。大都数场景下,与 vue-loader一起使用,只有在编写具有非常特定需求的构建工具时,才需要单独使用它
"xterm": "^4.8.1" // 前端终端组件
...
"5.0.3",
"~5.0.3",
"^5.0.3"
“5.0.3”表示安装指定的5.0.3版本,“~5.0.3”表示安装5.0.X中最新的版本,“^5.0.3”表示安装5.X.X中最新的版本。
4.webpack 相关
开发环境配置 --build/webpack.dev.config.js
生产环境配置 --build/webpack.prod.config.js
提取公共基础配置文件 --build/webpack.base.config.js
使用 webpack-merge合并配置文件
build/webpack.base.config.js基础文件内容如下
/*
1.配置webpack编译入口
2.配置webpack输出路径和命名规则
3.配置模块resolve规则
4.配置不同类型模块的处理规则 */
'use strict';
const path = require('path');
// node.js的文件路径,用来处理文件当中的路径问题
const baseconfig = require('../config');
//基础环境变量的配置信息
const utils = require('./utils');
//处理css的工具包
const isDev = process.env.NODE_ENV === 'development';
const vueLoaderConfig = require('./vue-loader.config');
// vue-loader.conf配置文件是用来解决各种css文件的,定义了诸如css,less,sass之类的和样式有关的loader
function resolve(dir) {
return path.join(__dirname, '..', dir)
}
// 此函数是用来返回当前目录的平行目录的路径,因为有个'..'
const config = {
context: path.resolve(__dirname, '../'),
//基础目录(绝对路径),用于从配置中解析入口点和加载程序 以应用程序为根目录 普通字符串代表子目录 /代表绝对路径根目录
// 指明入口函
entry: {
app: './src/main.js'
},
// 定义入口文件
// 输出配置项
output: {
// 路径,从config/index读取的,值为:工程目录下的dist目录,需要的自定义的也可以去修改
path: config.build.assetsRoot,
// 发布路径,这里是的值为/,正式生产环境可能是服务器上的一个路径,也可以自定义
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath,
filename: '[name].js'
},
resolve: {
// 当使用require或者import的时候,自动补全下面的扩展名文件的扩展名,也就是说引入的时候不需要使用扩展名
extensions: ['.js', '.vue', '.json'],
// 省略扩展名,比方说import index from '../js/index'会默认去找index文件,然后找index.js,index.vue,index.json文件
// 当我们require的东西找不到的时候,可以去node_modules里面去找,
fallback: [path.join(__dirname, '../node_modules')],
// 别名 来缩短我们需要的路径的长度
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
// 使用别名 使用上面的resolve函数,意思就是用@代替src的绝对路径
},
// 对相应文件的编译使用什么工具的配置
// loader之前的配置,会对.vue,.js的文件用eslint进行编译,include是包含的文件,exclude是排除的文件,可以使用的正则
// 这里也是相应的配置,test就是匹配文件,loader是加载器,
// query比较特殊,当大小超过10kb的时候,会单独生成一个文件,文件名的生成规则是utils提供的方法,当小于10kb的时候,就会生成一个base64串放入js文件中
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{
test: /\.jsx$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [
'style-loader', //将css以js形式插入HTML中
'css-loader', //专门处理css文件
]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,// 文件大小小于10000则编译成base64格式代码
name: utils.assetsPath('resources/images/[name].[hash:8].[ext]') //指定输出文件的名字
},
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,// 文件大小小于10000则编译成base64格式代码
name: utils.assetsPath('resources/mp4/[name].[hash:8].[ext]') //指定输出文件的名字
}
},
{
test: /\.(woff2?|eot|ttf|otf|ico)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,// 文件大小小于10000则编译成base64格式代码
name: utils.assetsPath('resources/icon/[name].[hash:8].[ext]')
}
}
]
},
// 不同文件模块使用不同的loader
node: {
setImmediate: false,
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
}
//这些选项可以配置是否 polyfill 或 mock 某些 Node.js 全局变量和模块。这可以使最初为 Node.js 环境编写的代码,在其他环境(如浏览器)中运行.
};
module.exports = config;
build/webpack.dev.config.js开发环境配置文件:
/*
1.引入相关插件和配置
2.生成处理各种样式的规则
3.配置开发环境,如热更新、监听端口号,是否自动打开浏览器等都在webpack中的devServer中配置完成
4.寻找可利用的端口和添加显示程序编译运行时的错误信息。*/
'use strict';
const path = require('path');
//基础环境变量的配置信息
const utils = require('./utils');
//处理css的工具包
const webpack = require('webpack');
// 引入webpack模块
const merge = require('webpack-merge');
// 将基础配置和开发环境配置或者生产环境配置合并在一起的包管理
const baseWebpackConfig = require('./webpack.base.config');
// 引入基本webpack基本配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 文件名及时更改,自动打包并且生成响应的文件在index.html里面
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
//当前环境的host
const HOST = process.env.HOST;// processs为node的一个全局对象获取当前程序的环境变量,即host
//当前环境的port
const PORT = process.env.PORT && Number(process.env.PORT);
const baseconfig = require('../config');
const isDev = process.env.NODE_ENV === 'development';
const defaultPlugins = [
//webpack编译过程中以及页面上判断环境,js代码中可以引用到,用于区分环境
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: isDev ? '"development"':'"production"'
}
}),
new VueLoaderPlugin(),
//HTMLPlugin:添加HTML入口,可以设置基础参数
new HtmlWebpackPlugin({
template: path.join(__dirname,'../index.html')
})
];
const devServer = {
port: PORT || baseconfig.dev.port, //启动监听端口
disableHostCheck: true,
host: HOST || baseconfig.dev.host,
// 如果编译过程中有错误,将错误显示到网页上
overlay: baseconfig.dev.errorOverlay
? { warnings: false, errors: true }
: false,// warning 和 error 都要显示
compress: true,// 一切服务都启动用gzip方式进行压缩代码
hot: true, // 只重新渲染页面当前组件的效果,而不会刷新这个页面,每次渲染时数据依然存在
//将没有做映射的url路由地址,都映射到index.html中,即当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(baseconfig.dev.assetsPublicPath, 'index.html') },
],
},
open: baseconfig.dev.autoOpenBrowser, // 启动webpack-dev-server时,自动打开网页
proxy: baseconfig.dev.proxyTable,//接口代理
// 如果你有单独的后端开发服务器API,并且希望在同域名下发送API请求,那么代理某些URL将很有用.简称就是API代理,中间件 需引入 http-proxy-middleware
quiet: false, // necessary for FriendlyErrorsPlugin
// 启用quiet后,除了初始启动信息之外的任何内容都不会被打印到控制台。这也意味着来自的WebPack的错误或警告在控制台不可见。
};
const devWebpackConfig = merge(baseWebpackConfig,{
// devtool:'#cheap-module-eval-source-map', //帮助页面上调试代码
module: {
rules: [
{
test: /\.scss/, //css预处理器 后缀名.scss
use: [
'vue-style-loader', //将css以js形式插入HTML中
'css-loader', //专门处理css文件
{
loader: "postcss-loader",
options: {
sourceMap: true, //直接使用前面生成的sourceMap,编译的效率会快点
}
},
'sass-loader' //专门处理sass文件,转为css文件,不处理css
]
}
]
},
devServer:devServer,
plugins: defaultPlugins.concat([
//启动hot加载的功能的plugin
new webpack.HotModuleReplacementPlugin(),// 永远不能用在生产模式,模块热更新,修改文件的内容,允许在运行时更新各种模块,而无需进行完全刷新。
new webpack.NamedModulesPlugin(), // 当进行热更新时,相关文件名会被展示出来
new webpack.NoEmitOnErrorsPlugin(), // 跳过编译时出错的代码并记录,使编译后运行时的包不会发生错误。
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// 该插件可自动生成一个 html5 文件或使用模板文件将编译好的代码注入进去
new CopyWebpackPlugin([//复制插件
{
from: path.resolve(__dirname, '../static'),
to: baseconfig.dev.assetsSubDirectory,
ignore: ['.*']//忽略.*的文件
}
])
]),
});
module.exports = devWebpackConfig;
build/webpack.prod.config.js开发环境配置文件:
/*
1.合并基础的webpack配置
2.配置样式文件的处理规则,styleLoaders
3.配置webpack的输出
4.配置webpack插件
5.gzip模式下的webpack插件配置
6.webpack-bundle分析 */
'use strict';
const path = require('path');
// node.js的文件路径,用来处理文件当中的路径问题
const webpack = require('webpack');
// 引入webpack模块
const CopyWebpackPlugin = require('copy-webpack-plugin');
// 在webpack中拷贝文件和文件夹
const merge = require('webpack-merge');
// 将基础配置和开发环境配置或者生产环境配置合并在一起的包管理
const baseWebpackConfig = require('./webpack.base.config');
// 引入基本webpack基本配置
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 文件名即使更改,自动打包并且生成响应的文件在index.html里面
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');// 压缩css代码
const miniCssExtractPlugin=require("mini-css-extract-plugin"); // css单独提取打包
//一个用来压缩优化CSS大小的东西
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// 一个用来压缩优化JS大小的东西
const VueLoaderPlugin = require('vue-loader/lib/plugin');
const env = require('../config/prod.env');
const utils = require('./utils');
const baseconfig = require('../config');//导入基础配置
const serverConfig = require('../serverConfig.json');//导入,可修改的公共域名
const defaultPlugins = [
//webpack编译过程中以及页面上判断环境,js代码中可以引用到,用于区分环境
new webpack.DefinePlugin({
'process.env': env
}),
new VueLoaderPlugin(),
//HTMLPlugin:添加HTML入口,可以设置基础参数
new HtmlWebpackPlugin({
template: path.join(__dirname,'../index.html'),
inject: true,
minify: {//压缩
removeComments: true,//删除注释
collapseWhitespace: true,//删除空格
removeAttributeQuotes: true//删除属性的引号
},
chunksSortMode: 'dependency'//模块排序,按照我们需要的顺序排序
})
];
//让打包的时候输出可配置的文件
const GenerateAssetPlugin = require('generate-asset-webpack-plugin');
const createServerConfig = function(compilation){
return JSON.stringify(serverConfig);
}
// 引入生产环境
const webpackConfig = merge(baseWebpackConfig,{
// 这一部分会单独打包成类库文件,方便浏览器缓存 会生成一个vendor.js代码,包含类库代码
entry: {
app: path.join(__dirname, "../src/main.js"),
},
output: {
filename: utils.assetsPath('js/[name].[chunkHash:8].js'),
path: baseconfig.build.assetsRoot,
chunkFilename: utils.assetsPath('js/[id].[chunkHash].js')
},
module: {
rules: [
{
test: /\.scss/, //css预处理器 后缀名.scss
use: [
{
loader:miniCssExtractPlugin.loader,
options:{
publicPath: '../'
}
},
'css-loader', //专门处理css文件
{
loader: "postcss-loader",
options: {
sourceMap: true, //直接使用前面生成的sourceMap,编译的效率会快点
}
},
'sass-loader' //专门处理sass文件,转为css文件,不处理css
]
}
]
},
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({}),
],
splitChunks: {
chunks: 'all'
},
runtimeChunk: true // webpack相关代码打包到一个文件中,好处:可以规避新的模块加入的时候,webpack给新的模块加id后,插入的顺序可能在中间,使后面模块id变化,会导致打包出的hash产生变化,这样hash就不能进行常缓存
},
plugins: defaultPlugins.concat([
new miniCssExtractPlugin({filename: 'css/main.[contentHash:8].css'}),
//让打包的时候输入可配置的文件
new GenerateAssetPlugin({
filename: 'serverconfig.json',
fn: (compilation, cb) => {
cb(null, createServerConfig(compilation));
},
extraFiles: []
}),
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: path.join(__dirname, '../dist'),
ignore: ['.*']
},
]),
])
});
module.exports = webpackConfig;
build文件夹下utils.js文件是用来处理css的文件
/*utils是工具的意思,是一个用来处理css的文件*/
'use strict';
const path = require('path');
const baseconfig = require('../config');
//导出文件的位置,根据环境判断开发环境和生产环境,为config文件中index.js文件中定义的build.assetsSubDirectory或dev.assetsSubDirectory
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? baseconfig.build.assetsSubDirectory
: baseconfig.dev.assetsSubDirectory
//Node.js path 模块提供了一些用于处理文件路径的小工具①
return path.posix.join(assetsSubDirectory, _path)
}
config/index.js
'use strict';//严格模式
const path = require('path');
module.exports = {
dev:{
// 开发环境下面的配置
assetsSubDirectory: './static',//子目录,一般存放css,js,image等文件
assetsPublicPath: './',//根目录
proxyTable: {},//可利用该属性解决跨域的问题
host: 'localhost', // 地址
port: 8080, //端口号设置,端口号占用出现问题可在此处修改
autoOpenBrowser: false,//是否在编译(输入命令行npm run dev)后打开http://localhost:8080/页面,以前配置为true,近些版本改为false,个人偏向习惯自动打开页面
errorOverlay: true,//浏览器错误提示
notifyOnErrors: true,//跨平台错误提示
poll: false, //使用文件系统(file system)获取文件改动的通知devServer.watchOptions
devtool: 'cheap-module-eval-source-map',//增加调试,该属性为原始源代码(仅限行)不可在生产环境中使用
cacheBusting: true,//使缓存失效
cssSourceMap: true//代码压缩后进行调bug定位将非常困难,于是引入sourcemap记录压缩前后的位置信息记录,当产生错误时直接定位到未压缩前的位置,将大大的方便我们调试
},
build: {
// 生产环境下面的配置
index: path.resolve(__dirname, '../dist/index.html'),//index编译后生成的位置和名字,根据需要改变后缀,比如index.php
assetsRoot: path.resolve(__dirname, '../dist'),//编译后存放生成环境代码的位置
assetsSubDirectory: './static',//js,css,images存放文件夹名
assetsPublicPath: './',//发布的根目录,通常本地打包dist后打开文件会报错,此处修改为./。如果是上线的文件,可根据文件存放位置进行更改路径
productionSourceMap: true,
devtool: '#source-map',//①
//unit的gzip命令用来压缩文件,gzip模式下需要压缩的文件的扩展名有js和css
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
bundleAnalyzerReport: process.env.npm_config_report
}
}
postcss.config.js:配置css在不同浏览器上的添加前缀
const autoprefixer = require('autoprefixer');
module.exports = {
plugins: [
require('autoprefixer')({
"overrideBrowserslist": [
"defaults",
"not ie < 11",
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
]
})
]
}
vue cli 3.xx
在使用vue-cli3创建项目后,因为webpack的配置均被隐藏了,当你需要覆盖原有的配置时,则需要在项目的根目录下,新建vue.config.js文件,来配置新的配置。
module.exports = {
// 基本路径
publicPath: '/',
// 输出文件目录
outputDir: 'dist',
// eslint-loader 是否在保存的时候检查
lintOnSave: false,
// use the full build with in-browser compiler?
// https://vuejs.org/v2/guide/installation.html#Runtime-Compiler-vs-Runtime-only
runtimeCompiler: false,
// webpack配置
// see https://github.com/vuejs/vue-cli/blob/dev/docs/webpack.md
chainWebpack: () => {},
configureWebpack: () => {},
// vue-loader 配置项
// https://vue-loader.vuejs.org/en/options.html
// vueLoader: {},
// 生产环境是否生成 sourceMap 文件
productionSourceMap: false,
// css相关配置
/*css: {
// 是否使用css分离插件 ExtractTextPlugin
extract: true,
// 开启 CSS source maps?
sourceMap: false,
// css预设器配置项
loaderOptions: {},
// 启用 CSS modules for all css / pre-processor files.
modules: false
},*/
// use thread-loader for babel & TS in production build
// enabled by default if the machine has more than 1 cores
parallel: require('os').cpus().length > 1,
// 是否启用dll
// See https://github.com/vuejs/vue-cli/blob/dev/docs/cli-service.md#dll-mode
// dll: false,
// PWA 插件相关配置
// see https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-pwa
pwa: {},
// webpack-dev-server 相关配置
devServer: {
// open: process.platform === 'darwin',
//将服务启动后默认打开浏览器
open: true,
host: '0.0.0.0',
port: 8080,
https: false,
hotOnly: false,
proxy: {// 设置代理
'/api': {
target: 'http://www.lzzyaf.com',
changeOrigin: true,
pathRewrite: {
'^/api': '/'
}
}
},
before: app => {}
},
// 第三方插件配置
pluginOptions: {
// ...
}
}
5 生命周期
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li>
<a
href="https://vuejs.org"
target="_blank"
>
Core Docs
</a>
</li>
<li>
<a
href="https://forum.vuejs.org"
target="_blank"
>
Forum
</a>
</li>
<li>
<a
href="https://chat.vuejs.org"
target="_blank"
>
Community Chat
</a>
</li>
<li>
<a
href="https://twitter.com/vuejs"
target="_blank"
>
Twitter
</a>
</li>
<br>
<li>
<a
href="http://vuejs-templates.github.io/webpack/"
target="_blank"
>
Docs for This Template
</a>
</li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li>
<a
href="http://router.vuejs.org/"
target="_blank"
>
vue-router
</a>
</li>
<li>
<a
href="http://vuex.vuejs.org/"
target="_blank"
>
vuex
</a>
</li>
<li>
<a
href="http://vue-loader.vuejs.org/"
target="_blank"
>
vue-loader
</a>
</li>
<li>
<a
href="https://github.com/vuejs/awesome-vue"
target="_blank"
>
awesome-vue
</a>
</li>
</ul>
<span class="value">{{value}}</span>
<el-button class="search-btn" size="small" type="primary" @click="handle">点我点我点我</el-button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App',
value: 0
}
},
beforeCreate () {
// 在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,
// 因此无法访问methods, data, computed等上的方法和数据。
console.log('创建前 ')
},
created () {
// 实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,
// watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始, $el属性目前不可见,
// 这是一个常用的生命周期,因为你可以调用methods中的方法,改变data中的数据,
// 并且修改可以通过vue的响应式绑定体现在页面上,
// ,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理,也有一些童鞋喜欢在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,
// 建议在组件路由钩子beforeRouteEnter中完成
console.log('创建后')
},
beforeMount () {
// 挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上
console.log('beforeMount')
},
methods: {
handle () {
this.value += 1
}
},
mounted () {
// 挂在完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。
console.log('mounted')
},
beforeUpdate () {
// 在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程
console.log('更新前')
},
updated () {
// 在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用
console.log('更新后')
},
beforeDestroy () {
// 在实例销毁之前调用,实例仍然完全可用,
// 这一步还可以用this来获取实例,
// 一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件
console.log('销毁前')
},
destroyed () {
// 在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,
// 该钩子在服务器端渲染期间不被调用
console.log('销毁后')
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
.value{
font-size: 24px;
}
</style>
new Vue()
init Event & Lifecycle: 先进行初始化生命周期、事件,但数据代理未开始
beforeCreate:无法通过vm 访问到data中的数据、methods中的方法
init Reactive & Injections : 初始化数据监听,数据代理
created : 可以通过vm 访问到data中的数据、methods中的方法
has ‘el’ option? has ‘template’ option? : 开始解析模板,生成虚拟dom(内存中),还没挂载到页面上(未将虚拟dom渲染成真实dom) 大致过程: 有el 直接挂载到el上 没有 找到 mount() 中挂载的对象,有template 属性直接将页面整个替换,不保留挂载元素,没有直接解析,保留挂载元素
beforeMount : 此时页面呈现的是未经过 vue 编译的dom 结构 (原始dom,例如:{{n}} 会原封不动的显示在页面上,等待vue渲染)
create ‘$el’ and replace ‘el’ with it : 将虚拟dom 转为真实 dom 并插入页面 自己保存一份 留着在比较算法中使用
mounted : 此时页面中显示的是经过 vue 编译的 dom , 至此初始化阶段结束,一般可以在这个阶段进行: 开启定时器、网络请求、绑定自定义事件、订阅消息等。
beforeUpdate : 数据已经改变 但是页面还没更新,页面尚未和数据保持一致
更新数据,生成新的虚拟dom 与旧的虚拟dom 进行比较,重复的复用,不同的更新。完成model -> view 的更新
update : 此时 数据是新的 页面也是新的
当调用 vm.$destroy 进入销毁流程 : 触发beforeDestroy 和 destroyed 钩子,清理当前销毁的实例和其他实例的链接,解绑他的所有指令和(自定义)事件监听器(@click 事件 已经初始化元素的点击事件(原生事件),销毁不了了),此时vm 不在工作, 页面还在,但继续操作各种绑定效果没了。
beforeDestroy : 将要要进行销毁,可以访问函数,但是不会触发更新环节。一般在这个阶段进行:关闭定时器、取消订阅消息、解绑自定义事件等收尾工作。
destroyed :销毁完成。