vue2自用总结

271 阅读8分钟

vue-cli配置

//vue.config.js
const path =  require('path');
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV);
const resolve = (dir) => path.join(__dirname, dir);
module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? '/site/vue-demo/' : '/',  // 公共路径
    indexPath: 'index.html' , // 相对于打包路径index.html的路径
    outputDir: process.env.outputDir || 'dist', // 'dist', 生产环境构建文件的目录
    assetsDir: 'static', // 相对于outputDir的静态资源(js、css、img、fonts)目录
    lintOnSave: false, // 是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码
    runtimeCompiler: true, // 是否使用包含运行时编译器的 Vue 构建版本
    productionSourceMap: !IS_PROD, // 生产环境的 source map
    parallel: require("os").cpus().length > 1, // 是否为 Babel 或 TypeScript 使用 thread-loader。该选项在系统的 CPU 有多于一个内核时自动启用,仅作用于生产构建。
    pwa: {}, // 向 PWA 插件传递选项。
    chainWebpack: config => {
        config.resolve.symlinks(true); // 修复热更新失效
        // 如果使用多页面打包,使用vue inspect --plugins查看html是否在结果数组中
        config.plugin("html").tap(args => {
            // 修复 Lazy loading routes Error
            args[0].chunksSortMode = "none";
            return args;
        });
        config.resolve.alias // 添加别名
            .set('@', resolve('src'))
            .set('@assets', resolve('src/assets'))
            .set('@components', resolve('src/components'))
            .set('@views', resolve('src/views'))
            .set('@store', resolve('src/store'));
    },
    css: {
        extract: IS_PROD,
        requireModuleExtension: false,// 去掉文件名中的 .module
        loaderOptions: {
                // 给 less-loader 传递 Less.js 相关选项
                less: {
                    // `globalVars` 定义全局对象,可加入全局变量
                    globalVars: {
                        primary: '#333'
                    }
                }
        }
    },
    devServer: {
            overlay: { // 让浏览器 overlay 同时显示警告和错误
              warnings: true,
              errors: true
            },
            host: "localhost",
            port: 8080, // 端口号
            https: false, // https:{type:Boolean}
            open: false, //配置自动启动浏览器
            hotOnly: true, // 热更新
            // proxy: 'http://localhost:8080'   // 配置跨域处理,只有一个代理
            proxy: { //配置多个跨域
                "/api": {
                    target: "http://172.11.11.11:7071",
                    changeOrigin: true,
                    // ws: true,//websocket支持
                    secure: false,
                    pathRewrite: {
                        "^/api": "/"
                    }
                },
                "/api2": {
                    target: "http://172.12.12.12:2018",
                    changeOrigin: true,
                    //ws: true,//websocket支持
                    secure: false,
                    pathRewrite: {
                        "^/api2": "/"
                    }
                },
            }
        }
}

mixins混入

//本质:扩展组件的对象与方法,可以共用(每个组件独立存在)
优先级: 值为对象,methods,components中,若发生冲突,取组件
        值为函数,如created,mounted,混入先于组件调用
用法:
1.定义一个js文件(mixin.js)
   export default {
 data() {
  return {
   name: 'mixin'
  }
 },
 created() {
  console.log('mixin...', this.name);
 },
 mounted() {},
 methods: {}
}
2.在vue文件中使用
import '@/mixin'; // 引入mixin文件
export default {
 mixins: [mixin]
}

vue-router(路由)

路由传参

1.query传参 (路径拼接方式  刷新一般不会丢失数据   name和path都可以
this.$router.push({ name:"admin",query:{id:item.id}})  
this.$router.push({ path:"/admin",query:{id:item.id}})  
接收参数:this.$route.query  
如果通过query方式传递的是数组或对象,需要通过JSON.stringify()转换

2.params传参       (只能使用name
this.$router.push({ name:"second",params:{id:item.id}})  
接收参数:this.$route.params
必须在路由中写入需要传递的参数  否则刷新会丢失数据
路由 {
   path:'/second/:id/:name', //若后面加?代表参数是可选的
   name:'second',
   component:()=>import('@/view/second')
}

3.使用props配合组件路由解耦
// 路由配置
{ 
    path: '/detail/:id',
    name: 'detail', 
    component: Detail,
    props: true // 如果props设置为true,$route.params将被设置为组件属性
} 

// 列表页(路由传参)
goDetail(row) { 
    this.$router.push({
        path: '/detail',
        query: {
            id: row.id
        }
    })
} 
-------------------------------------
// 详情页(获取传递参数)
export default {
    props: { // 将路由中传递的参数id解耦到组件的props属性上
        id: String
    },
    mounted: {
        console.log(this.id)
    }
}

Vue 过滤器

全局过滤器

//在utils中定义一个filter.js
import Vue from "vue"

/** 马赛克 */                   针对姓名  两个字只显示姓;  超过两个字 显示姓名首尾,中间*
Vue.filter("MosaicName", function (str) {
    var temp
  if (str.length === 0) { 
   temp =''
  } else if (str.length > 2) {
    var temp = ""
    temp = str.substring(0, 1) + "*" + str.substring(str.length - 1, str.length)
  } else {
    temp = str.substring(0, 1) + "*"
  }
  return temp
})

      针对索引 动态隐藏 根据数量添加*号
  Vue.filter("Mosaic", function (str, preIndex, posIndex) {
    let temp = "";
    if (str && preIndex <= posIndex) {
     for (var i = 0; i < str.length; i++) {
       if (i >= preIndex && i <= posIndex) {
         temp += "*";
        } else {
          temp += str[i];
        }
      }
    } else {
      temp = str || "";
    }
    return temp.toString();
   })

//在main.js中引入
import "./utils/filter"; 

//组件中直接使用
  <span class="name">{{name | MosaicName}}</span>

组件传值

父子组件传值

第一种:
父组件v-bind绑定属性
<myComponent :title="data"></myComponent>
子组件通过props接收绑定属性,可以通过数组或者对象形式接收
props:{
title:{
    type: String,                 //可指定接收类型,如:Array.
     default:"this is default"     //可设置默认值
}
}

第二种:
通过provide inject   无论层级多深都可以传递  数据不是响应式的
父组件provide 
provide(){
return {
yeye:this
}
}
子组件inject引入
inject:['yeye']

通过watch中监听获取到的方法,实现响应式数据
父组件:
<template>
    <div class="parent-container">
      Parent组件
      <br/>
      <button type="button" @click="changeName">改变name</button>
      <br/>
      Parent组件中 name的值: {{name}}
      <Child  v-bind="{name: 'k3vvvv'}" />
    </div>
</template>
<script>
import Child from './Child'
export default {
  name: 'Parent',
  data () {
    return {
      name: 'Kevin'
    }
  },
  methods: {
    changeName (val) {
      this.name = 'New Kevin'
    }
  },
  provide () {
    return {
      nameFromParent: this.name,
      getReaciveNameFromParent: () => this.name //将一个函数赋值给provide的一个值,这个函数返回父组件的动态数据
    }
  },
  components: {
    Child
  }
}
</script>


子组件:
<template>
  <div class="child-container">
    Child组件
    <br/>
    <GrandSon />
  </div>
</template>
<script>
import GrandSon from './GrandSon'
export default {
  components: {
    GrandSon
  }
}
</script><template>
  <div class="child-container">
    Child组件
    <br/>
    <GrandSon />
  </div>
</template>
<script>
import GrandSon from './GrandSon'
export default {
  components: {
    GrandSon
  }
}
</script>


孙组件:
<template>
  <div class="grandson-container">
    Grandson组件
    <br/>
    {{nameFromParent}}
    <br/>
    {{reactiveNameFromParent}}
  </div>
</template>
<script>
export default {
  inject: ['nameFromParent', 'getReaciveNameFromParent'],
  computed: {
    reactiveNameFromParent () {
      return this.getReaciveNameFromParent()//子孙组件里面调用这个函数
    }
  },
  watch: {
    'reactiveNameFromParent': function (val) {
      console.log('来自Parent组件的name值发生了变化', val)//监听数据变化
    }
  },
  mounted () {
    console.log(this.nameFromParent, 'nameFromParent')
  }
}
</script>


第三种
$parent  可以获取父组件数据和方法
$children   可以获取子组件数据和方法

子组件触发父组件自定义事件

第一种:父组件调用方法
父组件定义一个事件
示例:<menu-item @show="showFather"></menu-item>
子组件通过$emit触发
<button @click="$emit('show',111)">触发父组件并传值</button>

第二种:父组件通过加.sync然后 data中定义属性      子组件通过update:xxx
如果是用sync写法 可以如下:
子组件
<button @click="$emit('update:show',111)">触发父组件并传</button>
<!--
下面为简写
<menu-item @update:show="newVal=>showFather=newVal"></menu-item>
-->
<menu-item :show.sync="showFather"></menu-item>
showFather在data中声明

eventBus事件总线

//1.先定义一个事件中心
var eventBus=new Vue()

//监听与销毁
eventBus.$on('add',(getData)=>{//靠回调接收数据(j)
    console.log(`接收得数据为:${getData}`)
})
evnetBus.$off('add')

//触发
eventBus.$emit('add',参数) //传递数据方

vue组件绑定原生事件

//组件注册事件时添加.native,事件逻辑写在methods中即可
比如:
<child @click.native="handleClick"></child>

插槽

1.匿名插槽

<!--1.匿名插槽(默认插槽)-->
父组件
<template>
  <div>
    <h3>这是父组件</h3>
    <son>匿名slot</son>  //此处的实践slot会在子组件中slot标签展示
  </div>
</template>
-------------------------------------------------------------
子组件
<template>
  <div>
    <h4>这是子组件</h4>
    <input type="text" placeholder="请输入">
    <slot></slot>   //展示实践slot
  </div>
</template>

2.具名插槽

<!--2.具名插槽-->
父组件
<template>
  <div>
    <h3>这是父组件</h3>
    <son>
       <template slot="myslot">
          <div>具名slot</div>
       </template>
    </son>
  </div> 
</template>
----------------------------------------------------
子组件
<template>
  <div>
    <h4>这是子组件</h4>
    <input type="text" placeholder="请输入">
    <slot name="myslot"></slot>
  </div>
</template>

3.作用域插槽

<!--3.作用域插槽-->
父组件
<template lang="">
  <div>
    <h3>这是父组件</h3>
    <son>
      <template slot="myslot" slot-scope="scope"> 
     <!--通过scope.data拿子组件数据 ,这个data是子组件自定义属性名,需与子组件保持一致-->
        <ul>
          <li v-for="item in scope.data">{{item}}</li>
        </ul>
      </template>
    </son>
  </div> 
</template>
---------------------------------------------------------
子组件
<template>
  <div>
    <h4>这是子组件</h4>
    <slot name="myslot" :data='list'></slot>  <!--属性名为data-->
  </div>
</template>
 
<script>
  export default {
    name:'Son',
    data(){
      return{
        list:["banana","Jim","Tony"]
      }
    }
  }
</script>

Vuex(状态管理,任意组件修改值,其他组件值随之修改)

安装及配置

第一步:npm i vuex -s
//store.js:
import Vue from 'vue'
import Vuex from 'vuex'

//挂载Vuex
Vue.use(Vuex)

//创建VueX对象
const store = new Vuex.Store({
    state:{
        //存放的键值对就是所要管理的状态
        name:'helloVueX'
    }
})

export default store

//在main.js中挂载Vuex
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,  //store:store 和router一样,将我们创建的Vuex实例挂载到这个vue实例中
  render: h => h(App)
})

在vue组件中取值

//1.State取值
第一种方式
this.$store.state.name  //使用state值

第二种方式:
import {mapState} from 'vuex'

computed:{
    ...mapState(['name'])
}
//2.mutation(变更state中的数据)
第一种方式:
const store=new Vuex.State({
state:{
    count:0
},
 mutation:{
     add(state){
         state.count++
     }
 }
})

//组件中使用
第一种方式
methods:{
handle(){
    this.$store.commit('add') //利用commit触发
}
}

第二种方式
import {mapMutations}from 'vuex'
methods:{
    ...mapMutations(['add']) //作为方法直接使用过
}
//Actions(异步任务)
const store =new Vuex.store({
mtations:{
add(state){
state.count++
  }
 }
})
actions:{
    addAsync(context,payload){
        setTimeout(()=>{
        context.commit('add',payload)//触发mutations中函数操作state数据
       },1000)
    }
}

//组件中使用
第一种方式
methods:{
  handle(){
     this.$store.dispatch('addAsync')//触发actions
  }
}
第二种方式
import {mapActions} from 'vuex'
methods:{
    ...mapActions(['addAsync'])
}
//getters(对store中得数据加工处理形成新的数据)
const store =new Vuex.store({
mtations:{
add(state){
state.count++
  }
 }
})
getters:{
  showNum:State=>{
       return '当前最新数量【'+State.count++'】'
  }
}

//组件中使用
第一种方式
this.$store.getters.showNum
第二种方式
import {mapGetters} from 'vuex'
computed:{
  ...mapGetters(['showNum'])
}

解决页面刷新数据丢失问题

以下内容为博客园 ____chen的文章总结

在vue项目中用vuex来做全局的状态管理, 发现当刷新网页后,保存在vuex实例store里的数据会丢失。

//原因:
因为store里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,store里面的数据就会被重新赋值初始化

//解决思路:配合本地存储做数据持久化
1.localStorage:永久存储
2.sessionSrorage:窗口关闭销毁
//vue单页面应用,适合sessionStorage
1.sessionStorage可以保证页面打开时数据为空
2.每次打开页面localStorage存储着上一次打开页面的值,因此需要清空之前的数据

//在app.vue中
export default {
name: 'App',
created () {
//在页面加载时读取sessionStorage里的状态信息
if (sessionStorage.getItem("store") ) {
    //vuex.store的replaceState方法可以替换store的
this.$store.replaceState(Object.assign({}, this.$store.state,JSON.parse(sessionStorage.getItem("store"))))
}

//在页面刷新时将vuex里的信息保存到sessionStorage里
window.addEventListener("beforeunload",()=>{
    //监听beforeunload事件,此事件可以在页面刷新前触发
sessionStorage.setItem("store",JSON.stringify(this.$store.state))
})
}
}

动态组件

//通过使用保留的 <component> 元素,动态地绑定到它的 is 特性,可以实现动态组件
<component :is="组件名称"></component>

组件缓存

//注意:要求同时只有一个子元素被渲染。若其中有v-for则无效
常用方式
方案一 动态组件  内置组件<component></component>
<keep-alive>
  <component :is="view"></component>
</keep-alive>
方案二:当出现条件判断
<keep-alive>
  <comp-a v-if="a > 1"></comp-a>
  <comp-b v-else></comp-b>
</keep-alive>
//方案三  结合路由使用
<keep-alive>
     <router-view></router-view>
 </keep-alive>
属性:
include        只有名称包含才缓存
exclude         名称包含不缓存
示例:可以使用正则,分隔字符串,数组
<keep-alive include="a,b"></keep-alive>
<keep-alive :include="/a|b/"></keep-alive>
<keep-alive :include="['a', 'b']"></keep-alive>

watch监听

data:{
    a:1,
    b:{
        c:1
  }
},
watch:{
    a(val,oldVal){   //普通监听
          console.log('a'+val,oldVal)
    },
    b:{//深度监听,可监听到对象、数组的变化
        handler(val,oldVal){
             console.log('b.c:'+val.c,old.c)
        },
        deep:true,  //深度监听
       immediate: true  //立即监听(默认false)
    }
}

配置多环境

//1、根目录下新建文件:.env.development(开发环境)、.env.test(测试环境)、.env.production文件(生产环境)

.env.development(开发环境)配置内容
NODE_ENV = 'development'  //模式
VUE_APP_MODE = 'development'  //通过"VUE_APP_MODE"变量来区分环境
VUE_APP_BASE_URL = 'http://192.****:8008/api/' //api地址

.env.test(测试环境)配置内容
NODE_ENV = 'production'
VUE_APP_MODE = 'test'
VUE_APP_BASE_URL = 'http://xxx.xxx.xxx.xx:8008/api/'
//打包输出目录
outputDir = dist-test

.env.production文件(生产环境)配置内容
NODE_ENV = 'production'
VUE_APP_MODE = 'production'
VUE_APP_BASE_URL = 'http://xxx.xxx.xxx.xx:8008/api/'
outputDir = dist-production


//2.修改vue.config.js
console.log(process.env.VUE_APP_BASE_URL)//打印环境
module.exports = {
    // 基本路径,相对路径
    publicPath: "./",
    // 输出文件目录
    outputDir: process.env.outputDir,
    productionSourceMap:process.env.NODE_ENV==='production'?false:true,//生产环境下设置source map为false加速构建
    devServer:{
      proxy:{
         '/api':{
           target:process.env.VUE_APP_BASE_URL,//使用的时候调用process.env
           changeOrigin:true,//开启跨域
           ws:false,//websocket不支持
           pathRewrite:{
               '^/api':''          
           }
         }
      }
    }
}

//3.配置package.json     (执行对应的npm run xxx)
"scripts":{
    //打包开发环境
    "serve":"vue-cli-service build --mode development",
    //打包生产环境    
    "build":"vue-cli-service build --mode production",
    //打包测试环境
    "test": "vue-cli-service build --mode test", 
    "lint":"vue-cli-service lint"
}
  ----------------------------------------- 
   // 4.判断并使用不用的开发环境配置
if(process.env.VUE_APP_MODE==='development'){
    //开发环境下的执行操作
}else if(process.env.VUE_APP_MODE==='test'){
    //测试环境下的执行操作
}else{
    //生产环境下的执行操作
}

观察组件中的任何内容

export default {
  computed: {
    someComputedProperty() {
      // 更新计算道具
    },
  },
  watch: {
    someComputedProperty() {
      // 当计算的 prop 更新时做一些事情
    }
  }
};

nextTick()

//this.$nextTick()作用:帮助我们在改变组件中属性后,立刻拿到渲染以后的dom节点对象
this.$nextTick(()=>{

})

监听组件生命周期

//使用 @hook 即可监听组件生命周期,组件内无需做任何改变。同样的, created 、 updated 等也可以使用此方法

<template>
    <List @hook:mounted="listenMounted" />
</template>
<script>
    export default{
         methods:{
              listenMounted(){

            }
        }
    }
</script>

定时器优雅清除方式

//我们可以通过 $on 或 $once 监听页面生命周期销毁来解决这个问题:
export default {
    mounted() {
        this.creatInterval('hello')
        this.creatInterval('world')
    },
    methods:{
        creatInterval(msg) {
        let timer = setInterval(() => {
            console.log(msg)
        }, 1000)
        this.$once('hook:beforeDestroy', function() {
            clearInterval(timer)
        })
    }
    }
}

移动端调试

1.npm install vconsole -D

2.在vue项目的main.js文件中写入
import VConsole from 'vconsole';
Vue.prototype.$vconsole = new VConsole()

vue内外边距的初始化

//APP.vue根组件中
<template>
  <div id="app">
    <router-view/>
  </div>
</template>
<style lang="less" > //注意此处不能加scoped 因为需要影响全部页面
 html,body,#app{
        height: 100%;
        width: 100%;
         padding: 0;
         margin: 0;
    }
</style>

vue项目美化滚动条

::-webkit-scrollbar-track {
  background: rgba(0, 0, 0, 0.1);
  border-radius: 0;
}

::-webkit-scrollbar {
  -webkit-appearance: none;
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-thumb {
  cursor: pointer;
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.15);
  transition: color 0.2s ease;
}

vue低版本兼容处理方案

npm install --save babel-polyfill
npm install es6-promise

//.babel.config.js中
module.exports = {
  presets: [
    ['@vue/app', {
      polyfills: [
        'es.promise',
        'es.symbol'
      ]
    }]
  ],

  plugins: [
    ["@nutui/babel-plugin-separate-import", {
      "libraryName": "@nutui/nutui",
      "libraryDirectory": "dist/packages",
      "style": "scss"
    }]
  ]
}

//vue.config.js中
 transpileDependencies: ['vuex-persist', 'webpack-dev-server/client', 'vconsole', /\@vue\//, /vue.runtime.esm-bundler/, 'sockjs', 'sockjs-client',
    'axios',
    '@nutui',
    'inobounce'
  ],//可以在里面添加,配置node_modules中指定哪些文件夹或文件需要编译

 chainWebpack: (config) => {
    // 在chainWebpack中添加下面的代码
    config.entry('main').add('babel-polyfill') // main是入口js文件
    config.entry.app = ['babel-polyfill', './src/main.js']
 }

vue项目代码混淆

//需要安装npm i WebpackObfuscator
const path = require("path");
const WebpackObfuscator = require('webpack-obfuscator');


function resolve(dir) {
  return path.join(__dirname, dir);
}

module.exports = {
  /* 部署应用包的基本URL */
  parallel: false,
  /* baseUrl 从 Vue CLI 3.3 起已弃用 ,请使用publicPath */
  //  baseUrl: process.env.NODE_ENV === "production" ? "./" : "./",
  publicPath: "./",
  // publicPath: process.env.NODE_ENV === "production" ||  process.env.NODE_ENV === "test" ? "./" : "./",
  /* 生产环境构建文件的目录 defalut: dist */
  outputDir: "dist" + '_' + process.env.NODE_ENV,
  /* 放置生成的静态文件目录(js css img) */
  assetsDir: "static",
  /* 指定生成的index.html 输出路径 相对 default: index.html */
  indexPath: "index.html",
  // 是否开启eslint保存检测,有效值:ture | false | 'error'
  // lintOnSave: process.env.NODE_ENV === 'development',
  lintOnSave: false,
  /* 指定生成文件名中包含hash default: true */
  filenameHashing: true,
  /* 是否使用编译器 default: false */
  runtimeCompiler: false,
  /* 默认babel-loader会忽略node_modules中的文件,你想显示的话在这个选项中列出来 */
  // transpileDependencies: [],
  transpileDependencies: ['vuex-persist', 'webpack-dev-server/client', 'vconsole', /\@vue\//, /vue.runtime.esm-bundler/, 'sockjs', 'sockjs-client',
    'axios',
    '@nutui',
    'inobounce'
  ],
  /* 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建 */
  productionSourceMap: false,

  // crossorigin: "",
  integrity: false,
  css: {
    loaderOptions: {
      // 给 sass-loader 传递选项
      scss: {
        // @/ 是 src/ 的别名
        // 注意:在 sass-loader v7 中,这个选项名是 "data"
        prependData: `
              @import "@nutui/nutui/dist/styles/index.scss";
              `,
      },
    },
  },
  chainWebpack: (config) => {
    // 在chainWebpack中添加下面的代码
    config.entry('main').add('babel-polyfill') // main是入口js文件
    config.entry.app = ['babel-polyfill', './src/main.js']
    // 仅在生产环境生效   此处需要判断是否混淆代码
    config.when(process.env.NODE_ENV === 'production', config => {
      config.plugin(
        new WebpackObfuscator(
          {
            // 压缩代码
            compact: true,
            // 是否启用控制流扁平化(降低1.5倍的运行速度)
            controlFlowFlattening: true,
            // 应用概率;在较大的代码库中,建议降低此值,因为大量的控制流转换可能会增加代码的大小并降低代码的速度。
            controlFlowFlatteningThreshold: 0.75,
            // 随机的死代码块(增加了混淆代码的大小)
            deadCodeInjection: true,
            // 死代码块的影响概率
            deadCodeInjectionThreshold: 0.4,
            // 此选项几乎不可能使用开发者工具的控制台选项卡
            debugProtection: false,
            // 如果选中,则会在“控制台”选项卡上使用间隔强制调试模式,从而更难使用“开发人员工具”的其他功能。
            debugProtectionInterval: false,
            // 通过用空函数替换它们来禁用console.log,console.info,console.error和console.warn。这使得调试器的使用更加困难。
            disableConsoleOutput: true,
            // 标识符的混淆方式 hexadecimal(十六进制) mangled(短标识符)
            identifierNamesGenerator: 'hexadecimal',
            log: false,
            // 是否启用全局变量和函数名称的混淆
            renameGlobals: false,
            // 通过固定和随机(在代码混淆时生成)的位置移动数组。这使得将删除的字符串的顺序与其原始位置相匹配变得更加困难。如果原始源代码不小,建议使用此选项,因为辅助函数可以引起注意。
            rotateStringArray: true,
            // 混淆后的代码,不能使用代码美化,同时需要配置 cpmpat:true;
            selfDefending: true,
            // 删除字符串文字并将它们放在一个特殊的数组中
            stringArray: true,
            stringArrayEncoding: 'base64',
            stringArrayThreshold: 0.75,
            transformObjectKeys: true,
            // 允许启用/禁用字符串转换为unicode转义序列。Unicode转义序列大大增加了代码大小,并且可以轻松地将字符串恢复为原始视图。建议仅对小型源代码启用此选项。
            unicodeEscapeSequence: false
          },
          []
        )
      )
        .use("webpack-obfuscator")
        .end()
    })

  },
  // webpack-dev-server 相关配置
  devServer: {
    host: "0.0.0.0",
    // port: 8080,
    open: true,
    proxy: {
      ['/dev']: {
        // target: '', // 测试
        target: '', // 生产
        changeOrigin: true, //会修改掉域名
        pathRewrite: {
          ["^" + process.env.VUE_APP_BASE_API]: "",
        },
      },
    },
    // disableHostCheck: true,
  },
  configureWebpack: {
    name: "",
    resolve: {
      alias: {
        "@": resolve("src"),
      },
    },
  },
}