前言
当前总结是本人在业余学习与实践过程后的总结与归纳,旨在检验自己的积累,也方便忘记时查阅,同时也希望能帮助那些这方面知识匮乏的同行门,总结是基于 vue2.x , vue-cli3.x ,主要记录些, vue 常用的指令、事件,监听、数据绑定、过滤器、组件、动画、 vuex , vue-router 等日常工作中时常用到的东西,也有些常用的 插件 和 开发工具 的介绍与使用,以及部分 性能优化 的建议与实践,如有不对,或不足的地方,也请各位大神,指出来,学习学习。
vue2.x
vue-cli3.x
vue
vuex
vue-router
插件
开发工具
性能优化
目录
1. 基础
1.1 理解mvvm
1.2 常用指令
3. 性能优化
4. 插件的介绍和使用
m
data
mvc
model
vm
v
mvvm
html
v-cloak
v-text
v-html
v-bind
v-on
@
stop
prevent
a
capture
self
once
v-modle
tips: 表单元素 radio text address email select checkbox textarea
radio
text
address
email
select
checkbox
textarea
1、数组带对象
<div :class="[classA,classB,{'classC':flag}]" > data(){ return{ flag:true }
tips: 可以在类中的数组中写三元表达式,但推荐使用对象来代替它控制是否渲染
2、单纯的对象
<div :class="{classA:falg1,classB:flag2}" /> data(){ return{ falg1:true, falg2:true }
3、数组带三元
<div :class="['ac','bd',falg?'active','']" / > data(){ return{ falg:true, }
4、对象升级
<div :class="classObj" /> data(){ return{ classObj:{classA:falg1,classB:flag2} }
tips: 直接使用一个对象数组来控制样式
5、使用 style 的对象来实现样式的修改
style
<div :class="styleObj" /> data(){ return{ styleObj:{color:red} }
6、使用 style 的数组带对象来实现样式的修改
<div :class="[styleObj1,styleObj2]" /> data(){ return{ styleObj1:{color:red}, styleObj2:{color:red} }
可以遍历: 普通数组,对象数组,对象,还可以是数字
<div v-for='(item,key,index) in object' :key='index'> {{item}}--{{key}}--{{index}} <div v-for='(count in 10)'> </div>
tips: 在遍历对象的时候有多个 index 索引,遍历数字时是从 1 开始的。绑定 key 时属性值必须是 number 或者 string
index
key
number
string
v-if
v-show
vue-devtools
debugger
<div v-for='(item,key) in object' :key='index'> {{item | dateFormat}} <div v-for='(count in 10)'> </div>
全局
vue.filter('过滤器名称',function(){ })
私有(局部)
filters:{ dateFormat:function(data,param){ do some }
tips:
|
padstart
padend
es6
0
简单的过滤用过滤器
方法
计算属性
<input @keyup.enter='方法名'></input>
tips: enter 可以换成键盘上的任何一个值,只要去找相关的键盘码,就都可以使用,推荐设置个别名,放在没有按钮操作的模板。
enter
Vue.config.keyCodes.f2=113 , 就可使用了
Vue.config.keyCodes.f2=113
tips: f2 修饰符是 vue 里没有定义的自己创建。
f2
定义的指令都要按规定去创建在 bind 和 inserted 还有 updated 中去创建
bind
inserted
updated
Vue.directive('focus'{ //每当指令绑定到元素上的时候,会立即执行bind 函数,只执行一次, 注意:在元素刚绑定元素的时候,还没有插入到dom中去,这时候,调用focus方法没有作用,即放在focus 放在bind中是不起作用 的 bind:function(el,binding){ el.style.color=binding.value //表示元素插入到dom中的时候,只执行一次 inserted:function(){ el.focus() js行为放在这里去创建 //当组件更新的时候,可能会触发多次 updated:function(){}, })
tips:
参数1
参数2
el
js
第二个参数可以是用户传进来值 bingding.value
bingding.value
directives:{ '指令名':{ bind:function( el,b){ }
3. 简写
'指令名':function(el,binding){ } //注意这个function 等同于 把代码写到bind和update中去
tips: 样式相关的指令放在 bind 中, js 行为相关的放在 inserted 中比较合适,防止指令不生效。使用场景 写组件时可以用这个去改样式
beforeCreate()
created()
beforeMount()
beforeMount
mounted()
beforeUpdate()
update()
dom
DOM
data(model层)->view(视图层)
beforeDestory
Vue
beforeDestroy
methods
过滤器、指令...
destroyed
数据,方法,指令,过滤器...
1. vue的内置动画
<style> .v-enter, .v-leave-to{ opacity:0; transform:translateX(150px) --这东西是位移 .v-enter-active, .v-leave-active{ transition:all 0.4s ease; </style>
<transition name='my'> <h3 v-if="flag"></h3> </transition>
<script> data(){ return { flag:false </script>
2. 使用第三方类实现动画
<transition enter-active-class="bounceIn" leave-avtive-class="bounceOut" duration='200' <h3 v-if="flag" class="animated" ></h3> </transition>
3. 在属性中声明js钩子 实现半场动画(只需要进场,不需要离场)
<transition @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" </transition>
<transition v-show="flag" @before-enter="beforeEnter" @enter="enter" @after-enter="afterEnter" </transition>
<script> methods:{ beforeEnter(el){ //动画入场之前,此时动画尚未开始, 可以在beforeEnter中设置元素开始动画之前的初始位置 el.style.transform= "translate(0,0)" enter(el,done){ /*这句话,没有实际的作用,但是,如果不写,出不来动画效果,可以认为 这个会强制刷新动画,ofset触发了重绘重排导致动画更新了*/ el.offsetWidth el.style.transform= "translate(150px,450px)" el.style.transition='all 1s ease' /*这里的done 代表着 afterEnter的引用, 这个会立即执行afterEnter 否则会有延时 done() afterEnter(el){ /*动画完成之后,会调用afterEnter */ this.flag=!this.flag </script>
4. 在实现列表过渡的时候,如果需要过渡的元素,是通过 v-for 循环渲染出来的,不能使用 transition 包裹,需要使用 transitionGroup
v-for
transition
transitionGroup
<transition-group appear tag='ul'> <li v-for > </transition-group>
.v-enter, .v-leave-to{ opacity: 0; transform:translateY(80x); .v-enter-active, .v-leave-active { transition: all 0.6s ease; /*离开后下一个东西没有动画使用这个可以使用动画实现下一个东西渐渐地飘上来的效果,要和 v-leave-active的absolute 配合 固定写法*/ .v-move { transition:all 0.6s ease .v-leave-active{ /* absolute 有个特点元素默认宽度就是最小值,要在元素上添加width:100%*/ }
<transition mode="out-in"> <component :is="comName" > </component> </transition>
v-enter
v-leave-to
v-enter-active
v-leave-active
animated
duration=200
对象
duration="{enter:200,leave:400}"
appear
transition-group
tag
span
mode="out-in" 先过渡再进来,防止有阴影,通过
注意:最外层一定要用 transition 包裹着,动画似乎升级了,可以在 transition 标签中加入 name 属性,并且在 css 样式中把 v ,替换为你的 name 属性值。
name
css
1.使用Vue.extend 来创建全局的Vue组件
var coml=Vue.extend({ template:'<h3>这是使用Vue.extend 创建的组件</h3>' })
//第一个参数组件名称,第二个参数创建出来的组件模板对象 Vue.component('myComl',coml)
<my-coml><my-coml/>
2.使用 vue.component 来创建组件
Vue.component('mycom2',{ template:'<div> 这是直接使用Vue.component 创建出来的组件 </div>' })
3.使用 template 来创建组件
<template id='tmp1'> 这里通过template元素,在外部定义的组件结构,这个方式,有代码的智能提示和高量 </template> Vue.component('mycom3',{ template:'#tem1' })
4.私有组件 componment
<template id='temp2'> <h1>这是私有login组件</h1> </template> componment:{ login: template:'tmpl2' }
Vue.component
Vue.extend
template
实例
实例外部
其他实例
1、组件里的切换 可以用 v-if 和 v-else 进行切换即标签页切换
v-else
<a href="" @click.prevent="flag=true" </a>
<a href="" @click.prevent="flag=flase" </a>
2、 vue 提供了 component ,来展示对应名称的组件
component
//component 是一个占位符 :is属性,可以用来指定要展示的组件的名称 写死的时候这个组件名要是个字符串,动态绑定时key普通写法就好,但value必须是字符串。 <component :is="'componentId'"> </component> <component :is="oneName"> </component> data(){ return{ oneName:"login", }
1、父子组件传值,通过 v-bind:(:) 来传值,通过 props 来接收值
v-bind:(:)
props
2、父组件用事件绑定机制传递 方法 给子组件— v-on 简写 @
//父组件中 <component-name :children='children' //传值 @handle='show' //绑定方法 </component-name> data(){ return(){ children:11 methods:{ show(data){ }
3、 emit 英文原意: 是触发,调用,发射的意思。 @handle=show 父组件传 show 方法给子组件。 子组件接收父组件的方法,并用 $emit 把子组件的值传给父组件
emit
@handle=show
show
$emit
//子组件中 methods:{ handle(){ this.$emit('func',{ age:1, name:'搞事' }
4、在父组件中接收子组件所有参数的同时,添加自定义参数
1.子组件传出单个参数时: // 子组件 this.$emit('test',this.param) // 父组件 @test='test($event,userDefined)' 2.子组件传出多个参数时: // 子组件 this.$emit('test',this.param1,this.param2, this.param3) // 父组件 arguments 是以数组的形式传入 @test='test(arguments,userDefined)'
tips:子组件中的 data 数据,并不是通过 父组件传递过来的,而是子组件自身私有的,比如子组件通过 ajax ,请求回来的数据,都可以放到 data 身上, data 上的数据都是可读可写的;
ajax
<h3 id='myh3' ref='myh3'> </h3> methods:{ getElement(){ console.log( this.$refs.myh3.innerText) }
//组件也可以使用ref,让父组件调用子组件里的方法和属性值 <login ref='mylogin'> </login> methods:{ getElement(){ //父组件调用子组件里的属性值 console.log(this.$refs.mylogin.msg) }
refs
s
ref
reference
1、占位符
这是 vue-router 提供的元素,专门用来 当作占位符的,将来,路由规则,匹配到的组件,就会展示到这个 router-view 中去,所以我们可以把 router-view 认为是一个占位符
router-view
<router-view></router-view>
2、路由切换模板
路由切换模板写法,默认渲染为一个 a 标签,使用 tag 的 span 可以用来转换模板的标签名
<router-link to="/login" tag='span' > </router-link>
3、路由配置
new VueRouter({ //路由匹配规则 routes:[ path:'/', redirect:'/login' path:'login', component:login path:'/register', component:register //路由高亮的类名 linkActiveClass:'myactive' var vm=new Vue({ el:'#app', data:{}, methods:{}, router //将路由规则对象注册到vm实例上,用来监听Url地址的变化,然后展示对应的组件。 })
4、路由传参
query
//获取id this.$route.query.id
path
//参数要一一对应不可缺失,不然可能会 造成路由的不匹配 < router-link to="/login/12/ls" path:'/login/:id/:name',component:login }
params
5、子路由
<router-link to="/account/login" </router-link>
routes:[{ path:'/account', component:account, children:{ { path:'login', component:login } }}]
/
url
to
注意: componen 属性值,必须是一个组件的模板对象,不能是组件的引用名称
componen
根据 name 来找组件
<router-view></router-view> <router-view name="left"></router-view> <router-view name="main"></router-view>
var header={ template:'<h1>header</h1>' var leftBox={ template:'<h1>leftBox</h1>' var mainBox={ template:'<h1>mainBox</h1>' }
{ path:'/',components:{ 'default':header, 'left':leftBox, 'main':mainBox }
监听非 dom 元素
watch:{ 'obj.a'(newValue,oldValue){ }, immediate:false }
watch:{ 'obj':{ handler (newValue, oldValue) { deep:true //深程度监听 性能消耗大 }
watch:{ //监听路由 '$route.path':{ handler (newValue, oldValue) { //immediate:true代表如果在 wacth 里声明了之后,就会立即先去执行里面的handler方法,如果为 false就跟我们以前的效果一样,不会在绑定的时候就执行 immediate:true }
obj.a
handle +immediate:true
obj
handle+deep true
handle
watch
computer
computed:{ 'fullname':(){ return }
render:function(createElements){ //createElements是一个方法,调用它,能够把指定的 组件模板 渲染为html结构 return createElements(login) //注意 这里 return 的结果,会替换页面中el 指定的那个容器 }
tips: render 和 components 区别 render 会把整个 app 里组件全部覆盖掉一个 app 中只能放一个 render 组件 components 可以多个,且不会覆盖。
render
components
app
1、写插槽
<div v-if="layout === 'block'" class="layout-block" :class="scroll?'layout-scroll':''"> <slot></slot> //匿名插槽 <!-- 左右块 --> <div v-if="layout === 'both'" class="d-flex jc-between"> <div class="layout-both" :class="scrollLeft?'layout-scroll':''"> <slot name="left"></slot> //有名字的插槽 <div class="layout-both" :class="scrollRight?'layout-scroll':''"> <slot name="right"></slot> </div>
2、使用插槽
//有名字的插槽 # v-slot的缩写是# <template #left></template> <template v-slot="left" > </template>
tips:区别对待 v-slot="" 和 v-slot:name; = 和 : 的区别 一个是 slot 的 name 一个是父组件获取子组件的数据,插槽一定要用 template 包裹着
<template> 插槽的内容 </template>
2. 杂项
安装 nrm
nrm
npm i nrm -g
nrm ls
nrm use npm
npm use
tips: nrm 只是单纯的提供几个常用的下载包 url 地址,并能够让我们在这几个地址之前,很方便的进行切换,但是,我们每次装包的时候,使用的装包工具,都是 npm 和 npm i cnpm -g 不一样。
npm
npm i cnpm -g
在网页中会引用哪些常见的静态资源
webpack-dev-server 实现自动打包功能,浏览器不用刷新也能看到文件已经修改,打包的文件并没有放在实际的物理磁盘上,而是直接托管到了,电脑的内存中,所以,我们在项目根目录中,根本找不到这个打包好的文件,这文件和 src 、 dist 、 node_modules 平级,有一个看不见的文件。
webpack-dev-server
src
dist
node_modules
hot 网页不重载 直接更新 加快打包速度 不生成新文件
hot
"scripts":{ "dev":"webpack-dev-ser ver --open --prot 3000 --contentBase src --hot " }
配置文件中配置热更新
devServer:{ hot:true 就热更新了 }
tips: webpage 当中带 s 都是数组
webpage
在 webpack 中使用以下方式导入的 Vue 构造函数,功能并不完善,只提供了 runtime-only 的方式,并没有提供 像网页中那样的使用方式;
webpack
runtime-only
阉割版 import Vue from 'vue' import Vue from '../node_modules/vue/dist/vue.js' module.exports={ resolve:{ //设置 Vue被导入的时候的包的路径 alias:{ "vue$":"vue/dist/vue.js" }
tips: 包的查找规则
package.json
main
webpake
如果想要通过 vue ,把一个组件放到页面中去展示, vm 实例中的 render 函数可以实现
render:function(createElement){ return createElement(login) //就一行可以省略{} 并且没有花括号默认就有return, 简写: render: c => c(login)
tips: webpack 中如何使用 Vue
.vue
loader
main.js
import Vue from 'vue'
import login from './login.vue'
var vm = new Vue
({el:'app',render:c=>c(login)})
id
div
export default
export
import
const arr={ a:'1', b:'2' export default arr /* export default { 这个暴露是错误的所以当前注释 一个js文件中只能暴露一次 address:'北京' export title=1 import arr, {title as title1 } from '/xxx.js'
router-link
el: '#app'
Account
GoodsList
标签页
样式的 scoped 是通过 css 的属性选择器来实现的 .aa[vsfp]{color:red}
scoped
.aa[vsfp]{color:red}
tips: vsfp 是哈希值
可以映射本地 80 端口,把本地的映射为外网
80
//npm下载 --感觉下的有点慢 换个路径下比较好 npm install ngrok -g ngrok http 80
tips: 需要开启本地服务器,映射后只是映射 www 路径,不是完整的程序路径需要自己去补充完整
//第一种 图片质量小的可以自动转换为base64的 img: require("@/../public/img/home/user.jpg ") //第二种 这里可以把最前面的 / 看做是public /img/abnormal/Trash.png 即 public/img/abnormal/Trash.png
tips: @是指 src 目录 .. @ 的上一级目录,再进入 public
watch 如果是 obj 加上 handle+deep true 也是可以监听对象的属性但是性能消耗大
computer 里生成的值会有缓存不建议用函数去处理一些值得计算而是用 computer 来计算值,这样性能高。
id 是列表返回的 id 如果没有 id 就写 item 一般不建议写 index (eslint 会有警告错误信息) 写上 key 是为了减少消耗 它会有个缓存。
v-once 和 v-model 的区别是 只会绑定一次 不会重新更新内容 可以 减少开销 应用场景:只读场景,不进行修改页面内容的时候。
v-once
v-model
可在最外层套用一层 template 来解决
<template v-for="(column, index) in btn"> <el-button size="small" :type='column.type' :plain='column.plain' :class='!isEmpty(column.style)&&[scope.$index + (currentPage - 1) * pageSize==column.style.index?column.style.className:""] ' @click="handle(id&&!column.isGetAll?scope.row[id]:scope.row,column.lable,scope.$index + (currentPage - 1) * pageSize)" :key='index'> {{column.lable}} </el-button> </template>
this.$parent 可修改父组件值,但不建议,只读就好
this.$parent
gz
compression-webpack-plugin
const CompressionWebpackPlugin = require('compression-webpack-plugin') const productionGzipExtensions = ['js', 'css'] const isProduction = process.env.NODE_ENV === 'production' configureWebpack: config => { if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 },
ngnix 服务端配置
//配合前端的gzip 在站点配置添加如下代码: location ~* \.(css|js)$ { gzip_static on; 这是 nginx 的静态 gzip功能,会自动查找对应扩展名的文件,如果存在 gzip 文件,就使用,如果没有就用原文件 //后端返回gzip gzip on; gzip_static on; gzip_min_length 1k; gzip_buffers 4 16k; gzip_http_version 1.1; gzip_comp_level 2; gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml; gzip_vary on; gzip_proxied expired no-cache no-store private auth; gzip_disable "MSIE [1-6]\.";
<script src="https://unpkg.com/[email protected]/dist/vue.runtime.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/vuex.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/vue-router.min.js"></script> <script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script> <script src="https://unpkg.com/[email protected]/lib/index.js"></script>
//有了config就按以下配置 configureWebpack: config => { //cdn config.externals = { vue: 'Vue', vuex: 'Vuex', 'vue-router': 'VueRouter', axios: 'axios' if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 }
二次
解决方案:
base64
cdn
requireJs
一、建立环境配置文件 在package.json 同级的目录下 建立3个文件 1 .env.development --开发环境 (本地环境) 2 .env.production --正式环境 (正式线服务器--打包) 3 .env.test --测试环境 (测试线服务器--打包) 二、在每个文件中写入具体的配置内容 /*****.env.development文件的内容*****/ NODE_ENV = 'development' VUE_APP_CURRENT_MODE = 'development' /*****.env.production文件的内容*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'production' /*****.env.test*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'test' 三、在package.json 中写入 1.在纯粹的vue_cli3.x配置如下 "scripts": { "serve": "vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "build:test": "vue-cli-service build --mode test", 2.在uni-app下的vue_cli3.x的配置 "scripts": { "serve": "npm run dev:h5 -- development", //修改点 "build": "npm run build:h5 -- production", //修改点 "build:test": "npm run build:h5 -- test", //修改点 "build:h5": "cross-env NODE_ENV=production UNI_PLATFORM=h5 vue-cli-service uni-build --mode", //修改点 "build:mp-alipay": "cross-env NODE_ENV=production UNI_PLATFORM=mp-alipay vue-cli-service uni-build", "build:mp-baidu": "cross-env NODE_ENV=production UNI_PLATFORM=mp-baidu vue-cli-service uni-build", "build:mp-toutiao": "cross-env NODE_ENV=production UNI_PLATFORM=mp-toutiao vue-cli-service uni-build", "build:mp-weixin": "cross-env NODE_ENV=production UNI_PLATFORM=mp-weixin vue-cli-service uni-build", "dev:h5": "cross-env NODE_ENV=development UNI_PLATFORM=h5 vue-cli-service uni-serve --mode", //修改点 "dev:mp-alipay": "cross-env NODE_ENV=development UNI_PLATFORM=mp-alipay vue-cli-service uni-build --watch", "dev:mp-baidu": "cross-env NODE_ENV=development UNI_PLATFORM=mp-baidu vue-cli-service uni-build --watch", "dev:mp-toutiao": "cross-env NODE_ENV=development UNI_PLATFORM=mp-toutiao vue-cli-service uni-build --watch", "dev:mp-weixin": "cross-env NODE_ENV=development UNI_PLATFORM=mp-weixin vue-cli-service uni-build --watch", "info": "node node_modules/@dcloudio/vue-cli-plugin-uni/commands/info.js" },
tips: 以上不同环境的切换,修改点主要就是 mode -- '环境变量'
配置文件名 postcss.config.js vue-cli3.x 脚手架自带的 px 转 rem 等单位的配置,建立脚手架的时候选择分离 不然配置在 josn 文件中不好配置
postcss.config.js
px
rem
josn
module.exports = { plugins: [ require('autoprefixer')(), require('postcss-plugin-px2rem')({ rootValue: 192, //设计图的宽度/10 unitPrecision: 10, //换算的rem保留几位小数点 mediaQuery: true, minPixelValue: 3 // exclude:/node_modules|folder_name/i,把第三方的框架排除掉 }
删除 console ,在根目录中新建个 .babelrc 的文件,在以下文件中配置
console
.babelrc
//第一种 "env": { "production": { "plugins": [ ["transform-remove-console", { "exclude": ["error", "warn"] }] //第二种 一、建立环境配置文件 在package.json 同级的目录下 建立3个文件 1 .env.development --开发环境 (本地环境) 2 .env.production --正式环境 (正式线服务器--打包) 3 .env.test --测试环境 (测试线服务器--打包) 二、在每个文件中写入具体的配置内容 /*****.env.development文件的内容*****/ NODE_ENV = 'development' VUE_APP_CURRENT_MODE = 'development' /*****.env.production文件的内容*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'production' /*****.env.test*****/ NODE_ENV = 'production' VUE_APP_CURRENT_MODE = 'test' 三、在package.json 中写入 "scripts": { "serve": "vue-cli-service serve --mode development", "build": "vue-cli-service build --mode production", "build:test": "vue-cli-service build --mode test", 四、在babel.config.js 中写 let transformRemoveConsolePlugin = []; if (process.env.VUE_APP_CURRENT_MODE === "production") { transformRemoveConsolePlugin = [ ["transform-remove-console", { exclude: ["error", "warn"] }] module.exports = { presets: ["@vue/app"], plugins: [...transformRemoveConsolePlugin] };
当使用 html-webpack-plugin 之后,我们不再需要手动处理 bundle.js 的引用路径了,因为这个插件,已经帮我们自动创建了一个合适的script,并且,引用了正确的路径。
html-webpack-plugin
bundle.js
/*导入在内存中生成html页面的插件,只要是插件,都一定要放到plugins节点中去 const htmlWebpackPlugin=require("html-webpack-plugin") //创建一个 内存中 生成html 页面的插件 new htmlWebpackPlugin({ template:path.join(__dirname,'./src/index.html') filename:'index.html' })
//这个节点,用于配置 所有 第三方模块 加载器 module:{ rules:[ {test:/\.css$,use:[]} }
构建阶段生成匹配预渲染路径的 html 文件
npm install prerender-spa-plugin --save vue.config.js const PrerenderSPAPlugin = require('prerender-spa-plugin') const Renderer = PrerenderSPAPlugin.PuppeteerRenderer configureWebpack: config => { if (isProduction) { config.plugins.push( new CompressionWebpackPlugin({ algorithm: 'gzip', test: new RegExp('\\.(' + productionGzipExtensions.join('|') + ')$'), threshold: 10240, minRatio: 0.8 config.plugins.push( new PrerenderSPAPlugin({ staticDir: path.join(__dirname, 'dist'), routes: [ // '/' '/login' // '/show', // '/websocket', // 'websocket2', // '/websocket3', // '/home', // 'abnormal/AbnormalStatis', // 'abnormal/FocusCrowd', // 'abnormal/FocusDetail', // 'abnormal/ScaleDetail', // 'abnormal/WarnSetup', // 'abnormal/WarnDetail', // 'abnormal/WarnLists', // 'abnormal/PsychMonth', // 'abnormal/PsychTeacher', // 'abnormal/PsychList', // 'laboratory/sports/MoveClock', // 'laboratory/sports/ClockDetail', // 'activity/ActList', // 'activity/ActForm' minify: { minifyCSS: true, // css压缩 removeComments: true // 移除注释 server: { port: 8080 //忽略打包错误 ignoreJSErrors: true, phantomOptions: '--web-security=false', maxAttempts: 10, renderer: new Renderer({ injectProperty: '__PRERENDER_INJECTED', inject: { foo: 'bar' headless: false, renderAfterTime: 5000, renderAfterDocumentEvent: 'render-event'