Vue3.0(四):Composition API的使用

Composition API

认识Composition API

前几篇文章中主要用Options API进行编写代码,但是有一些弊端

  • Options API弊端
    • Options API中,有data、watch、computed、methods以及生命周期函数各种各样的选项
    • 而一个变量,为了实现某个功能,会分散在各个选项中,不利于代码的维护
  • 此时 Composition API就出现了
    • 使用 setup函数可以将大部分选项代替,data、watch、computed、methods以及生命周期函数

ssetup函数的参数

  • setup函数主要有两个参数

    • props
    • context
  • props是一个对象,包含着父组件传递过来的属性

  • context主要包含三个属性

    • attrs:所有的非prop的attribute
    • **slots:**父组件传递过来的插槽(在以渲染函数返回时会有作用)
    • **emit:**当我们组件内部需要发出事件时,会用到emit(在setup函数中,不能访问this)
  • 简单实现

<template><div><span>{{ count }}</span><button @click="add">+1</button><button @click="deAdd">-1</button></div>
</template><script>
//引入ref函数
import { ref } from "vue";
export default {setup() {//定义变量,此时count并不是响应式数据,需要用ref进行包裹let count = ref(0);//定义函数//要对count进行修改,需要通过.value的方式进行修改let add = () => count.value++;let deAdd = () => count.value--;//将变量以及函数返回出去,template中才可以使用return {count,add,deAdd,};},
};
</script>
  • 同时我们可以将内部的逻辑代码,封装单独的一个文件,而后进行引入
<script>
//引入函数
import counter from "./utils/counter";export default {setup() {let { count, add, deAdd } = counter();return {count,add,deAdd,};},
};
</script>
-------还可以做以下优化
<script>
//引入函数
import counter from "./utils/counter";export default {setup() {return {...counter()};},
};
</script>

setup定义数据

  • 定义普通函数
setup(){//可以直接使用,但不是响应式let message = "hello"return{message}
}
  • 定义响应式数据(reactive
    • 定义复杂数据:对象/数组等,不能传入普通类型的,比如字符串等
    • option api中data中定义的数据实际上就是交给了reactive函数
import {reactive} from "vue"
setup(){//此时就是响应式了let obj = reactive({a:100,b:200})//对obj进行修改obj.a = 300return{obj}
}
  • 定义响应式数据(ref):返回的是ref对象,需要使用.value进行获取值
    • 定义简单类型的响应式数据
    • 也可以定义复杂类型的数据
    • 但是在template中,会自动解包,即自动获取 变量.value的值,直接使用变量即可
<template>{{count}}    
</template>import {ref} from "vue"
setup(){//定义简单数据,也可以定义复杂数据let count = ref(0)//修改变量count.value = 100return {count    }
}

ref定义数据和reactive定义数据的开发

  • 在实际开发中,使用ref的频次比较多
    • ref可以定义复杂数据
  • reactive应用场景
    • 应用于本地数据const obj = reactive({username:"123"}),不是从数据库中得来的
    • 多个数据之间是有关系/联系的 const user = reactive({username:"admin",password:"123456"})
  • ref应用场景:其余的场景基本都用ref
    • 定义本地的简单数据
    • 定义从网络获取的数据
const music = ref([])   
onMounted(()=>{const serverMusic = ["野狼","小苹果"]music.value = serverMusic
})

单向数据流的规范和做法

  • 父组件传递给子组件一个对象/数组,此时,子组件能否对其进行修改?
  • 在代码层面,子组件是可以进行修改的 —但是,不符合规范
  • 因为父组件引用的子组件很多的情况下,若子组件擅自修改了对象中的数据,那么就不清楚到底是谁对数据进行了修改
  • 正确的做法
    • 父组件将数据传递给了子组件
    • 子组件抛出事件,以及要修改的值
    • 父组件使用 @子组件事件,来将数据进行修改

readonly函数

创建出来的数据也是响应式数据,但是不能对数据进行修改,但是我们可以对元数据进行修改

  • 其返回的也是一个Proxy对象,只是setter方法受到了限制
setup(){let obj = ref({a:100})//此时readonlyObj不能进行修改,可以将其传给子组件let readonlyObj = readonly(obj)//若我们向修改其内容,可以对obj进行修改}

Reactive判断的API

  • isProxy

    • 检查对象 是否由reactive或者readonly创建的Proxy
  • isReactive

    • 检查对象是否由 reactive创建的响应式代理
  • isReadonly

    • 检查对象 是否由readonly创建的只读代理
  • toRaw

    • 返回proxy代理对象的原始数据
  • shallowReactive

    • 创建一个响应式代理,但是只响应浅层次的数据
  • shallowReadonly

    • 创建一个响应式代理,但是不执行嵌套对象的深度只读转换

toRef和toRefs

  • 现在有如下代码
    • 我们在使用user的时候,想直接通过name age height的方式直接展示
    • 不是通过 user.name user.age user.height的方式展示
<template><div><div>{{ user.name }}-{{ user.age }}-{{ user.height }}</div><button @click=""></button></div>
</template><script>
//引入函数
import { reactive, ref, toRef, toRefs } from "vue";export default {setup() {let user = reactive({name: "zhangcheng",age: 18,height: 1.88,});return {user,};},
};
</script><style scoped></style>
  • 为了实现上述要求可以将user进行解构
    • 之后将解构的数据返回出去
 const {name,age,height} = user
  • 但是解构出来的变量,就是普通的变量,不再是响应式数据了
    • 因此我们可以通过 toRef和toRefs方法进行操作
let user = reactive({name: "zhangcheng",age: 18,height: 1.88,
});//toRefs对多个值进行ref转化
const { name, age } = toRefs(user);
// toRef对某个属性进行ref转化
const height = toRef(user, "height");
  • 这种做法实际上是将 name.value与user.name做了某种联系,使其中一方修改,另外一方也会进行修改

ref定义数据其他的API

unref

  • unref实际上是 语法糖
    • 其内部会先判断传进来的参数是否是ref对象,是的化就返回 ref.value,不是的化就直接返回值本身
const a = ref(2)
const b = unref(a)//内部实际上是 b = isRef(a)?a.value:a

isRef

  • 判断值 是否是一个ref对象

setup函数中不能使用this

  • 在官方文档中,有对setup函数中不能使用this进行过提示
  • 大概意思如下
    • this并没有指向当前组件的实例
    • setup被调用之前,data,computed、methods等都没有被解析

computed函数使用

当某些数据需要进行某些逻辑转化,再显示,就会用到计算属性 computed

  • 在里面传入一个回调函数,默认调用的是其中的getter方法
    • 此时 computedStr变量就是计算属性
    • 且这个计算属性,是只读的
import {computed} from "vue"
setup(){const computedStr = computed(()=>{return "a+b"}) return {computedStr}
}
  • 如果想要调用computed中的getter方法,需要在computed函数中传入对象
    • computed函数返回值实际上是ref对象
    • 因此想要修改的话,需要使用 .value进行修改
import {computed} from "vue"
//可以调用setter方法
const computedObjStr = computed({set: function (newValue) {const temp = newValue.split(" ");str.first = temp[0];str.last = temp[1];},get: function () {return str.first + str.last;},
});
//若想修改computedObjStr的话,需要computedObjStr.value="li si"

ref引入元素

此ref不是定义数据的ref

在vue中,我们可以通过ref this.$refs.ref进行获取元素,那么在setup函数中怎么使用

  • 直接在setup函数内部打印 ref引用的元素是不会获取到的
  • 因此,需要在onMounted生命周期中查看
<template><div><div ref="table">123</div><div ref="divEl">456</div></div>
</template><script>
//引入函数
import { onMounted, ref, reactive, computed } from "vue";export default {setup() {const refTable = ref();const divEl = ref();onMounted(() => {//需要使用.value获取值//对于组件使用也是如此console.log(refTable.value);console.log(divEl.value);});return {//两种返回方式,一种是对象的增强写法table: refTable,divEl,};},
};
</script><style scoped></style>

生命周期钩子

在setup中使用生命周期的方式 onX

  • 需要进行导入 生命周期的函数调用
  • 之后再 其内部传入函数,才是生命周期的函数
  • vue的官网中,有这样的提示,setup就是围绕 beforeCreate和created进行的,因此之前在该生命周期中做的事,可以直接写在setup中
选项式APIHook inside setup
beforeCreate不需要
created不需要
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeUnmountonBeforeUnmount
unmountedonUnmounted
activatedonActivated
deactivatedonDeactivated
import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onActivated,onDeactivated,
} from "vue";
setup() {onMounted(() => {console.log("onMounted 执行");});return {};
},

provide和inject函数

  • option API中我们用到了provide和inject用于组件之间传递数据
  • 那么 在 composition API中要怎么使用
  • provide(key,value):key是传递参数的代表,value 是具体数据
  • inject(key,default):key是父组件传递参数的代表,default是父组件没有传递数据的时候的默认值
import { provide, inject } from "vue";
//父组件
const obj = ref({ a: 100 })
provide("objStr", obj)//子组件
inject("objStr",{a:0})

侦听数据的变化

在option API中使用的是watch中进行监听数据的变化,那么在composition中怎么进行监听

watch

  • 首先导入 watch函数
  • 基本使用
    • 可以监听多个数据
    • newValue, oldValue返回的都是proxy对象
import { reactive, ref, watch } from "vue";export default {setup() {/*** 参数* 1.数据源*    针对于ref包裹的需要监听.value*    使用数组可以监听多个数据* 2.执行的逻辑* 3.配置项:配置deep以及immediate*    默认就是深度监听*///定义数据let obj = ref({ a: 100, b: { c: 200 } });let objRea = reactive({ username: "zhangcheng" });//对数据进行监听watch([objRea, obj.value], (newValue, oldValue) => {console.log(newValue, oldValue);},{immediate: true,});return { obj, objRea };},
};
};
  • newValue, oldValue返回的是普通对象
    • 数据源需要传递一个函数
    • 且配置项中需要进行深度监听的配置,默认不启用深度监听
    /*** 参数* 1.数据源*    针对于ref包裹的需要监听.value*    使用数组可以监听多个数据* 2.执行的逻辑* 3.配置项:配置deep以及immediate*    默认就是深度监听*/let obj = ref({ a: 100, b: { c: 200 } });let objRea = reactive({ username: "zhangcheng", b: { c: 200 } });watch(() => ({ ...obj.value, ...objRea }),(newValue, oldValue) => {console.log(newValue, oldValue);},{deep: true,immediate: true,});

watchEffect

相较于watch而言,watchEffect可以自动监听依赖变量的变化

  • 传入warchEffect中的回调函数,在页面初次加载的时候会先执行一次
  • 而后在依赖的数据发生变化的时候,也会执行回调函数
  • 同时,达到某一个条件的时候,可以停止数据的监听
const stopWatch = watchEffect(() => {//当obj.value发生变化的时候,会自动调用这个回调函数console.log(obj.value);//执行watchEffect的返回值,就可以停止对数据的监听if (obj.value > 10) {stopWatch();}
});

script setup语法

本质就是setup函数的语法糖

  • 就是在 script的标签中加入setup的attribute
    • 这种写法有更好的运行效率,因为内部会将script与template模板放在同一个作用域中
    • 代码会更加的简洁
    • 有更好的提示
<script setup>//实际上就是在setup中在编写代码//不用写return
</script>

顶层的绑定会直接暴露给模板

  • script setup标签中直接写的内容,在template中可以直接使用
    • 若是在函数中,定义一个变量,则不属于顶层
<template>{{ message }}
</template><script setup>
//引入函数
import { ref } from "vue";let message = ref(123);
</script><style scoped></style>

导入组件直接使用

  • 导入的组件,无需注册, 直接在template中使用即可
<template><home-vue></home-vue>
</template><script setup>
//导入组件直接使用
import HomeVue from "./components/HomeVue";</script><style scoped></style>
  • 子组件通过 defineProps()接受父组件传进来的参数,defineEmits()发送事件
<template><button @click="messageClick">{{ message }}</button>
</template><script setup>
//defineEmits和defineProps都是内部绑定的,因此不用注册//接受参数
defineProps({message: {type: String,default: "默认信息",},
});//定义发射的事件
const messageEmit = defineEmits(["message-click"]);
function messageClick() {messageEmit("message-click", "传递参数");
}
</script><style scoped></style>

defineExpose将子组件中的数据暴露

默认都是在 <script setup></script>标签中写的代码

  • 子组件
    • 定义变量,函数等,之后暴露出去
import { ref } from "vue";function expsoeFun() {console.log("暴露出去了");
}
const message = ref("我是变量");
//子组件中有一个函数想被父组件直接调用,需要用到 defineExpose将函数暴露,或者将变量暴露
defineExpose({ expsoeFun, message });
  • 父组件
    • 首先通过ref获取子组件,之后调用其暴露的内容即可
import { onMounted, ref } from "vue";
import HomeVue from "./components/HomeVue.vue";//绑定实例
const homeVue = ref();
onMounted(() => {//调用实例中的方法homeVue.value.exposeFun();//获取实例中的变量console.log(homeVue.value.message);
});

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

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

相关文章

【数据分析岗】8家知名企业秋招(含实习)面试题汇总

年底了&#xff0c;技术群组织了一场机器学习算法岗技术&面试讨论会&#xff0c;邀请了一些同学分享他们的面试经历&#xff0c;讨论会会定期召开&#xff0c;如果你想加入我们的讨论群或者希望要更详细的资料&#xff0c;文末加入。 喜欢本文记得收藏、关注、点赞 文章目…

力扣精选算法100道—— 连续数组(前缀和专题)

连续数组&#xff08;前缀和专题&#xff09; 目录 &#x1f6a9;了解题意 &#x1f6a9;算法原理 ❗为什么hash设置成<0,-1>键值对 ❗与和为K的子数组比较hash的键值对 &#x1f6a9;代码实现 &#x1f6a9;了解题意 我们看到给定数组里面只有0和1&#xff0c;我们…

植物生长调节剂行业调研:预计2029年将达到1.2亿美元

未来增长的重点势必在以中国为代表的亚太地区。尤其在我国农业现代化、无人化发展需求下&#xff0c;提升种植的效率和品质是必然需求&#xff0c;我国市场规模增速也将高于全球平均水平。植物生长调节剂的应用具有成本低、收效快、效益高、节省劳动力的优点&#xff0c;不仅对…

Elasticsearch:使用 LangChain 文档拆分器进行文档分块

使用 Elasticsearch 嵌套密集向量支持 这个交互式笔记本将&#xff1a; 将模型 “sentence-transformers__all-minilm-l6-v2” 从 Hugging Face 加载到 Elasticsearch ML Node 中使用 LangChain 分割器将段落分块成句子&#xff0c;并使用嵌套密集向量将它们索引到 Elasticse…

fghbbbbbbbbbb

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 磁盘满的本质分析 专栏&#xff1a;《Linux从小白到大神》 | 系统学习Linux开发、VIM/GCC/GDB/Make工具…

LeetCode 二叉树/n叉树的解题思路

二叉树 二叉树特点是每个节点最多只能有两棵子树&#xff0c;且有左右之分二叉树的数据结构如下&#xff1a; public class TreeNode {//节点的值int val;//左子树TreeNode left;//右子树TreeNode right;TreeNode(int x) { val x; } }树节点的初始化&#xff1a; int val1;T…

Flink Checkpoint过程

Checkpoint 使用了 Chandy-Lamport 算法 流程 1. 正常流式处理&#xff08;尚未Checkpoint&#xff09; 如下图&#xff0c;Topic 有两个分区&#xff0c;并行度也为 2&#xff0c;根据奇偶数 我们假设任务从 Kafka 的某个 Topic 中读取数据&#xff0c;该Topic 有 2 个 Pa…

机器学习与深度学习

什么是机器学习 机器学习是一门跨学科的学科&#xff0c;它致力于研究和开发让计算机能够模拟人类学习行为的技术和方法。机器学习涉及多个学科的知识&#xff0c;如概率论、统计学、逼近论、凸分析、算法复杂度理论等&#xff0c;这些学科为机器学习提供了理论基础和数学工具…

【Linux】gdb调试与make/makefile工具

目录 导读 1. make/Makefile 1.1 引入 1.2 概念 1.3 语法规则 1.4 示例 2. Linux调试器-gdb 2.1 引入 2.2 概念 2.3 使用 导读 我们在上次讲了Linux编辑器gcc\g的使用&#xff0c;今天我们就来进一步的学习如何调试&#xff0c;以及makefile这个强大的工具。 1. mak…

nginx:配置内网转发阿里云oss图片加水印

图片水印文档 https://help.aliyun.com/zh/oss/user-guide/add-watermarks nginx配置如下 location ^~ /oss/ {if ( $request_uri ~* \.(png|jpg|jpeg) ){set $args "x-oss-processstyle/watermark";}proxy_pass http://<bucket>.oss-cn-beijing-internal.al…

人工智能基础部分24-人工智能的数学基础,汇集了人工智能数学知识最全面的概况

、 大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能基础部分24-人工智能的数学基础&#xff0c;汇集了人工智能数学知识最全面的概况&#xff0c;深度学习是一种利用多层神经网络对数据进行特征学习和表示学习的机器学习方法。要全面了解深度学习的数学基…

FlinkSql通用调优策略

历史文章迁移&#xff0c;稍后整理 使用DataGenerator 提前进行压测&#xff0c;了解数据的处理瓶颈、性能测试和消费能力 开启minibatch&#xff1a;"table.exec.mini-batch.enabled", "true" 开启LocalGlobal 两阶段聚合&#xff1a;"table.exec.m…

netstat: 未找到命令

当您在Linux系统中遇到“netstat: 未找到命令”的提示时&#xff0c;这通常意味着您的系统上没有安装netstat工具。Netstat是一个用于显示网络连接、路由表、接口统计等网络相关信息的命令行工具。 要解决这个问题&#xff0c;您可以按照以下步骤进行操作&#xff1a; 1. 打开…

java springBoot项目实现数据脱敏的策略

在实际的软件开发中&#xff0c;保护用户隐私数据是非常重要的。在Java Spring Boot项目中&#xff0c;通常需要对敏感数据进行脱敏处理&#xff0c;以确保数据安全性。本文将介绍几种常见的数据脱敏策略&#xff0c;并提供相应的实现方式和示例代码。 1、使用Hutool工具类进行…

Leetcode 2641. 二叉树的堂兄弟节点 II

本题为修改给定二叉树中结点的值&#xff0c;修改的规则为&#xff1a;将原来的值替换为该结点所有堂兄弟结点值的和。 其实我们可以延申一下题意&#xff0c;怎样去计算该结点所有堂兄弟结点值的和&#xff1f;其实只需要先计算每一层所有结点的和&#xff0c;再减掉其本身的…

如何做零售企业满意度调查

零售业满意度调研是一项至关重要的市场研究工作&#xff0c;它能够帮助企业深入了解消费者对零售店的整体印象、商品质量、服务质量等方面的评价。这种评价可以帮助企业了解自身的优势和不足&#xff0c;提高企业的市场竞争力。民安智库&#xff08;第三方市场调研公司&#xf…

《学成在线》微服务实战项目实操笔记系列(P1~P62)【上】

《学成在线》项目实操笔记系列【上】&#xff0c;跟视频的每一P对应&#xff0c;全系列12万字&#xff0c;涵盖详细步骤与问题的解决方案。如果你操作到某一步卡壳&#xff0c;参考这篇&#xff0c;相信会带给你极大启发。同时也欢迎大家提问与讨论&#xff0c;我会尽力帮大家解…

nginx登录用户验证配置

我们的nginx端口一般都是对外开放的&#xff0c;所以有一定程度上有被别人扫描的风险&#xff0c;所以为了减少被扫描的风险&#xff0c;我们可以配置一个nginx的用户登录验证&#xff1b; 用户验证登录需要nginx的一个模块&#xff1a;ngx_http_auth_basic_module 我们使用…

进程间通信(4):消息队列

先进先出&#xff0c;保证信息的有序性。 函数&#xff1a;msgget(搭配ftok)、msgsnd、msgrcv、msgctl 实现流程&#xff1a; 1、创建消息队列IPC对象 msgget 2、通信(内置函数&#xff1a;msgsnd、msgrcv) 3、删除消息队列IPC对象 msgctl write.c /* * 文件名称&…

PyTorch 2.2 中文官方教程(八)

训练一个玛丽奥玩游戏的 RL 代理 原文&#xff1a;pytorch.org/tutorials/intermediate/mario_rl_tutorial.html 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 注意 点击这里下载完整的示例代码 作者&#xff1a; 冯元松, Suraj Subramanian, 王浩, 郭宇章。 这个…