VUE-核心配置

文章详细介绍了Vue的核心配置,包括如何配置vue.config.js以处理路径、源码映射和别名,以及如何实现懒加载分组以优化性能。同时,讲解了本地服务配置和代理设置,解决了跨域问题。接着,文章讨论了Vue的多环境配置,包括创建不同环境变量文件和如何在不同环境中自动读取。最后,深入探讨了Vue的响应式原理,通过数据劫持和依赖收集来实现数据变化时视图的自动更新。
摘要由CSDN通过智能技术生成

第一节、核心vue配置

一定要记住:每次更改了配置文件需要手动重新开服

核心配置文件:项目根目录下vue.config.js (等价于webpack.config.js)

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  //根据浏览器自动采取是否把ES6转为ES5,兼容
  transpileDependencies: true,
  //配置路径 ,能够避免打包后js找不到路径(推荐)
  publicPath:"./",
  //去掉map文件(map文件是用来查找源码出问题的行数的)
  productionSourceMap:false,
  //别名,为某一段路径取别名(可以用于打包之后和开发阶段)
  configureWebpack:{
    resolve:{
      alias:{
        //"别名":"路径"
        "xxx":"@/views/stu"
      }
    }
  },
})

懒加载分组打包

打包的js个数会随着懒加载组件的增加而增加,—》打包之后的js文件个数增加----》性能降低

解决:通过分组配置来合并懒加载的文件个数

router/index.js

let Login=()=>import(/*webpackChunkName:'group-user'*/'@/views/Login.vue')
let Register=()=>import(/*webpackChunkName:'group-user'*/'@/views/Register.vue')

本地服务

//本地服务(只能用于开发阶段)
  devServer: {
    port: 8080,
    //代理 前端处理跨域
    //浏览器有同源策略(协议、ip地址、端口) ---》  ajax
    //生产阶段(上线)一定是后端来处理
    proxy: {
      // "/users": {
      //   //需要代理的地址(和axios的baseURL两者选其一)
      //   //代理生效的条件:以后ajax必须以/自定义标识开头
      //   //ajax的路径写: /users  等价于    http://localhost:3000/user
      //   //错误的想法:   /users  等价于    http://localhost:3000
      //   target: "http://localhost:3000"
      // },
      // "/stus": {
      //   target: "http://localhost:3000"
      // },
      // "/clas": {
      //   target: "http://localhost:3000"
      // }

      "/api":{
        target: "http://localhost:3000",
        //关闭ws报错提示(对程序没有影响)
        ws:false,
        //重写路径
        pathRewrite:{
            // "^/标识" :"/替换的路径"
             "^/api":""
        }
      }
      // /api/stus/getAllByPage
      // http://localhost:3000/aa/stus/getAllByPage
    }

注意:浏览器的F12调试器是无法识别代理

第二节、多环境

能够通过配置,让项目在不同环境中自动读取不同的变量

  • 开发环境 --development
  • 测试环境 --test
  • 生产环境 --production

面临问题

开发:http://localhost:3000
生产:http://localhost:4000
为了今后切换地址方便,我们可以配置多环境,程序自动读取对应地址

步骤

1 在项目根目录下新建两个文件(文件名是固定)

1 .env.development   npm run serve  程序会读取该文件
2 .env.production     npm run build  程序会读取该文件
3 .env     npm run serve和npm run build 程序都会读取该文件

2 语法

2.1 定义

1 NODE_ENV=值  只能写一次 ,一般来说值就是标题,比如 生产环境 、开发环境  
2 VUE_APP_自定义变量=值  能够写多次,值一般就是今后不同环境对应不同的数据,比如url地址等...
注释: # ....
注意:中间没有任何符号

2.2 读取

今后可以在该项目的任意文件中读取到环境文件的变量(vue、js。。)
process.env.NODE_ENV
process.env.VUE_APP_自定义变量

自定义环境文件

1 依然在项目根目录中新建
2 取名规范为:.env.xx  ,xx就是自定义名字
3 配置package.json中的 scripts属性
	语法:
	"自定义命令名" :"vue-cli-service serve/build --mode .env的后缀名"
	
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
     
    "serve-a":"vue-cli-service serve --mode a",  ---》npm run serve-a
    "build-b":"vue-cli-service build --mode b"   ---> npm run build-b
  }, 

第三节、vue响应式原理

vue的响应式是什么东西?

数据驱动基于响应式,当vue检测到data数据发生变化时,则会自动去渲染页面

1 侦查数据的变化—数据劫持

该方法可以劫持对象的属性(实现了监听),一旦数据的属性发生更改或者被访问,都会被监听到
Object.defineProperty()来劫持data定义数据,

demo1:数据劫持的基本操作

let user={
    name:"张三"
}
let value=user.name

//劫持
//参数1.被劫持的对象
//参数2.被劫持的对象的具体的属性
//参数3:触发监听后的业务
Object.defineProperty(user,'name',{
    //一旦user的name被访问,那么就会触发get方法
    get(){
        console.log("有人在访问user的name属性");
        return value
    },
    //一旦user的name被更新时,那么就会触发set方法
    set(val){
        console.log("有人在修改user的name属性,更新后的值是:"+val);
        value=val
    }
})

console.log(user.name);//张三
user.name='李四'
console.log(user.name); 

demo2:封装数据劫持

//封装方法---数据劫持
function defineReactive(data, key, value) {
    //参数1.被劫持的对象
    //参数2.被劫持的对象的具体的属性
    //参数3:触发监听后的业务
    Object.defineProperty(data, key, {
        //一旦user的name被访问,那么就会触发get方法
        get() {
            console.log("有人在访问user的name属性");
            return value
        },
        //一旦user的name被更新时,那么就会触发set方法
        set(val) {
            console.log("有人在修改user的name属性,更新后的值是:" + val);
            value = val
        }
    })
}

let user = {
    name: "张三"
}

//劫持user的name属性
defineReactive(user,'name',user.name)
console.log(user.name);
user.name = '李四'
console.log(user.name); 

demo3: 再次封装方法—数据劫持

//封装方法---数据劫持
function defineReactive(data, key, value) {
    //参数1.被劫持的对象
    //参数2.被劫持的对象的具体的属性
    //参数3:触发监听后的业务
    Object.defineProperty(data, key, {
        //一旦user的name被访问,那么就会触发get方法
        get() {
            console.log("有人在访问user的name属性");
            return value
        },
        //一旦user的name被更新时,那么就会触发set方法
        set(val) {
            console.log("有人在修改user的name属性,更新后的值是:" + val);
            value = val
        }
    })
}

//再次封装方法---数据劫持 (劫持多个属性)
function observer(data){
    for(let k in data){
        defineReactive(data,k,data[k])
    }
}


let user = {
    name: "张三",
    age:18
}

//劫持user的所有属性
observer(user)
console.log(user.name);
user.name = '李四'
console.log(user.name); 
console.log(user.age);
user.age = 10
console.log(user.age); 

demo4 递归封装(解决属性是引用类型的情况)

//封装方法---数据劫持
                        //user,dog,{type:"哈士奇"}
function defineReactive(data, key, value) {
    //递归
    observer(value)
    //参数1.被劫持的对象
    //参数2.被劫持的对象的具体的属性
    //参数3:触发监听后的业务
    Object.defineProperty(data, key, {
        //一旦user的name被访问,那么就会触发get方法
        get() {
            console.log("有人在访问对象的"+key+"属性");
            return value
        },
        //一旦user的name被更新时,那么就会触发set方法
        set(val) {
            console.log("有人在修改对象的属性,更新后的值是:" + val);
            value = val
        }
    })
}
//再次封装方法---数据劫持 (劫持多个属性)
function observer(data){
   
    //递归结束条件,如果某个属性不是对象
    if(typeof data != 'object'){
        return data;
    }

    for(let k in data){
        defineReactive(data,k,data[k])
    }
}
let user = {
    name: "张三",
    age:18 ,
    dog:{
        type:"哈士奇"
    }
}
//劫持user的所有属性
observer(user)
// console.log(user.dog.type);
// user.dog.type = '金毛'
// console.log(user.dog.type);

// console.log(user.name);
// user.name = '李四'
// console.log(user.name); 

// console.log(user.age);
// user.age = 10
// console.log(user.age); 

2 收集视图依赖了哪些数据—依赖收集 (初始化)

引入了两个角色:

1 watcher观察者, 有几个{{}}那么就会new出几个观察者对象 
	每一个watcher对象都拥有 render方法(渲染)
2 dep订阅者  ,有几个属性就new出几个订阅者对象
	每一个dep对象拥有一个数组属性(subs)以及一个方法(notify)
	比如订阅者age 就拥有一个数组,[watcher对象-age,watcher对象-age]
		订阅者name 就拥有一个数组, [watcher对象-name,watcher对象-name,watcher对象-name]
	notify方法, 该方法可以通知dep订阅者对应的数组中的每一个watcher对象执行render方法
	 Object.defineProperty(xx, xx, {
        //一旦user的name被访问,那么就会触发get方法
        get() {
           	依赖收集操作
        },
        //一旦user的name被更新时,那么就会触发set方法
        set(val) {
         
        }
    })
demo:
5个 watcher
2个 dep
{{name}}   {{name}}    {{name}}
{{age}}   {{age}}
data:{
	name:"aaa",
	age:18
}

3 数据变化时,dep会”通知“需要更新的视图部分,并进行更新-----发布订阅

一旦data属性发生修改,则

	 Object.defineProperty(xx, xx, {
        //一旦user的name被访问,那么就会触发get方法
        get() {
           	依赖收集操作
        },
        //一旦user的name被更新时,那么就会触发set方法
        set(val) {
         	通知修改操作
        }
    })

我们把vue响应式原理也称之为 观察者模式、订阅/观察 模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值