Vue3 - 从 vue2 到 vue3 过渡,这一套就够了(案例 + 效果演示)(二)

news2024/12/24 18:18:08

目录

一、组合式 API 的使用

1.1、watch 函数

1.2、watchEffect 函数

1.3、toRef 和 toRefs

1.3.1、toRef

1.3.2、toRefs

1.4、vue3  的声明周期


 

一、组合式 API 的使用


1.1、watch 函数

与 vue2.x 中的 watch 配置功能一致,但是多了一些坑:

这是我当前的 vue 版本

  1. 监视 reactive 定义的响应式数据时:oldValue 无法正确获取
  2. 监视 reactive 定义的响应式数据中某个属性时:deep 配置有效.

Ps:我目前使用的 vue3 的版本没有以上问题!!!

这里我来列出几种情况:

a)监视 ref 所定义的响应式数据

<template>
  <h2>当前和为: {{ sum }}</h2>
  <button @click="sum++">点我 + 1</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let sum = ref(0);

    watch(sum, (newValue, ordValue) => {
      console.log("sum变了", newValue, ordValue);
    });

    return {
      sum,
    };
  },
};
</script>

监视没有问题,如下:

b)监视 ref 定义的多个响应式数据(只要其中一个变,就会触发监视事件)

<template>
  <h2>当前和为: {{ sum }}</h2>
  <h2>{{ msg }}</h2>
  <button @click="sum++">点我 + 1</button>
  <button @click="msg += '!'">点我 + !</button>
</template>

<script>
import { ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let sum = ref(0);
    let msg = ref("你好呀");

    //情况二
    watch([sum, msg], (newValue, oldValue) => {
      console.log("sum 或 msg 变了", newValue, oldValue);
    });

    return {
      sum,
      msg,
    };
  },
};
</script>

先点三下 “点我 + 1”、再点三下 “点我 + !”,效果如下:

c)监视 reactive 所定义的一个响应式数据的全部属性,无法正确的获取 oldValue

若没有配置 deep,默认开启深度监视(老版本的 vue3 强制开启深度监视,无法修改,我当前使用的版本已修改该问题).

<template>
  <h2>一个人的信息</h2>
  <div>{{ person.name }}</div>
  <div>{{ person.age }}</div>
  <div>{{ person.a.b.c }}</div>
  <button @click="person.name = 'lyj'">修改姓名</button>
  <button @click="person.age += 1">修改年龄</button>
  <button @click="person.a.b.c += 100">修改a.b.c</button>
</template>

<script>
import { reactive, ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

    //情况三
    watch(
      person,
      (newValue, oldValue) => {
        console.log("person变化了", newValue, oldValue);
      },
    );

    return {
      person,
    };
  },
};
</script>

依次点击按钮,效果如下:

若设置 deep 为 false ,则点击 “修改 a.b.c ” 无效,如下:

<template>
  <h2>一个人的信息</h2>
  <div>{{ person.name }}</div>
  <div>{{ person.age }}</div>
  <div>{{ person.a.b.c }}</div>
  <button @click="person.name = 'lyj'">修改姓名</button>
  <button @click="person.age += 1">修改年龄</button>
  <button @click="person.a.b.c += 100">修改a.b.c</button>
</template>

<script>
import { reactive, ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

    //情况三
    watch(
      person,
      (newValue, oldValue) => {
        console.log("person变化了", newValue, oldValue);
      },
      { deep: false } //此处 deep 配置有效!!版本更新,修复了之前无效的问题
    );

    return {
      person,
    };
  },
};
</script>

d)监视 reactive 所定义的一个响应式数据中的某个属性,这样可以解决上述请款三无法正确显示 oldValue 的问题

这里写法上和之前有点差异,第一个参数返回的是一个箭头函数.

<template>
  <h2>一个人的信息</h2>
  <div>{{ person.name }}</div>
  <div>{{ person.age }}</div>
  <div>{{ person.a.b.c }}</div>
  <button @click="person.name = 'lyj'">修改姓名</button>
  <button @click="person.age += 1">修改年龄</button>
  <button @click="person.a.b.c += 100">修改a.b.c</button>
</template>

<script>
import { reactive, ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

    //情况四
    watch(
      () => person.name,
      (newValue, oldValue) => {
        console.log("person 的 name 变化了", newValue, oldValue);
      }
    );

    return {
      person,
    };
  },
};
</script>

点就 修改姓名 按钮,效果如下: 

 

e)监视 reactive 所定义的一个响应式数据中的某些属性(这种方式可以用来解决监视 reactive 后 oldValue 变化的问题).

<template>
  <h2>一个人的信息</h2>
  <div>{{ person.name }}</div>
  <div>{{ person.age }}</div>
  <div>{{ person.a.b.c }}</div>
  <button @click="person.name = 'lyj'">修改姓名</button>
  <button @click="person.age += 1">修改年龄</button>
  <button @click="person.a.b.c += 100">修改a.b.c</button>
</template>

<script>
import { reactive, ref, watch } from "vue";
export default {
  name: "App",
  setup() {
    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

    //情况五
    watch([() => person.name, () => person.age], (newValue, oldValue) => {
      console.log("person 的 name 或 age 变化了", newValue, oldValue);
    });

    return {
      person,
    };
  },
};
</script>

依次点击 修改姓名 和 修改年龄,效果如下:

f)特殊情况:当监视的是 reactive 定义的对象中的某个属性对象或者当前对象,并且第一个参数返回的是 回调方法,deep也会生效,默认非深层监视.

1.2、watchEffect 函数

watchEffect 的参数就是一个回调.

不用指明监视的是哪个属性,只要监视的回调中用到哪个属性发生变化了,就会重新执行回调(挂载的时候也会执行一次).

<template>
  <h2>一个人的信息</h2>
  <div>{{ person.name }}</div>
  <div>{{ person.age }}</div>
  <div>{{ person.a.b.c }}</div>
  <button @click="person.name = 'lyj'">修改姓名</button>
  <button @click="person.age += 1">修改年龄</button>
  <button @click="person.a.b.c += 100">修改a.b.c</button>
</template>

<script>
import { reactive, watchEffect } from "vue";
export default {
  name: "App",
  setup() {
    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

    watchEffect(() => {
      const test1 = person.name;
      const test2 = person.a.b.c;
      console.log("watchEffect 回调执行了");
    });

    return {
      person,
    };
  },
};
</script>

刚开始组件挂载的时候会执行一次,之后分别点击 修改姓名 和 修改 a.b.c ,又会执行两次,效果如下: 

Ps:默认 deep: false,因此如果 watchEffect 中使用 person.a 的话,修改 person.a.b.c 是不会重新执行回调的.

1.3、toRef 和 toRefs

1.3.1、toRef

将指定的属性通过 toRef 就可以创建一个 ref 对象.

通俗来讲,是对源对象的属性的浅拷贝,并且将源对象对应的属性改成响应式的.

为什么要使用它?例如以下场景:

    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });

a)要给模板中展示  person 的所有属性很麻烦,每次都要 person. 的方式才能获取到对应的属性,因此可能就有人会这样操作:

    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });
    return {
      person,
      name: person.name, //模板中可以直接使用 name 表示 person.name
      age: person.age, //同理
    };

b)但是上述这种方式返回的数据不是响应式的呀,因此,就有人想到了以下方式

    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });
    return {
      person,
      name: ref(person.name), //模板中可以直接使用 name 表示 person.name
      age: ref(person.age), //同理
    };

c)虽然实现了响应式,但是这相当于是重新创建了一个新的 ref 对象,对这些数据的修改不会影响源数据,因此就需要使用 toRef 了~

    let person = reactive({
      name: "cyk",
      age: 18,
      a: {
        b: {
          c: 666,
        },
      },
    });
    return {
      person,
      name: toRef(person, "name"), //模板中可以直接使用 name 表示 person.name
      age: toRef(person, "age"), //同理
    };

1.3.2、toRefs

和 toRef 的功能一致,但是它可以直接将一个对象中的所有属性都变成响应式的,语法:toRefs(person).

    return {
      ...toRefs(person),
    };

 

1.4、vue3  的声明周期

a)vue3 中可以继续使用 vue2 中的生命周期钩子,但有两个被更名.

  • beforeDestory 改名为 beforeUnmount.
  • destroyed 改名为 unmounted.

b)vue3 中也提供了 Composition API 形式的生命周期钩子,与 vue2 中的钩子对应关系如下:

案例如下:

App 父组件定义如下

<template>
  <button @click="isShowUser = !isShowUser">切换隐藏/显示</button>
  <User v-if="isShowUser" />
</template>

<script>
import { ref } from "vue";
import User from "./views/User.vue";
export default {
  name: "App",
  components: { User },
  setup() {
    let isShowUser = ref(true);
    return {
      isShowUser,
    };
  },
};
</script>

 User 子组件如下:

<template>
  <h2>求和: {{ sum }}</h2>
  <button @click="sum++">点我 + 1</button>
</template>

<script>
import {
  ref,
  onBeforeMount,
  onBeforeUnmount,
  onBeforeUpdate,
  onMounted,
  onUnmounted,
  onUpdated,
} from "vue";
export default {
  name: "User",
  setup() {
    let sum = ref(0);

    // vue3 中可以通过组合式 API 的形式取使用声明周期的钩子
    onBeforeMount(() => {
      console.log("-------onBeforeMount-------");
    });
    onMounted(() => {
      console.log("-------onMounted-------");
    });
    onBeforeUpdate(() => {
      console.log("-------onBeforeUpdate-------");
    });
    onUpdated(() => {
      console.log("-------onUpdated-------");
    });
    onBeforeUnmount(() => {
      console.log("--------onBeforeUnmount------");
    });
    onUnmounted(() => {
      console.log("--------onUnmounted------");
    });

    return {
      sum,
    };
  },
};
</script>

使用效果如下: 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1430556.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据环境搭建(一)-Hive

1 hive介绍 由Facebook开源的,用于解决海量结构化日志的数据统计的项目 本质上是将HQL转化为MapReduce、Tez、Spark等程序 Hive表的数据是HDFS上的目录和文件 Hive元数据 metastore&#xff0c;包含Hive表的数据库、表名、列、分区、表类型、表所在目录等。 根据Hive部署模…

10 分钟在K8s 中部署轻量级日志系统 Loki

转载至我的博客 https://www.infrastack.cn &#xff0c;公众号&#xff1a;架构成长指南 Loki 是什么&#xff1f; Loki是由Grafana Labs开源的一个水平可扩展、高可用性&#xff0c;多租户的日志聚合系统的日志聚合系统。它的设计初衷是为了解决在大规模分布式系统中&#x…

WebGL+Three.js入门与实战——绘制水平移动的点、通过鼠标控制绘制(点击绘制、移动绘制、模拟画笔)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1f4c3;个人状态&#xff1a; 研发工程师&#xff0c;现效力于中国工业软件事业 &#x1f680;人生格言&#xff1a; 积跬步…

MATLAB矩阵的操作(第二部分)

师从清风 矩阵的创建方法 在MATLAB中&#xff0c;矩阵的创建方法主要有三种&#xff0c;分别是&#xff1a;直接输入法、函数创建法和导入本地文件中的数据。 直接输入法 输入矩阵时要以中括号“[ ]”作为标识符号&#xff0c;矩阵的所有元素必须都在中括号内。 矩阵的同行元…

IEC104 S帧超时判定客户与服务端不匹配造成的异常链接问题分析

2、通过ss命令发现确有链接端口变化&#xff0c;与设备约一天一次的重连&#xff0c;通过抓包&#xff08;tcpdump -vvv -nn port 1001 -w 0926.cap&#xff09;分析得以下现象 2.1、异常情况时未对设备的I帧均匀的回S帧进行确认&#xff0c;正常情况时均匀的回S帧进行确认 2.…

数据在内存中的存储(上)

1. 整数在内存中的存储 整数的2进制表示方法有三种&#xff1a;即原码、反码和补码 三种表示方法均有符号位和数值位两部分&#xff0c;符号位都是用0表示“正”&#xff0c;用1表示“负”&#xff0c;而数值位最 高位的一位是被当做符号位&#xff0c;剩余的都是数值位。 正…

深度学习水论文怎么缝模块?搭积木永不过时!(附80个即插即用模型)

深度学习如何创新&#xff1f;如何水模型&#xff1f;总结来说就八个字&#xff1a;排列组合&#xff0c;会讲故事。说直白点&#xff0c;就是缝模块。 先看看别人怎么做&#xff0c;然后根据自己的实际情况将这些模块来一波随机组合&#xff0c;这样效率会高很多。我这边已经…

冰冻天气恰逢春运,“观冰精灵”化身电力供应守护者

据中国路网&#xff0c;截至2月1日14时&#xff0c;受降雪及路面结冰影响&#xff0c;河北、山西、内蒙古、黑龙江、江苏、安徽、河南、山东、西藏、陕西、宁夏、甘肃、新疆共封闭路段66个&#xff08;涉及44条高速公路、5条普通国道、5条普通省道&#xff09;&#xff0c;关闭…

Pandas.Series.clip() 修剪数值范围 详解 含代码 含测试数据集 随Pandas版本持续更新

关于Pandas版本&#xff1a; 本文基于 pandas2.2.0 编写。 关于本文内容更新&#xff1a; 随着pandas的stable版本更迭&#xff0c;本文持续更新&#xff0c;不断完善补充。 传送门&#xff1a; Pandas API参考目录 传送门&#xff1a; Pandas 版本更新及新特性 传送门&…

前端JavaScript篇之map和Object的区别、map和weakMap的区别

目录 map和Object的区别map和weakMap的区别 map和Object的区别 Object是JavaScript的内置对象&#xff0c;用于存储键值对。Object的键必须是字符串或符号&#xff0c;值可以是任意类型。Map是ES6引入的新数据结构&#xff0c;用于存储键值对。Map的键可以是任意类型&#xff…

高中数学两面角习题练习1

用到的定理 2 第1问证明&#xff1a; 第2问用到的知识和例子&#xff1a; 二面角锐角钝角判断的快速技巧 https://www.bilibili.com/video/BV13P41157K1/?spm_id_from333.788.recommend_more_video.0&vd_source91b03ee59c462b7b3cfbd57346cf1001 叉乘的几何意义及应用 …

day39 不同路径 不同路径Ⅱ

题目1&#xff1a;62 不同路径 题目链接&#xff1a;62 不同路径 题意 机器人位于m*n网格的左上角每次只能向下或向右移动一步&#xff0c;到达网格的右下角,返回不同路径的数量 动态规划 动规五部曲 1&#xff09;dp数组及下标i的含义 dp[i][j]&#xff1a;到达(i,j)有…

2024年 复习 HTML5+CSS3+移动web 笔记 之CSS遍 第5天

第 五 天 整个网站例 5.1 准备工作 项目目录与版心 base.css 5.2 网页制作思路 5.3 header 区域-整体布局 5.4 header区域-logo 5.5 header区域-导航 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

代码随想录算法训练营29期Day41|LeetCode 343,96

文档讲解&#xff1a;整数拆分 不同的二叉搜索树 343.整数拆分 题目链接&#xff1a;https://leetcode.cn/problems/integer-break/description/ 思路&#xff1a; 题目要求我们拆分n&#xff0c;拆成k个数使其乘积和最大&#xff0c;然而题目中并没有给出k&#xff0c;所以…

[python]基于opencv实现的车道线检测

【检测原理】 一、首先进行canny边缘检测&#xff0c;为获取车道线边缘做准备 二、进行ROI提取获取确切的车道线边缘&#xff08;红色线内部&#xff09; 三、利用概率霍夫变换获取直线&#xff0c;并将斜率正数和复数的线段给分割开来 四、离群值过滤&#xff0c;剔除斜率…

uniapp 高德地图显示

1. uniapp 高德地图显示 使用前需到**高德开放平台&#xff08;https://lbs.amap.com/&#xff09;**创建应用并申请Key   登录 高德开放平台&#xff0c;进入“控制台”&#xff0c;如果没有注册账号请先根据页面提示注册账号   打开 “应用管理” -> “我的应用”页面…

Springboot集成Camunda并完成一条流程实例

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;设计流程定…

028 方法的重载

方法重载的定义 使用案例 public static void main(String[] args) {// 匹配到max(int a, int b)System.out.println(max(1, 3));// 匹配到max(double a, double b)System.out.println(max(1L, 3L));// 匹配到max(double a, double b, double c, double d)&#xff0c;int自动…

SQL 函数(十二)

SQL 函数&#xff08;十二&#xff09; 一、函数分类 1.1 单行函数 单行函数仅对单个行进行运算&#xff0c;并且每行返回一个结果。 常见的函数类型&#xff1a; 字符、数字、日期、转换 1.2 多行函数 多行函数能够操纵成组的行&#xff0c;每个行组给出一个结果&#x…

【拜年神器】AI写真保姆级教程

1. 介绍 废话不说&#xff0c;先上图看效果 功能简介 上传几张自己的照片&#xff0c;训练之后&#xff0c;就能生成各种风格的AI写真照&#xff0c;主要有无限风格写真、固定模板写真、AI虚拟试衣、人物说话视频四个类别 无限风格写真 固定模板写真 证件照 工作照 婚纱…