Vue项目开发学习经历
- 一、准备工作
- 二、知识点
- 1.开发使用less
- 2.Vuetr插件设置
- 3.less-loader依赖
- 4.导入组件
- 5.表单验证规则
- 6.表单重置规则
- 7.axios组件导入
- 8.全局挂载Message提示
- 9.保存token
- 10.Vue登录拦截
- 11.axios——request拦截器
- 12.NavMenu踩雷
- 13.循环生成icon图标字体
- 14.侧边栏装饰
- 15.侧边栏点击跳转路由
- 16.侧边栏默认背景
- 17.表格索引号
- 18.作用域插槽开关
- 19.vue验证规则功能
- 20.分级别显示功能
- 21.弹框删除组件
- 22.vue-table-with-tree-grid插件
- 23.Cascader 级联选择器
- 24.计算属性
- 25.数组分割雷区
- 26.Element-ui文本框自动获取焦点
- 27.过滤器filter处理时间格式
- 28.MessageBox全局注册
- 29.Steps 步骤条与Tab 栏切换双向绑定
- 30.Tabs栏切换函数:before-leave
- 31.图片上传组件Upload
- 32.图片上传成功的事件
- 33.图片移除效果
- 34.图片预览效果
- 35.富文本编辑器
- 36.lodash深拷贝
- 37.Echarts依赖
- 三、项目优化
- 四、打包上线
一、准备工作
前端项目初始化步骤
1.安装Vue脚手架
2.通过Vue脚手架创建项目
3.配置Vue路由
4.配置Element-UI组件
5.配置axios库
6.初始化git仓库
7.将本地项目托管到github
token
在学习的时候接触到了一个新的知识点:token
token登入原理:
客户端与服务器存在跨域问题 不推荐使用session cookie
登入页面输入用户名和密码进行登入,服务器验证通过之后生成该用户的token并返回
客户端存储该token,后续的请求都应该携带该token发生请求
⭐在使用axios向服务器端发请求的时候,如果是使用get方法,则需要在携带参数时,加上params属性
this.$axios.get("goods",{
params:this.queryInfo
})
脚手架整理
1.App.vue根组件删除后效果
<template>
<div id="app"></div>
</template>
<script>
export default {
name:"app",
}
</script>
<style scoped>
</style>
2.router文件夹下的index.js删除后效果
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = []
const router = new VueRouter({
routes
})
export default router
二、知识点
1.开发使用less
在开发时推荐使用less进行页面美化,并且加上scoped保证该美化只对该组件生效。(当时学CSS不太了解scoped属性,现在在vue项目开发中遇到了它)
<style lang="less" scoped>
</style>
2.Vuetr插件设置
在开发的时候,上午使用vue写的好好的代码,下午打开却发现报了一堆错误(心里有点慌),后面想到应该是Vuetr插件的设置问题。
打开Vuetr插件设置,找到图中的三个选项,取消勾选即可
3.less-loader依赖
必须要安装less-loader依赖才能在编译的时候不报错(因为我自己使用的是less语法)
4.导入组件
使用element-ui的时候,一开始报错:
翻译一下是说没有找到这些标签,想了一下是自己在一开始创建项目的时候使用了按需导入。因此我来到了plugins文件夹下,修改element.js
import Vue from 'vue'
import { Button, Form, FormItem, Input, Message,
Container, Header, Aside, Main, Menu,
Submenu, MenuItem } from "element-ui"
Vue.use(Button)
Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.use(Container)
Vue.use(Header)
Vue.use(Aside)
Vue.use(Main)
Vue.use(Menu)
Vue.use(Submenu)
Vue.use(MenuItem
导入Form、FormItem、Input,并在use方法中使用它们。之后发现不报错了。
5.表单验证规则
1.首先要定义一个规则 :rules=“loginRules”
<el-form class="form" :model="form" :rules="loginRules">
2.在data中定义表单规则验证对象
3.给需要验证的表单加上验证规则 prop=" "
6.表单重置规则
1.首先我们要拿到表单引用对象 ref=“reset”
<el-form ref="reset" class="form" :model="form" :rules="loginRules">
2.然后给重置按钮绑定一个单击响应函数
3.在单击响应函数中,调用this.$refs.reset.resetFields()即可
7.axios组件导入
如果表单验证通过,就发送请求,那么这里我选择通过axios发送请求。
在main.js中导入axios并全局配置
import axios from "axios"
Vue.config.productionTip = false
axios.defaults.baseURL = "http://127.0.0.1:8888/api/private/v1"
Vue.prototype.$http = axios
使用this.$http.post()发送请求
使用对象结构并重命名为res的方式获取服务器Promise对象中的data:
const {data:res}= await this.$http.post("login",this.form)
8.全局挂载Message提示
import { Message } from "element-ui"
Vue.prototype.$message = Message
9.保存token
将登录成功之后的token保存在客户端的sessionStorage中
①项目中出了登录之外的其他API接口,必须在登录之后才能访问
②token只应该在当前网站打开期间生效,所以将token保存在sessionStorage中
window.sessionStorage.setItem("token",res.data.token);
10.Vue登录拦截
router.beforeEach((to, from, next) => {
//to表示将要访问的路径
//from代表从哪个路径跳转而来
//next是一个函数表示放行
if (to.path === "/login") {
return next();
} else {
const tokenStr = window.sessionStorage.getItem("token")
if (!tokenStr) {
return next("/login")
} else {
next();
}
}
})
11.axios——request拦截器
11.通过axios——request拦截器添加token,保证拥有数据获取的权限。
//axios拦截器
axios.interceptors.request.use(config => {
config.headers.Authorization = window.sessionStorage.getItem("token")
return config
})
12.NavMenu踩雷
在使用NavMenu 导航菜单时,给index绑定一个item.id属性之后,发现报错:
<el-submenu :index="item.id" v-for="item in menuList" :key="item.id">
从报错信息反映出这个index接收字符串,而我更改index属性之后是一个数字,直接使用最简单的方法解决,在item.id之后加一个空字符串,拼串
<el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id">
13.循环生成icon图标字体
在导出的默认数据内部的data中返回一个icons对象,分别保存对应item.id和想要的图标字体代码,在循环时给class属性绑定,使用中括号,根据item.id找到icons对象中对应的图标字体代码。
<el-submenu :index="item.id+''" v-for="item in menuList" :key="item.id">
<i :class="icons[item.id]"></i>
</el-submenu>
<script>
export default {
data() {
return {
icons:{
"125":"el-icon-user",
"103":"el-icon-lock",
"101":"el-icon-star",
"102":"el-icon-font",
"145":"el-icon-flag",
}
}
},
</script>
14.侧边栏装饰
在做项目的时候想到了一个侧边栏折叠效果,因此我加了一个可以点击的按钮,并且绑定了一个点击事件:
<div class="toggle-button" @click="toggleCollapse">|||</div>
给侧边栏加了一个属性绑定:使用动态开关来决定flag的值。
<!-- 侧边栏菜单 -->
<el-menu :collapse="flag" background-color="#114896" text-color="#fff" active-text-color="#ffd04b"
在script中,data定义了一个flag开关;methods定义了toggleCollapse方法。
data() {
return {
//是否折叠
flag:false
}
},
methods: {
toggleCollapse(){
//取反状态
this.flag=!this.flag
}
}
在万事俱备以后,给侧边栏的宽度进行动态修改
<!-- 侧边栏 -->
<el-aside :width="flag?'64px':'200px'">
15.侧边栏点击跳转路由
在element-ui中的Menu Attribute有一个router属性,启用该模式会在激活导航时以 index 作为 path 进行路由跳转。
因此我给侧边栏菜单开启了这个属性
<el-menu :router="true" background-color="#114896" text-color="#fff" active-text-color="#ffd04b" unique-opened :collapse="flag"
:collapse-transition="false">
修改对应的index让它符合规则
:index="'/'+subItem.path+''"
16.侧边栏默认背景
(在methods中使用this.XXX就是在访问data里面的数据名称)
给点击到的侧边栏加一个默认背景,使用default-active属性
与14号知识点差不多的思路,但是这里使用到了sessionStorage,通过它来存储点击到的path路径,然后赋值给default-active属性
⭐这里就不演示代码了
17.表格索引号
Element-UI组件中给表格加上一个索引号,使用type=“index”
<el-table-column type="index"></el-table-column>
18.作用域插槽开关
作用域插槽渲染状态(mg_state)开关;slot-scope="scope"接收服务器的数据,提取其中的scope.row.mg_state,双向绑定在el-switch上
<el-table-column label="状态">
<template slot-scope="scope">
<!-- {{scope.row.mg_state}} -->
<el-switch v-model="scope.row.mg_state" active-color="#13ce66"></el-switch>
</template>
</el-table-column>
19.vue验证规则功能
添加用户的手机号和邮箱时,不能使用普通的验证(例如对用户名、密码),此时需要在script标签中定义验证规则函数,然后使用validator属性接收定义好的验证规则函数。(validator接收一个函数)
<script>
export default {
data() {
//验证规则
var checkemail=(rule,value,callback)=>{
const reg=/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/;
if(reg.test(value)){
return callback();
}
callback(new Error("请输入合法的邮箱"))
}
return {
rules:{
email:[
{required:true,message:"请输入邮箱",trigger:"blur"},
//validator属性接收
{validator:checkemail,trigger:"blur"}
],
}
}
}
</script>
20.分级别显示功能
先说明一下开发这个功能的想法:每一个用户都有不同的角色,而不同的角色对应着不同的权限,这个时候就需要区别对待。
但是逐一渲染非常麻烦,因此我想起了v-if属性,通过组件插槽这个功能拿到数据,使用v-if与拿到数据中的等级对比,从而在页面上渲染对应的等级
<el-table-column label="权限等级" prop="level">
<template slot-scope="scope">
<el-tag v-if="scope.row.level==='0'">一级</el-tag>
<el-tag v-if="scope.row.level==='1'" type="success">二级</el-tag>
<el-tag v-if="scope.row.level==='2'" type="warning">三级</el-tag>
</template>
</el-table-column>
21.弹框删除组件
给弹框删除的元素绑定一个函数事件,使用element-ui提供的函数主体即可,函数源码如下:
async remove(){
const confirm = await this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).catch(err=>err)
}
if(confirm!==confirm){
return this.$message.info("取消删除")
}
22.vue-table-with-tree-grid插件
main.js入口文件导入
import TreeTable from "vue-table-with-tree-grid"
Vue.component("tree-table", TreeTable)
官方文档:https://github.com/MisterTaki/vue-table-with-tree-grid
23.Cascader 级联选择器
分级别的选择功能运用场景还挺多,里面有几个需要注意的属性知识点:
I.options用来指定数据源
II.props用来指定配置对象
III.v-model用来保存选中数据的id
<el-cascader
v-model="selectvalue"
:options="parentCateList"
:props="{ expandTrigger:'hover',value:'cat_id',label:'cat_name',children:'children' }"
@change="handleChange"
clearable change-on-select
></el-cascader>
24.计算属性
在编写项目的时候,需要根据数组的长度来判断是否禁用按钮,于是我想到了利用计算属性computed。
// 给按钮绑定disabled
<el-button :disabled="isBtndisabled" type="primary" size="mini">添加参数</el-button>
computed: {
//计算属性 如果按钮需要被禁用则返回true
isBtndisabled(){
if(this.seleteCateList.length!==3){
return true
}
return false
}
},
25.数组分割雷区
使用split()方法对数组进行分割时,如果对一个空数组进行空格分割,则结果是得到一个空格(而不是空数组),会导致渲染数据的时候,明明没有数据,浏览器却渲染出了一个空格!
使用三元表达式进行判断,如果这个数组为空,则直接返回空数组,不调用split方法。
res.data.forEach(item => {
item.attr_vals = item.attr_vals?item.attr_vals.split(" "):[];
})
26.Element-ui文本框自动获取焦点
//$nextTick方法的作用,就是当页面上的元素被重新渲染之后,才指定回调函数中的代码
//第二行是获取页面上的Tag标签,调用focus()方法
this.$nextTick(_ => {
this.$refs.saveTagInput.$refs.input.focus();
});
27.过滤器filter处理时间格式
在对日期进行处理的时候,需要使用filter
首先在全局中定义一个处理函数来处理日期格式
⭐padStart()方法: 用于头部补全补全字符串,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。
Vue.filter("dateFormat", function(origin) {
const dt = new Date(origin)
const y = dt.getFullYear()
const m = (dt.getMonth() + 1 + "").padStart(2, "0")
const d = (dt.getDate() + "").padStart(2, "0")
const hh = (dt.getHours() + "").padStart(2, "0")
const mm = (dt.getMinutes() + "").padStart(2, "0")
const ss = (dt.getSeconds() + "").padStart(2, "0")
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
})
接着在vue文件中使用作用域插槽来使用过滤器
<el-table-column width="180px" prop="add_time" label="创建时间">
<template slot-scope="scope">
{{scope.row.add_time | dateFormat}}
</template>
</el-table-column>
28.MessageBox全局注册
在调用Element-ui之MessageBox组件时,忘记全局注册而导致报错
提示我this.$confirm is not a function,我明明引用了组件为什么还报错,仔细一想我是在全局中进行使用,于是在element.js中全局注册了一下,完美的解决了这个问题
Vue.prototype.$confirm = MessageBox.confirm
29.Steps 步骤条与Tab 栏切换双向绑定
//active属性指定step的显示,在data中预先定义了一个activeIndex
<el-steps align-center :space="200" :active="activeIndex-0" finish-status="success">
<el-step title="基本信息"></el-step>
<el-step title="商品参数"></el-step>
<el-step title="商品属性"></el-step>
<el-step title="商品图片"></el-step>
<el-step title="商品内容"></el-step>
<el-step title="完成"></el-step>
</el-steps>
//v-model与activeIndex进行绑定,而name属性值存储在v-model中,点击不同的tab栏更改name,更改v-model,从而实现双向绑定
<el-tabs v-model="activeIndex" :tab-position="'left'" style="height: 200px;">
<el-tab-pane name="0" label="基本信息">基本信息</el-tab-pane>
<el-tab-pane name="1" label="商品参数">商品参数</el-tab-pane>
<el-tab-pane name="2" label="商品属性">商品属性</el-tab-pane>
<el-tab-pane name="3" label="商品图片">商品图片</el-tab-pane>
<el-tab-pane name="4" label="商品内容">商品内容</el-tab-pane>
</el-tabs>
30.Tabs栏切换函数:before-leave
<el-tabs :before-leave="beforeTabLeave"></el-tabs>
methods: {
beforeTabLeave(activename,oldactivename){
console.log("即将离开的标签页是"+oldactivename)
console.log("即将进入的标签页是"+activename)
}
}
31.图片上传组件Upload
这里记录一个bug:在上传的时候upload组件并没有使用项目设置的token,因此上传是失败的,使用headers设置上传的请求头部即可
<!-- action表示图片上传到的后台API地址 -->
<!-- list-type="picture" 指定缩略图 -->
<!-- :headers="headerObj" 指定请求头token -->
<el-upload
:headers="headerObj"
action="http://127.0.0.1:8888/api/private/v1/upload"
:on-preview="handlePreview"
:on-remove="handleRemove"
list-type="picture"
>
data() {
return{
//图片请求头对象
headerObj:{
Authorization:window.sessionStorage.getItem("token")
}
}
}
32.图片上传成功的事件
通过调用图片上传成功时触发的函数,得到图片信息对象
之后将图片信息对象的push到存储图片的数组中
const picInfo = { pic: response.data.tmp_path };
//将图片信息对象的push到pics数组中
this.addForm.pics.push(picInfo);
33.图片移除效果
通过调用图片移除时触发的函数,获取图片路径。
之后调用findIndex方法,在存储所有图片的数组中找到要移除的图片的索引号,使用一个参数接收。
之后调用splice方法移除该图片
const filePath = file.response.data.tmp_path;
const i = this.addForm.pics.findIndex((x) => {
x.pic === filePath;
});
this.addForm.pics.splice(i, 1);
34.图片预览效果
使用el-dialog组件弹出一个对话框,在对话框中放对应的图片:
<el-dialog title="图片预览" :visible.sync="dialogVisible" width="50%">
<img :src="previewPath" class="previewimg">
</el-dialog>
data() {
//定义图片的路径
previewPath:""
}
method:{
handlePreview(file){
//拿到预览图片的路径并赋值
this.previewPath = file.response.data.url;
this.dialogVisible=true
}
}
35.富文本编辑器
启动vue ui,在运行依赖中输入Vue-Quill-Editor,安装
Mount with global:
import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css' // import styles
import 'quill/dist/quill.snow.css' // for snow theme
import 'quill/dist/quill.bubble.css' // for bubble theme
Vue.use(VueQuillEditor /* { default global options } */)
Component:
<quill-editor v-model="addForm.goods_introduce"></quill-editor>
36.lodash深拷贝
启动vue ui,在运行依赖中输入lodash,安装
//导入
import _ from "lodash"
//cloneDeep()
//获得拷贝对象
const from = _.cloneDeep(this.addForm)
from.goods_cat = from.goods_cat.join(",")
37.Echarts依赖
官方文档:https://echarts.apache.org/zh/index.html
运行vue ui ,在运行依赖中搜索Echarts,安装
//1.导入echarts
import echarts from "echarts";
//2.为ECharts准备一个具备大小(宽高)的Dom
<div id="main" style="width: 750px;height:400px;"></div>
//3. 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById("main"));
//4. 指定图表的配置项和数据
const result = _.merge(res.data,this.options)
//5.展示数据
myChart.setOption(result);
在第4步的时候,使用了lodash的对象合并merge()方法,在36项知识点(使用_)已经导入。
三、项目优化
1.生成打包报告
在项目打包之后,可以看到打包报告。速度统计是在不同网络下打开所需时间。
体积过大的依赖项我们需要优化,来提升用户的浏览体验
2.路由懒加载
当打包构建项目时,JavaScript包会变得非常大,影响页面加载。我们需要把不同的路由对应的组件分割成不同的代码块,当路由被访问的时候在加载对应组件。
①安装@babel/plugin-syntax-dynamic-import包
②在babel.config.js文件下声明该插件
module.exports = {
plugins: [
"@babel/plugin-syntax-dynamic-import"
]
}
③将路由改为按需加载模式(示例一项)
//import Login from '../components/Login.vue'
const Login = () =>
import ( /* webpackChunkName: "login_home_welcome" */ '../components/Login.vue')
3.首页内容定制
所谓的首页内容定制,就是动态的渲染title标签:
根据环境不同(开发环境、发布环境),给title加上不同前缀
来到vue.config.js文件,在发布环境和开发环境新增一个回调函数,找到plugin下的html插件,通过调用tap加一个可控的属性args[0].isProd
module.exports = {
lintOnSave: false,
chainWebpack: config => {
//发布模式
config.when(process.env.NODE_ENV === 'production', config => {
config.plugin("html").tap(args => {
args[0].isProd = true
return args
})
})
//开发模式
config.when(process.env.NODE_ENV === 'development', config => {
config.plugin("html").tap(args => {
args[0].isProd = false
return args
})
})
}
}
创建了动态参数属性后,来到public文件夹下,找到index.html
使用art-template模板的原文输出给title加上之前定义的isProd进行改造:
<title>
//这里使用了art-template模板的原文输出
<%= htmlWebpackPlugin.options.isProd ? "":"dev-" %>电商后台管理系统
</title>
4.nprogress进度条
在Vue项目中,我们不需要使用npm install安装,在命令行窗口输入vue ui,在依赖栏的运行依赖中,搜索nprogress安装即可!
官方文档:https://github.com/rstacruz/nprogress
⭐最重要的两个函数
NProgress.start();
NProgress.done();
//在入口文件main.js导入nprogress的JS和CSS
import NProgress from "nprogress"
import "nprogress/nprogress.css"
//request拦截器中展示进度条
axios.interceptors.request.use(config => {
NProgress.start()
config.headers.Authorization = window.sessionStorage.getItem("token")
return config
});
//response拦截器中隐藏进度条
axios.interceptors.response.use(config => {
NProgress.done()
return config
})
5.babel-plugin-transform-remove-console
去除打包环境下的console警告。
vue ui开发依赖中搜索babel-plugin-transform-remove-console,安装
之后再babel.config.js文件中编写下列代码
//这是项目发布阶段需要用到的babel插件
const prodPlugins=[]
if(process.env.NODE_ENV==="production"){
prodPlugins.push("transform-remove-console")
}
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
],
plugins: [
[
'component',
{
libraryName: 'element-ui',
styleLibraryName: 'theme-chalk'
}
],
//在项目开发的时候才运行这个插件
...prodPlugins
]
}
6.vue.config.js配置webpack打包
找到入口文件main.js,全选复制里面的代码,然后删除该文件,新建两个新的文件main-prod.js、main-dev.js,都粘贴原先main.js中的代码。
然后找到vue.config.js文件,编写下列代码:
module.exports = {
lintOnSave: false,
chainWebpack: config => {
//发布模式
config.when(process.env.NODE_ENV === 'production', config => {
//entry找到默认的打包入口,调用clear则是删除默认的打包入口
//add添加新的打包入口
config.entry('app').clear().add('./src/main-prod.js')
})
//开发模式
config.when(process.env.NODE_ENV === 'development', config => {
config.entry('app').clear().add('./src/main-dev.js')
})
}
}
7.第三方库启用CDN(externals)
在6步骤的基础上新增externals设置排除项
module.exports = {
lintOnSave: false,
chainWebpack: config => {
//发布模式
config.when(process.env.NODE_ENV === 'production', config => {
//entry找到默认的打包入口,调用clear则是删除默认的打包入口
//add添加新的打包入口
config.entry('app').clear().add('./src/main-prod.js')
//使用externals设置排除项
config.set('externals', {
vue: 'Vue',
'vue-router': 'VueRouter',
axios: 'axios',
lodash: '_',
echarts: 'echarts',
nprogress: 'NProgress',
'vue-quill-editor': 'VueQuillEditor'
})
})
//开发模式
config.when(process.env.NODE_ENV === 'development', config => {
config.entry('app').clear().add('./src/main-dev.js')
})
}
}
之后找到public文件夹下的index.html文件,在head添加下列代码
<!-- nprogress 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" />
<!-- 富文本编辑器 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.core.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.snow.min.css" />
<link rel="stylesheet" href="https://cdn.staticfile.org/quill/1.3.4/quill.bubble.min.css" />
<script src="https://cdn.staticfile.org/vue/2.5.22/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.staticfile.org/axios/0.18.0/axios.min.js"></script>
<script src="https://cdn.staticfile.org/lodash.js/4.17.11/lodash.min.js"></script>
<script src="https://cdn.staticfile.org/echarts/4.1.0/echarts.min.js"></script>
<script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
<!-- 富文本编辑器的 js 文件 -->
<script src="https://cdn.staticfile.org/quill/1.3.4/quill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-quill-editor@3.0.4/dist/vue-quill-editor.js"></script>
8.Element-UI组件按需加载
与第7步骤有一点不同,要在main-prod.js文件中注释(或删除)element-ui代码
// import './plugins/element.js'
之后找到public文件夹下的index.html文件,在head添加下列代码
<!-- element-ui 的样式表文件 -->
<link rel="stylesheet" href="https://cdn.staticfile.org/element-ui/2.8.2/theme-chalk/index.css" />
<!-- element-ui 的 js 文件 -->
<script src="https://cdn.staticfile.org/element-ui/2.8.2/index.js"></script>
⭐7.8步骤均为优化依赖项体积的操作。
四、打包上线
1.打包最终的dist
在终端中输入vue ui,找到任务栏的build点击运行,结束后生成一个dist文件。
新创建一个文件夹,用来存放打包上线的所有资源。
①使用npm init -y初始化一个package.json文件
②使用npm install express -S安装Express,用于搭建网站服务器,要在电脑上先安装node
③新建一个文件app.js编写服务器代码
const express = require("express")
const app = express();
app.use(express.static("./dist"))
app.listen(80, () => { console.log("server running at http://127.0.0.1") })
④把dist文件夹移动到打包上线的文件夹,成效如图:
2.开启gzip配置
使用gzip减小文件的体积,更快速的打开网页
使用npm install compression -D安装
在1步骤的基础上,来到app.js文件编写代码
const express = require("express")
const compression = require("compression")
const app = express();
//一定要把compression写到静态资源托管之前
app.use(compression())
app.use(express.static("./dist"))
app.listen(80, () => { console.log("server running at http://127.0.0.1") })
3.pm2管理应用
使用pm2来解决打开网站必须运行在终端的问题。即可以通过配置达到不需要启动终端以打开网站的效果
①cmd命令行工具输入:npm i pm2 -g
②在打包上线的文件夹下命令行工具输入:pm2 start .\app.js --name web_vueshop
③查看运行项目:pm2 ls
④重启项目:pm2 restart id/项目名称
⑤停止项目:pm2 stop id/项目名称
⑥删除项目:pm2 delete id/项目名称
到此为止,所有的项目功能均已开发完毕!!