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

目录

一、组合式 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.nameage: person.age, //同理};

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

    let person = reactive({name: "cyk",age: 18,a: {b: {c: 666,},},});return {person,name: ref(person.name), //模板中可以直接使用 name 表示 person.nameage: 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.nameage: 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.mzph.cn/news/665357.shtml

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

相关文章

【蓝桥杯】环形链表的约瑟夫问题

目录 题目描述&#xff1a; 输入描述&#xff1a; 输出描述&#xff1a; 示例1 解法一&#xff08;C&#xff09;&#xff1a; 解法二&#xff08;Cpp&#xff09;&#xff1a; 正文开始&#xff1a; 题目描述&#xff1a; 据说著名犹太历史学家 Josephus 有过以下故事&a…

Pytest测试用例参数化

pytest.mark.parametrize(参数名1,参数名2...参数n, [(参数名1_data1,参数名2_data1...参数名n_data1),(参数名1_data2,参数名2_data2...参数名n_data2)]) 场景&#xff1a; 定义一个登录函数test_login,传入参数为name,password&#xff0c;需要用多个账号去测试登录功能 # …

JAVA方法引用:

方法引用的出现原因在使用Lambda表达式的时候&#xff0c;我们实际上传递进去的代码就是一种解决方案&#xff1a;拿参数做操作那么考虑一种情况&#xff1a;如果我们在Lambda中所指定的操作方案&#xff0c;已经有地方存在相同方案&#xff0c;那是否还有必要再写重复逻辑呢&a…

Java SWT Composite 绘画

Java SWT Composite 绘画 1 Java SWT2 Java 图形框架 AWT、Swing、SWT、JavaFX2.1 Java AWT (Abstract Window Toolkit)2.2 Java Swing2.3 Java SWT (Standard Widget Toolkit)2.4 Java JavaFX 3 比较和总结 1 Java SWT Java SWT&#xff08;Standard Widget Toolkit&#xff…

02 使用jdk运行第一个java程序:HelloWorld

使用jdk运行第一个java程序 1 HelloWorld小案例1.1 编写流程1.2 错误示例 首先在CMD命令行里面&#xff0c;使用javac xxxx.java&#xff0c; 进行编译&#xff0c;其中会有报错&#xff1b; 然后生成xxxx.class 文件&#xff0c;然后使用java xxxx.class 进行运行。 1 HelloWo…

瑞_23种设计模式_抽象工厂模式

文章目录 1 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;1.1 概念1.2 介绍1.3 小结1.4 结构 2 案例一2.1 案例需求2.2 代码实现 3 案例二3.1 需求3.2 实现 4 总结4.1 抽象工厂模式优缺点4.2 抽象工厂模式使用场景4.3 抽象工厂模式VS工厂方法模式4.4 抽象工厂…

node.js基础--01

Author nodes&#xff1a;&#xff08;题记&#xff09; node.js is an open-source&#xff0c;cross-platform JAVAScript runtime environment。 node.js是一个开源&#xff0c;跨平台的js运行环境 common commands&#xff08;常用指令&#xff09; 1、C: enter hard …

javaScript的序列化与反序列化

render函数的基本实现 javaScript的序列化与反序列化 一&#xff0c;js中的序列化二&#xff0c;序列化三&#xff0c;反序列化四&#xff0c;总结 一&#xff0c;js中的序列化 js中序列化就是对象转换成json格式的字符串&#xff0c;使用JSON对象的stringify方法&#xff0c;…

新书速览|Python数据科学应用从入门到精通

系统教授数据科学与Python实战&#xff0c;涵盖线性回归、逻辑回归、决策树、随机森林、神经网 本书内容 随着数据存储、数据处理等大数据技术的快速发展&#xff0c;数据科学在各行各业得到广泛的应用。数据清洗、特征工程、数据可视化、数据挖掘与建模等已成为高校师生和职场…

STL——空间配置器

空间配置器是STL六大组件之一&#xff0c;它和其他五个组件相互配合&#xff0c;起着很关键的作用。 容器&#xff1a;各种数据结构、如vector、list、stack、deque、queue、set、map、unordered_map等等算法&#xff1a;各种算法&#xff0c;如sort、serach、copy、erase 提供…

C#用正则表达式验证格式:电话号码、密码、邮编、手机号码、身份证、指定的小数点后位数、有效月、有效日

正则表达式在程序设计中有着重要的位置&#xff0c;经常被用于处理字符串信息。 用Regex类的IsMatch方法&#xff0c;使用正则表达式可以验证电话号码是否合法。 一、涉及到的知识点 Regex类的IsMatch方法用于指示正则表达式使用pattern参数中指定的正则表达式是否在输入字符串…

计算机网络_1.6.2 计算机网络体系结构分层的必要性

1.6.2 计算机网络体系结构分层的必要性 一、五层原理体系结构每层各自主要解决什么问题1、物理层2、数据链路层3、网络层4、运输层5、应用层 二、总结三、练习 笔记来源&#xff1a; B站 《深入浅出计算机网络》课程 本节主要介绍实现计算机网络需要解决哪些问题&#xff1f;以…

这种学习单片机的顺序是否合理?

这种学习单片机的顺序是否合理&#xff1f; 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「单片机的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01…

随着网络的快速发展,网络安全问题也日益凸显,遇到攻击该如何处理,如何抉择合适的防护方案

DexunCloud 经过研究发现当今世界&#xff0c;随着网络的快速发展&#xff0c;网络安全问题也日益凸显。其中&#xff0c;DDoS&#xff08;分布式拒绝服务&#xff09;攻击被认为是网络安全领域里最为严重的威胁之一。毫无疑问&#xff0c;DDoS攻击不仅可以导致网络服务中断&am…

支付宝直连商户处理支付交易投诉管理,支持多商户

大家好&#xff0c;我是小悟 1、问题背景 玩过支付宝生态的&#xff0c;或许就有这种感受&#xff0c;如果收到投诉单&#xff0c;不会通知到手机端&#xff0c;只会在支付宝商家后台-账号中心-安全中心-消费者投诉-支付交易投诉那里显示。那你能一直盯着电脑看吗&#xff1f;…

Flink CEP(基本概念)

Flink CEP 在Flink的学习过程中&#xff0c;我们已经掌握了从基本原理和核心层的DataStream API到底层的处理函数&#xff0c;再到应用层的Table API和SQL的各种手段&#xff0c;可以应对实际应用开发的各种需求。然而&#xff0c;在实际应用中&#xff0c;还有一类更为复…

AI Partition(银灿U盘分区工具)V2.0.0.3

AI Partition(银灿U盘分区工具)V2.0.0.3.zip 复制链接下载吧 https://url20.ctfile.com/f/36743220-1017367709-67f1b9?p2024 (访问密码: 2024) 支持IS903B IS902E IS916 AI Partition(银灿U盘分区量产工具) 这个是银灿官方发布的最新版U盘分区工具&#xff0c;版本号V2.0.0…

翻转二叉树

226. 翻转二叉树 已解答 简单 相关标签 相关企业 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a…

从零学习Linux操作系统 第二十五部分 文本处理工具

一、grep命令的基本使用方法及常用参数介绍 grep [全称&#xff1a;Globally search a Regular Expression and Print 全局搜索正则表达式并打印 ] grep 命令格式 grep 匹配条件 处理文件 grep root passwd过滤root关键字grep -i root passwd后略大小写grep -E “<root”…

嵌入式中物联网核心技术有哪些

IoT军事技术 物联网军事技术是一项利用IoT感知技术在军事活动中获取人、装备、作战环境状态的信息特征&#xff0c;从而实现在军事活动中做出智能化决策和控制局势的军事方针。 据悉&#xff0c;早于2012年10月军方联合了社会研究机构合力创建了“军事物联网联合实验室”。 …