Vue3-Composition-API(二)

一、computed函数使用

1.computed

在前面我们讲解过计算属性computed:当我们的某些属性是依赖其他状态时,我们可以使用计算属性来处理

  • 在前面的Options API中,我们是使用computed选项来完成的;

  • 在Composition API中,我们可以在 setup 函数中使用 computed 方法来编写一个计算属性;

如何使用computed呢?

  • 方式一:接收一个getter函数,并为 getter 函数返回的值,返回一个不变的 ref 对象;
  • 方式二:接收一个具有 get 和 set 的对象,返回一个可变的(可读写)ref 对象;
const fullName = computed(() => {return firstName.value + " " + lastName.value
})
const fullName = computed({get: () => {return firstName.value + " " + lastName.value},set: newValue => {const names = newValue.split(" ")firstName.value = names[0]lastName.value = names[1]}
})

2.setup中使用ref

在setup中如何使用ref获取元素或者组件?

  • 其实非常简单,我们只需要定义一个ref对象,绑定到元素或者组件的ref属性上即可;
<template><!-- 1.获取元素 --><h2 ref="titleRef">我是标题</h2><button ref="btnRef">按钮</button><!-- 2.获取组件实例 --><show-info ref="showInfoRef"></show-info><button @click="getElements">获取元素</button>
</template><script>import { ref, onMounted } from 'vue'import ShowInfo from './ShowInfo.vue'export default {components: {ShowInfo},setup() {const titleRef = ref()const btnRef = ref()const showInfoRef = ref()// mounted的生命周期函数onMounted(() => {console.log(titleRef.value)console.log(btnRef.value)console.log(showInfoRef.value)showInfoRef.value.showInfoFoo()})function getElements() {console.log(titleRef.value)}return {titleRef,btnRef,showInfoRef,getElements}}}
</script><style scoped>
</style>

二、组件的生命周期函数

1.生命周期钩子

我们前面说过 setup 可以用来替代 data 、 methods 、 computed 等等这些选项,也可以替代生命周期钩子。

那么setup中如何使用生命周期函数呢?

  • 可以使用直接导入的 onX 函数注册生命周期钩子;
<template><div>AppContent</div>
</template><script>import { onMounted, onUpdated, onUnmounted } from 'vue'export default {beforeCreate() {},// created() {// },// beforeMount() {// },// mounted() {// },// beforeUpdate() {// },// updated() {// }setup() {// 在执行setup函数的过程中, 你需要注册别的生命周期函数onMounted(() => {console.log("onmounted")})}}
</script><style scoped>
</style>

在这里插入图片描述

三、Provide/lnject使用

1.Provide函数

事实上我们之前还学习过Provide和Inject,Composition API也可以替代之前的 Provide 和 Inject 的选项。

我们可以通过 provide来提供数据:

  • 可以通过 provide 方法来定义每个 Property;

provide可以传入两个参数:

  • name:提供的属性名称;
  • value:提供的属性值;
let counter = 100
let info = {name: 'www',age: 10
}
provide("counter", counter)
provide("info", info)

2.Inject函数

在后代组件中可以通过 inject 来注入需要的属性和对应的值:

  • 可以通过 inject 来注入需要的内容;

inject可以传入两个参数:

  • 要 inject 的 property 的 name;
  • 默认值;
const counter = inject("counter")
const info = inject("info")

3.数据的响应式

为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide 值时使用 ref 和 reactive。

let counter = ref(100)
let info = reactive({name: 'www',age: 10
})
provide("counter", counter)
provide("info", info)

四、watch/watchEffect

1.侦听数据的变化

在前面的Options API中,我们可以通过watch选项来侦听data或者props的数据变化,当数据变化时执行某一些操作。

在Composition API中,我们可以使用watchEffectwatch来完成响应式数据的侦听;

  • watchEffect:用于自动收集响应式数据的依赖;
  • watch:需要手动指定侦听的数据源;

2.Watch的使用

watch的API完全等同于组件watch选项的Property:

  • watch需要侦听特定的数据源,并且执行其回调函数;
  • 默认情况下它是惰性的,只有当被侦听的源发生变化时才会执行回调;
const name = ref('kobe')
watch(name, (newValue, oldValue) +> {console.log(newValue, oldValue)
})const changeName = () => {name.value = "james"
}

3.侦听多个数据源

侦听器还可以使用数组同时侦听多个源:

const name = ref('kobe')
const age = ref(10)
watch([name,age], (newValue, oldValue) +> {console.log(newValue, oldValue)
})const changeName = () => {name.value = "james"
}

4.watch的选项

如果我们希望侦听一个深层的侦听,那么依然需要设置 deep 为true:

  • 也可以传入 immediate 立即执行;
// 1.定义数据
const message = ref("Hello World")
const info = reactive({name: "why",age: 18,friend: {name: "kobe"}
})// 2.侦听数据的变化
watch(message, (newValue, oldValue) => {console.log(newValue, oldValue)
})
watch(info, (newValue, oldValue) => {console.log(newValue, oldValue)console.log(newValue === oldValue)
}, {immediate: true
})// 3.监听reactive数据变化后, 获取普通对象
watch(() => ({ ...info }), (newValue, oldValue) => {console.log(newValue, oldValue)
}, {immediate: true,deep: true
})

5.watchEffect

当侦听到某些响应式数据变化时,我们希望执行某些操作,这个时候可以使用 watchEffect。

我们来看一个案例:

  • 首先,watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖;
  • 其次,只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行;
const name = ref("abc")
const age = ref(18)watchEffect(() => {console.log("watchEffect执行~")
})

6.watchEffect的停止侦听

如果在发生某些情况下,我们希望停止侦听,这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。

比如在上面的案例中,我们age达到20的时候就停止侦听:

<template><div><h2>当前计数: {{ counter }}</h2><button @click="counter++">+1</button><button @click="name = 'kobe'">修改name</button></div>
</template><script>import { watchEffect, watch, ref } from 'vue'export default {setup() {const counter = ref(0)const name = ref("why")// watch(counter, (newValue, oldValue) => {})// 1.watchEffect传入的函数默认会直接被执行// 2.在执行的过程中, 会自动的收集依赖(依赖哪些响应式的数据)const stopWatch = watchEffect(() => {console.log("-------", counter.value, name.value)// 判断counter.value > 10if (counter.value >= 10) {stopWatch()}})return {counter,name}}}
</script><style scoped>
</style>

五、自定义Hook练习

1.useCounter

我们先来对之前的counter逻辑进行抽取:

import { ref, onMounted } from 'vue'export default function useCounter() {const counter = ref(0)function increment() {counter.value++}function decrement() {counter.value--}onMounted(() => {setTimeout(() => {counter.value = 989}, 1000);})return {counter,increment,decrement}
}

2.useTitle

我们编写一个修改title的Hook:

import { ref, watch } from "vue";export default function useTitle(titleValue) {// document.title = title// 定义ref的引入数据const title = ref(titleValue)// 监听title的改变watch(title, (newValue) => {document.title = newValue}, {immediate: true})// 返回ref值return {title}
}

3.useScrollPosition

我们来完成一个监听界面滚动位置的Hook:

import { reactive } from 'vue'export default function useScrollPosition() {// 1.使用reative记录位置const scrollPosition = reactive({x: 0,y: 0})// 2.监听滚动document.addEventListener("scroll", () => {scrollPosition.x = window.scrollXscrollPosition.y = window.scrollY})return {scrollPosition}
}

4.Hook练习

App.vue

<template><div>AppContent</div><button @click="changeTitle">修改title</button><!-- 1.计数器 --><!-- <hr><home></home><hr><about></about> --><!-- 2.home和about页面的切换 --><button @click="currentPage = 'home'">home</button><button @click="currentPage = 'about'">about</button><component :is="currentPage"></component><div class="content"></div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</template><script>import { ref } from 'vue'import Home from './views/Home.vue'import About from './views/About.vue'import useTitle from './hooks/useTitle'export default {components: {Home,About},setup() {const currentPage = ref("home")function changeTitle() {useTitle("app title")}return {changeTitle,currentPage}}}
</script><style scoped>.content {width: 3000px;height: 100px;background-color: orange;}
</style>

views/About.vue

<template><h2>About计数: {{ counter }}</h2><button @click="increment">+1</button><button @clcik="decrement">-1</button>
</template><script>import { onActivated } from 'vue'import useCounter from '../hooks/useCounter'import useTitle from '../hooks/useTitle'export default {setup() {// 切换标题useTitle("关于")return {...useCounter()}}}
</script><style scoped>
</style>

views/Home.vue

<template><h2>Home计数: {{ counter }}</h2><button @click="increment">+1</button><button @click="decrement">-1</button><button @click="popularClick">首页-流行</button><button @click="hotClick">首页-热门</button><button @click="songClick">首页-歌单</button><div class="scroll"><h2>x: {{ scrollPosition.x }}</h2><h2>y: {{ scrollPosition.y }}</h2></div>
</template><script>import { onMounted, ref } from 'vue'import useCounter from '../hooks/useCounter'import useTitle from '../hooks/useTitle'import useScrollPosition from '../hooks/useScrollPosition'export default {setup() {// 1.counter逻辑const { counter, increment, decrement } = useCounter()// 2.修改标题const { title } = useTitle("首页")// 3.监听按钮的点击function popularClick() {title.value = "首页-流行"}function hotClick() {title.value = "首页-热门"}function songClick() {title.value = "首页-歌单"}// 4.获取滚动位置const { scrollPosition } = useScrollPosition()console.log(scrollPosition)return {counter,increment,decrement,popularClick,hotClick,songClick,scrollPosition}}}
</script><style scoped>
</style>

六、script setup语法糖

1.script setup语法

<script setup>是在单文件组件 (SFC) 中使用组合式 API 的编译时语法糖,当同时使用 SFC 与组合式 API 时则推荐该语法

  • 更少的样板内容,更简洁的代码;
  • 能够使用纯 Typescript 声明 prop 和抛出事件;
  • 更好的运行时性能 ;
  • 更好的 IDE 类型推断性能 ;

使用这个语法,需要将 setup attribute 添加到 <script> 代码块上:

<script setup>console.log(11)
</script>

里面的代码会被编译成组件 setup() 函数的内容:

  • 这意味着与普通的 <script> 只在组件被首次引入的时候执行一次不同;
  • <script setup> 中的代码会在每次组件实例被创建的时候执行。

2.顶层的绑定会被暴露给模板

当使用 <script setup> 的时候,任何在 <script setup> 声明的顶层的绑定 (包括变量,函数声明,以及 import 引入的内容) 都能在模板中直接使用:

<script setup>const message = ref(111)
</script>
<template>message: {{ message }}
</template>

响应式数据需要通过ref、reactive来创建。

3.导入的组件直接使用

<script setup>范围里的值也能被直接作为自定义组件的标签名使用:

<script setup>import ShowInfo from './ShowInfo.vue'
</script>
<template><ShowInfo></ShowInfo>
</template>

4.defineProps() 和 defineEmits()

为了在声明 props 和 emits 选项时获得完整的类型推断支持,我们可以使用 definePropsdefineEmits API,它们将自动地在 <script setup>可用

<template><div>ShowInfo: {{ name }}-{{ age }}</div><button @click="showInfoBtnClick">showInfoButton</button>
</template><script setup>// 定义props
const props = defineProps({name: {type: String,default: "默认值"},age: {type: Number,default: 0}
})// 绑定函数, 并且发出事件
const emits = defineEmits(["infoBtnClick"])
function showInfoBtnClick() {emits("infoBtnClick", "showInfo内部发生了点击")
}// 定义foo的函数
function foo() {console.log("foo function")
}
defineExpose({foo
})</script><style scoped>
</style>

5.defineExpose()

使用 <script setup> 的组件是默认关闭的:

  • 通过模板 ref 或者 $parent 链获取到的组件的公开实例,不会暴露任何在 <script setup> 中声明的绑定;

通过 defineExpose 编译器宏来显式指定在 <script setup> 组件中要暴露出去的 property:

ShowInfo.vue

function foo() {log("foo function")
}defineExpose({foo
})

App.vue

const showInfoRef = ref(null)
function callShowInfoRef() {showInfoRef.value.foo()
}

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

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

相关文章

有哪些好用的洗地机推荐?洗地机品牌推荐

在如今快节奏的生活中&#xff0c;人们对于家居清洁的需求也越来越高。洗地机无疑成为了很多家庭清洁的得力助手。然而&#xff0c;在众多品牌和型号中&#xff0c;到底哪款洗地机值得入手呢&#xff0c;这可能是很多人都会发出的疑问&#xff0c;下面&#xff0c;我们接下来一…

JDBC - 结构优化1

JDBC - 结构优化1 文章目录 JDBC - 结构优化1三层架构1 什么是三层架构2 三层架构项目搭建 结构优化1 - 学生信息管理1 封装工具类2 ORM3 DAO 三层架构 1 什么是三层架构 **三层架构&#xff1a;**将程序划分为表示层, 业务逻辑层, 数据访问层三层&#xff0c;各层之间采用接…

vit细粒度图像分类(七)TBNet学习笔记

1.摘要 细粒度鸟类图像识别致力于实现鸟类图像的准确分类&#xff0c;是机器人视觉跟踪中的一项基础性工作。鉴于濒危鸟类的监测和保护对保护濒危鸟类具有重要意义&#xff0c;需要采用自动化方法来促进鸟类的监测。在这项工作中&#xff0c;我们提出了一种新的基于机器人视觉…

代码随想录算法训练营29期|day36任务以及具体安排

第八章 贪心算法 part05 435. 无重叠区间 class Solution {public int eraseOverlapIntervals(int[][] intervals) {Arrays.sort(intervals, (a,b)-> {return Integer.compare(a[0],b[0]);});if(intervals.length 1) return 0;int result 0;for(int i 1 ; i < interva…

分布式事务(三)—— 两阶段提交解决方案(2PC)

系列目录&#xff1a; 《分布式事务&#xff08;一&#xff09;—— 事务的基本概念》 《分布式事务&#xff08;二&#xff09;—— CAP和Base理论》 一、常见分布式事务解决方案 两阶段提交&#xff08;2PC&#xff0c;Two-phase Commit&#xff09;TCC补偿模式基于本地消…

springboot mybatis-plus 项目分层笔记

整体定义 config: 配置项&#xff0c;包含configuration注解 constants: 常量类enums: 枚举 exceptions: 全局异常处理&#xff0c;自定义异常&#xff0c;RestControllerAdvice 注解 fia3: 三大器依据执行顺序&#xff1a;过滤器filter、拦截器interceptor、切面aop 简称 fia…

算法设计与分析实验:快速选择与单调栈

目录 一、找到K个最接近的元素 1.1 具体思路 1.2 思路展示 1.3 代码实现 1.4 复杂度分析 1.5 运行结果 二、前K个高频元素 2.1 思路一&#xff1a;哈希表 2.2 思路二&#xff1a;快速选择 2.3 思路三&#xff1a;堆 三、柱形图中的最大矩形 3.1 具体思路 3.2 思路…

Mysql单行函数练习

数据表 链接&#xff1a;https://pan.baidu.com/s/1dPitBSxLznogqsbfwmih2Q 提取码&#xff1a;b0rp --来自百度网盘超级会员V5的分享 单行函数练习 单行函数(一行数据返回一个结果) #1.显示系统时间(注:日期时间) #2.查询员工工号,姓名,工资以及提高百分之20后的结果(new…

2024年Java SpringBoot 计算机软件毕业设计题目推荐

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行交流合作✌ 主要内容&#xff1a;SpringBoot、Vue、SSM、HLM…

Flume搭建

压缩包版本&#xff1a;apache-flume-1.9.0-bin.tar 百度盘链接&#xff1a;https://pan.baidu.com/s/1ZhSiePUye9ax7TW5XbfWdw 提取码&#xff1a;ieks 1.解压 tar -zxvf /opt/software/apache-flume-1.9.0-bin.tar.gz -C /opt/module/ 2. 修改文件名 [rootbigdata1 opt]…

【stm32】hal库学习笔记-FSMC连接TFT_LCD

【stm32】hal库学习笔记-FSMC连接TFT LCD 触摸屏结构与原理 LCD模块接口原理图 LCD 接口连接在 FSMC 总线上面&#xff0c;图中的 T_MISO/T_MOSI/T_PEN/T_SCK/T_CS 连接在 MCU 的 PB2/PF11/PB1/PB0/PC13 上&#xff0c;这些信号用来实现对液晶触摸屏的控制&#xff08;支持电阻…

RHCE DNS域名解析服务器

目录 1. 正向解析 1.1 安装必要软件 1.2 配置静态ip 1.3 DNS配置 1.4 测试 2. 反向解析 2.1 关闭安全软件&#xff0c;安装必要软件 2.2 配置静态ip 2.3 DNS配置 2.4 测试 1. 正向解析 1.1 安装必要软件 1.2 配置静态ip 服务器配置 nmcli c modify ens32 ipv4.method man…

如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图三

Mermaid 系列 如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图一如何使用 Mermaid、GitHub 和 VSCode 用代码创建关系图二 1.如何创建甘特图 Gantt 甘特图以条形图的形式用作可视化表示。它有效地展示了项目的时间表&#xff0c;揭示了各个项目组件完成所需的持续时间…

leetcode刷题(剑指offer) 509.斐波那契数

509.斐波那契数 斐波那契数 &#xff08;通常用 F(n) 表示&#xff09;形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始&#xff0c;后面的每一项数字都是前面两项数字的和。也就是&#xff1a; F(0) 0&#xff0c;F(1) 1 F(n) F(n - 1) F(n - 2)&#xff0c;其中 n…

Java玩转《啊哈算法》排序综合篇之小哼买书

是诸法空相&#xff0c;不生不灭&#xff0c;不垢不净&#xff0c;不增不减 非目录 缘起代码地址案例桶排序冒泡排序快速排序 缘起 各位大哥大姐&#xff0c;兄弟姐妹们好呀&#xff01;本人最近看了下《啊哈算法》&#xff0c;说来惭愧&#xff0c;买几年了&#xff0c;当初看…

Office提取某一页转成图片

目录结构 前言支持的文件格式代码整理maven依赖文本文档解析转换电子表格解析转换演示文档解析转换PDF解析转换小编代码整理(完整版)特别感谢扩展前言 近期公司需求,要将office文件提取第一页内容转成图片;一番调查后整理如下: 支持的文件格式 文本文档电子表格演示文档…

协会认证!百望云荣获信创工委会年度“卓越贡献成员单位”称号

当前&#xff0c;新一轮科技革命和产业变革正加速重塑全球经济结构&#xff0c;强化企业科技创新的主体地位&#xff0c;推动创新链、产业链、人才链深度融合&#xff0c;加快科技成果产业化进程至关重要。 近日&#xff0c;中国电子工业标准化技术协会信息技术应用创新工作委员…

HTTP中传输协议的数据格式

HTTP 概述&#xff1a;超文本传输协议(Hyper Text Transfer Protocol) 传输协议&#xff1a;定义了客户端和服务器通信时&#xff0c;发送数据的格式 客户端和服务器端交互&#xff1a;客户端向服务器端发送请求&#xff0c;服务器端向客户端响应请求 HTTP特点&#xff1a;…

安装mysql和navicat

1 安装mysql 以下是 MySQL 的安装教程: 步骤 1:下载 MySQL 首先在官方网站上下载 MySQL 安装包。在下载页面中选择第一个安装包,然后点击“下载”按钮,下载后解压缩。 下载地址 步骤 2:配置环境变量 配置MYSQL_HOME path 中添加%MYSQL_HOME%\bin 添加 my.ini ,内容…

1月威胁态势 | 0day占比83%!两大勒索家族“均分天下”

近日&#xff0c;亚信安全正式发布《亚信安全2024年1月威胁态势报告》&#xff08;以下简称“报告”&#xff09;报告显示&#xff0c;1月份新增安全漏洞1511个&#xff0c;涉及0day漏洞占83%&#xff1b;监测发现当前较活跃的勒索病毒家族是Wacatac和Nemucod&#xff0c;病毒样…