vue3-响应式函数

​🌈个人主页:前端青山

🔥系列专栏:Vue篇

🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来vue篇专栏内容:vue3-响应式函数

目录

[ref 响应式函数](#ref 响应式函数)

引言:

[ref 函数](#ref 函数)

[reactive 函数](#reactive 函数)

[Reactive 与 ref 对比](#Reactive 与 ref 对比)

vue3响应式原理

1、vue3响应式原理

ref 响应式函数

引言:

如下代码:当点击执行changeFn函数,修改setup中定义的变量时,发现页面中的name和age的数据并没有修改,说明该数据不是响应式数据

javascript 复制代码
<template>
  <div>111</div>
  <p>{{ name }}--{{ age }}</p>
  <button @click="changeFn">changeFn</button>
</template>
​
<script>
export default {
  name: "App",
  setup() {
    //定义变量
    let name = "张三";
    let age = 20;
    // 定义方法
    function changeFn() {
      name = "李四";
      age = 30;
    }
    return {
      //setup函数返回值为一个对象
      name,
      age,
      changeFn,
    };
  },
};
</script>
ref 函数
  • 它是 vue3中的一个函数,一般用于将基本类型数据处理成响应式数据。

  • 作用:定义一个基本类型的响应式的数据,只有数据成为响应式数据,这样当数据变化时,才能被监测到。

  • 使用时需要从vue中引入

  • 语法:const xxx =ref(数据变量);结果 返回一个 RefImpl 的引用对象,获取时为 xxx.value

  • 在页面模板中使用数据直接 使用插值表达式,不需要加value <p>姓名:{{ name }}</p>,因为vue3会自动帮你.value,所以可以拿到值

  • ref 函数实现数据响应式的原理还是利用了vue2的Object.defineProperty() 给数据设置 get set 监听函数,如下图:

  • 接收的数据类型可以是基本类型(实现响应式原理为Object.defineProperty() ),也可以是对象类型(当为对象时,实现响应式的原理就是Proxy不是Object.defineProperty())

点击如下change事件,修改name 和age

javascript 复制代码
<template>
  <div>
    <!--name这个ref 引用对象在使用时不需要加value,vue3会自动帮你加value,所以可以拿到值-->
    <p>{{ name }}--{{ age }}</p>
    <p>{{ job.type }}--{{job.salary}}</p>
    <p @click="change">说话</p>
  </div>
</template>
<script>
import { ref } from "vue"; // 引入响应式函数ref
export default {
  name: "App",
  setup() {
    let name = ref("张三"); //返回一个 ref 引用对象
    let age = ref(20);
    console.log(name)
    // 当ref传的参数为对象时
    let job = ref({
      type: "前端工程师",
      salary: "20k",
    });
    function change() {
      name.value = "李四"; // ref对象.value 修改其值
      age.value = 30;
      job.value.type = "后端开发工程师";
      job.value.salary = "30k";
    }
    return {
      name,
      age,
      change,
      job
    };
  },
};
</script>

reactive 函数

1.定义一个对象类型的响应式数据,返回一个Proxy 实例对象,不能用于基本数据类型,否则报错。(基本类型响应式数据使用ref)。

语法:const 代理对象= reactive(源对象) ,接收一个对象或数组,返回一个代理对象(即Proxy源对象

  • 使用时先从vue中引入
javascript 复制代码
<script>
import { reactive } from "vue";
...
</script>
  • 代码如下:
javascript 复制代码
<template>
  <p>{{ job.type }} --{{ job.salary }}--{{ job.like.a.b }}--{{job.content}}</p>
  <p v-for="(item, index) in foodArr" :key="index">{{ item }}</p>
  <button @click="changeFn">changeFn</button>
</template>
​
<script>
import { reactive } from "vue";
export default {
  name: "App",
  components: {},
  setup() {
    //定义对象
    let job = reactive({
      type: "前端工程师",
      salary: "20k",
      like:{
          a:{
              b:'不告诉你'
          }
      }
    });
    console.log(job);
    //定义数组
    let foodArr = reactive(["刷抖音", "敲代码"]);
    console.log(foodArr);
    // 定义方法
    function changeFn() {
      job.type = "后端开发工程师";
      job.salary = "30k";
      job.content = "写代码"; // 给对象添加属性
      foodArr[0]='买包包' // 通过下标修改数组
    }
    return {
      //setup函数返回值为一个对象
      job,
      changeFn,
      foodArr
    };
  },
};
</script>
  • vue3中使用proxy 实现的数据响应去掉了vue2中不能检测到对象添加属性和通过下标修改数组而无法检测的情况。

Reactive 与 ref 对比

1、数据定义角度对比:

  • ref用来定义:基本数据类型

  • reactive 用来定义: 对象或数组类型数据

    注意:ref也可以定义对象或数组类型数据,它内部还是通过reactive转换成代理对象

2、原理角度对比:

  • ref通过Object.defineProperty() 的get和set 实现数据的响应式 即(数据劫持)

  • reactive 通过Proxy 实现数据响应式的,并通过Reflect 来操作源对象数据的。

3、从使用角度对比:

  • ref 定义的数据操作时需要使用 .value, 而插值表达式中使用时,不需要使用 .value

  • reactive 定义的数据操作都不需要 .value

vue3响应式原理

  • 对象数据新增属性和删除属性,不存在vue2.x 中的问题了。
javascript 复制代码
<template>
  <div>
    <p>{{ person.name }}</p>
    <p>{{ person.age }}</p>
    <p>{{ person.sex }}</p>
    <button @click="addSex">添加属性</button>
    <button @click="deleteSex">删除属性</button>
  </div>
</template>
​
<script>
import { reactive } from "vue";
export default {
  name: "App",
  components: {},
  setup() {
    let person = reactive({
      name: "张三",
      age: 20,
    });
    console.log(person);
    //定义添加属性
    function addSex() {
      person.sex = "男";
      console.log(person);
    }
    // 定义删除属性
    function deleteSex() {
      delete person.sex;
      console.log(person);
    }
    return {
      person,
      addSex,
      deleteSex,
    };
  },
};
</script>
  • 数组数据直接通过修改下标,修改数组,不存在vue2.x 中的问题了。
javascript 复制代码
<template>
  <div>
    <p v-for="(item, index) in person.like" :key="index">{{ item }}</p>
    <button @click="change">修改数组的值</button>
  </div>
</template>
​
<script>
import { reactive } from "vue";
export default {
  name: "App",
  components: {},
  setup() {
    let person = reactive({  
      name: "张三",
      age: 20,
      like: ["打球", "敲代码"],
    });
    console.log(person); // proxy 实例对象
    function change() {
      person.like[0] = "打台球";
    }
    return {
      person,
      change,
    };
  },
};
</script>

1、vue3响应式原理

首先说一下Reflect的作用。

javascript 复制代码
// Reflect是window下的一个内置对象
// 1. 使用reflect 访问数据
    let obj = {
        name: '张三',
        age: 20
    }
    console.log(Reflect.get(obj, 'name')); // 张三
// 2.使用Reflect 修改数据
    Reflect.set(obj, 'age', 50)
    console.log(obj);
​
//3.使用Reflect删除数据
    Reflect.deleteProperty(obj, 'name') 
    console.log(obj);

vue3响应原理代码

通过Proxy代理,拦截对象中任意属性的变化,包括属性的读取,修改、设置、删除。

通过Reflect 反射对被代理对象的属性进行操作。

javascript 复制代码
    let data = {
        name: "张三",
        age: 30
    }
    console.log(Proxy);
    // 使用p 对象代理data, Proxy为window 下的内置代理函数
    let p = new Proxy(data, {
        // 读取属性
        get(target, propName) {
            // target 就是 data
            console.log(`读取p上个${propName}属性`);
            return Reflect.get(target, propName)
        },
        // 修改和设置属性
        set(target, propName, value) {
            // value 为赋的值
            console.log(`修改p的${propName}属性`);
            // target[propName] = value
            Reflect.set(target, propName, value)
​
        },
        //删除属性
        deleteProperty(target, propName) {
            console.log(`删除p上的${propName}属性`);
            // return delete target[propName]
            return Reflect.deleteProperty(target, propName)
        }
    })
相关推荐
胡西风_foxww9 分钟前
【ES6复习笔记】数值扩展(16)
前端·笔记·es6·扩展·数值
mosen86811 分钟前
uniapp中uni.scss如何引入页面内或生效
前端·uni-app·scss
白云~️11 分钟前
uniappX 移动端单行/多行文字隐藏显示省略号
开发语言·前端·javascript
沙尘暴炒饭13 分钟前
uniapp 前端解决精度丢失的问题 (后端返回分布式id)
前端·uni-app
昙鱼27 分钟前
springboot创建web项目
java·前端·spring boot·后端·spring·maven
天天进步201533 分钟前
Vue项目重构实践:如何构建可维护的企业级应用
前端·vue.js·重构
2402_8575834933 分钟前
“协同过滤技术实战”:网上书城系统的设计与实现
java·开发语言·vue.js·科技·mfc
小华同学ai36 分钟前
vue-office:Star 4.2k,款支持多种Office文件预览的Vue组件库,一站式Office文件预览方案,真心不错
前端·javascript·vue.js·开源·github·office
APP 肖提莫37 分钟前
MyBatis-Plus分页拦截器,源码的重构(重构total总数的计算逻辑)
java·前端·算法
问道飞鱼1 小时前
【前端知识】强大的js动画组件anime.js
开发语言·前端·javascript·anime.js