title: Vue3使用Composition API实现响应式

date: 2024/5/29 下午8:10:24

updated: 2024/5/29 下午8:10:24

categories:

  • 前端开发

tags:

  • Vue3
  • Composition
  • Refs
  • Reactive
  • Watch
  • Lifecycle
  • Debugging

1. 介绍

Composition API是Vue.js 3中新增的一组API,用于在组件中组合逻辑和功能。它可以让你更好地组织和重用代码,使组件更易于理解和维护。在使用Composition

API时,你可以使用<script setup>语法或setup()函数,两种方式都可以使用Composition API中的响应式API、生命周期钩子、模板引用和自定义渲染函数等特性。

2. 基本响应式

在Vue.js 3中,Composition API提供了几种创建响应式数据的方法,包括refreactivereadonlyshallowReactive

shallowReadonly

2.1 ref

ref函数用于创建一个响应式的ref对象,其值可以通过.value

属性获取或设置。当ref对象的值发生变化时,Vue.js会自动更新视图。AD:首页 | 一个覆盖广泛主题工具的高效在线平台

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script setup>
import { ref } from 'vue'; const count = ref(0); function increment() {
count.value++;
}
</script>

2.2 reactive

reactive函数用于创建一个响应式的对象,其所有属性都是响应式的。当对象的属性发生变化时,Vue.js会自动更新视图。

<template>
<div>
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
<button @click="incrementAge">+1</button>
</div>
</template> <script setup>
import { reactive } from 'vue'; const user = reactive({
name: 'Alice',
age: 20
}); function incrementAge() {
user.age++;
}
</script>

2.3 readonly

readonly函数用于创建一个只读的响应式对象,其所有属性都是只读的。当试图修改只读对象的属性时,会抛出一个错误。

<template>
<div>
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
</div>
</template> <script setup>
import { reactive, readonly } from 'vue'; const user = reactive({
name: 'Alice',
age: 20
}); const readonlyUser = readonly(user); // 会抛出一个错误
readonlyUser.age = 21;
</script>

2.4 shallowReactive

shallowReactive函数用于创建一个浅响应式的对象,其所有属性都是响应式的,但其子对象的属性不是响应式的。

AD:专业搜索引擎

<template>
<div>
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
<p>address: {{ user.address }}</p>
<button @click="incrementAge">+1</button>
<button @click="changeAddress">改变地址</button>
</div>
</template> <script setup>
import { shallowReactive } from 'vue'; const user = shallowReactive({
name: 'Alice',
age: 20,
address: {
province: 'Beijing',
city: 'Beijing'
}
}); function incrementAge() {
user.age++;
} function changeAddress() {
user.address = {
province: 'Shanghai',
city: 'Shanghai'
};
}
</script>

2.5 shallowReadonly

shallowReadonly函数用于创建一个浅只读的响应式对象,其所有属性都是只读的,但其子对象的属性不是只读的。

<template>
<div>
<p>name: {{ user.name }}</p>
<p>age: {{ user.age }}</p>
<p>address: {{ user.address }}</p>
<!-- 会抛出一个错误 -->
<button @click="changeAddress">改变地址</button>
</div>
</template> <script setup>
import { shallowReactive, shallowReadonly } from 'vue'; const user = shallowReactive({
name: 'Alice',
age: 20,
address: {
province: 'Beijing',
city: 'Beijing'
}
}); const readonlyUser = shallowReadonly(user); // 会抛出一个错误
readonlyUser.age = 21;
</script>

3. 响应式API

Composition API提供了几种响应式API,包括watchEffectwatchcomputedprovide/inject

3.1 watchEffect

watchEffect函数用于创建一个响应式的副作用函数,当响应式数据发生变化时,副作用函数会自动重新执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script setup>
import { ref, watchEffect } from 'vue'; const count = ref(0); watchEffect(() => {
console.log(`count is ${count.value}`);
}); function increment() {
count.value++;
}
</script>

3.2 watch

watch函数用于创建一个响应式的监听器,当响应式数据发生变化时,监听器会自动执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script setup>
import { ref, watch } from 'vue'; const count = ref(0); watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`);
}); function increment() {
count.value++;
}
</script>

3.3 computed

computed函数用于创建一个响应式的计算属性,其值是根据响应式数据计算得出的。当响应式数据发生变化时,计算属性会自动重新计算。

AD:漫画首页

<template>
<div>
<p>count: {{ count }}</p>
<p>doubleCount: {{ doubleCount }}</p>
<button @click="increment">+1</button>
</div>
</template> <script setup>
import { ref, computed } from 'vue'; const count = ref(0); const doubleCount = computed(() => {
return count.value * 2;
}); function increment() {
count.value++;
}
</script>

3.4 provide/inject

provideinject函数用于在组件树中传递数据。provide函数用于在父组件中提供数据,inject函数用于在子组件中注入数据。

<template>
<div>
<ChildComponent />
</div>
</template> <script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue'; provide('message', 'Hello, world!');
</script>
<template>
<div>
<p>{{ message }}</p>
</div>
</template> <script setup>
import { inject } from 'vue'; const message = inject('message');
</script>

4. 生命周期钩子

Composition

API提供了几种生命周期钩子,包括setup()onBeforeMount()onMounted()onBeforeUpdate()onUpdated()onBeforeUnmount()onUnmounted()onErrorCaptured()onRenderTracked()

onRenderTriggered()

4.1 setup()

setup()函数是Composition API的入口点,用于在组件创建之前执行一些初始化操作。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} return {
count,
increment
};
}
};
</script>

4.2 onBeforeMount()

onBeforeMount()函数在组件挂载之前执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onBeforeMount(() => {
console.log('before mount');
}); return {
count,
increment
};
}
};
</script>

4.3 onMounted()

onMounted()函数在组件挂载之后执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onMounted(() => {
console.log('mounted');
}); return {
count,
increment
};
}
};
</script>

4.4 onBeforeUpdate()

onBeforeUpdate()函数在组件更新之前执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onBeforeUpdate(() => {
console.log('before update');
}); return {
count,
increment
};
}
};
</script>

4.5 onUpdated()

onUpdated()函数在组件更新之后执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onUpdated(() => {
console.log('updated');
}); return {
count,
increment
};
}
};
</script>

4.6 onBeforeUnmount()

onBeforeUnmount()函数在组件卸载之前执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onBeforeUnmount(() => {
console.log('before unmount');
}); return {
count,
increment
};
}
};
</script>

4.7 onUnmounted()

onUnmounted()函数在组件卸载之后执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onUnmounted(() => {
console.log('unmounted');
}); return {
count,
increment
};
}
};
</script>

4.8 onErrorCaptured()

onErrorCaptured()函数在组件捕获到错误时执行。

<template>
<div>
<p>count: {{ count }}</p>
<button @click="increment">+1</button>
</div>
</template> <script>
import { ref } from 'vue'; export default {
setup() {
const count = ref(0); function increment() {
count.value++;
} onErrorCaptured((error, instance, info) => {
console.error(error);
return false;
}); return {
count,
increment
};
}
};
</script>

4.9 onRenderTracked 和 onRenderTriggered

onRenderTrackedonRenderTriggered是两个生命周期钩子,它们与Vue的响应式系统和编译器有关。这两个钩子是在Vue

3.x版本中引入的,主要用于调试目的,帮助开发者了解组件渲染过程中的跟踪和触发情况。

  1. onRenderTracked钩子:

    • 当组件的响应式依赖项被追踪时,即响应式系统开始跟踪一个依赖项时,这个钩子会被调用。
    • 它主要用于调试,可以帮助开发者了解何时响应式系统开始关注某个依赖项。
    • onRenderTracked钩子接收两个参数:depcontextdep是依赖项对象,context是当前组件的上下文对象。
  2. onRenderTriggered钩子:

    • 当组件的响应式依赖项被触发时,即响应式系统因为某个依赖项的变化而触发了重新渲染时,这个钩子会被调用。
    • 它主要用于调试,可以帮助开发者了解何时响应式系统因为某个依赖项的变化而重新渲染组件。
    • onRenderTriggered钩子也接收两个参数:depcontext,含义与onRenderTracked相同。

示例代码:

export default {
setup() {
// 定义一个响应式数据
const count = ref(0); // 监听 count 的变化
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${oldValue} to ${newValue}`);
}); // 使用 onRenderTracked 和 onRenderTriggered 进行调试
onRenderTracked((dep, context) => {
console.log(`onRenderTracked: ${dep}`);
}); onRenderTriggered((dep, context) => {
console.log(`onRenderTriggered: ${dep}`);
}); return {
count
};
}
};

在这个示例中,我们定义了一个响应式数据count,并使用了watch来监听它的变化。同时,我们使用了onRenderTracked

onRenderTriggered来打印调试信息。当响应式系统开始跟踪或触发重新渲染时,我们会得到相应的提示。这些钩子可以帮助开发者更好地理解Vue组件的渲染过程和响应式系统的运作。

Vue3使用Composition API实现响应式的更多相关文章

  1. vue3.0 composition API

    一.Setup函数 1.创建时间:组件创建之前被调用,优先与created被调用,this指向的实例为window,created所指向的实例为proxy 2.this指向:不会指向组件实例 3.参数 ...

  2. 好久没发文了,一篇Vue3的Composition API使用奉上

    Composition API Composition API是Vue3中推荐的组件代码书写方式,相较于传统的Options API来说,它能让业务逻辑处理和后期代码维护变的更加简单. 首先我们来看O ...

  3. 学习 vue3 第一天 vue3简介,创建vue3项目 Composition Api 初识

    前言: 从今天开始来和大家一起学习 vue3 相信大家都不陌生,已经火了一段时间了,但是还是有不少人没有学习,那就跟着六扇老师来简单的入个门 废话不多说,来开始今天的学习 Vue3 简介: 2020年 ...

  4. vue3 学习笔记 (五)——vue3 的 setup 如何实现响应式功能?

    setup 是用来写组合式 api ,内部的数据和方法需要通过 return 之后,模板才能使用.在之前 vue2 中,data 返回的数据,可以直接进行双向绑定使用,如果我们把 setup 中数据类 ...

  5. 基于 Vue3.0 Composition Api 快速构建实战项目

    Quick Start 项目源码:https://github.com/Wscats/vue-cli 本项目综合运用了 Vue3.0 的新特性,适合新手学习

  6. Vue3中的响应式api

    一.setup文件的认识 特点1:script 中间的内容就是一个对象 特点2:script 在第一层 定义的方法 或者 变量 => 就是这个对象 属性  => 顶层的绑定回被暴露给模板( ...

  7. Vue3的新特性及相关的Composition API使用

    首先 创建项目 Vue3 Vue3 相较于Vue2 的6大亮点: 1 性能快. 2 按需编译 体积更小 3 提供了组合API 类似于react 的React Hooks 4 更好的Ts支持 5 暴露了 ...

  8. mixin和composition api

    1. 这两个都是实现组件逻辑复用的法宝 2. composition api是vue3的,  composition api的出现就是解决mixins的不足之处的 一. mixin 回顾下mixin, ...

  9. iOS响应式编程:ReactiveCocoa vs RxSwift 选谁好

    转载: iOS响应式编程:ReactiveCocoa vs RxSwift 选谁好 内容来自stack overflow的一个回答:ReactiveCocoa vs RxSwift – pros an ...

  10. 【Vue源码学习】响应式原理探秘

    最近准备开启Vue的源码学习,并且每一个Vue的重要知识点都会记录下来.我们知道Vue的核心理念是数据驱动视图,所有操作都只需要在数据层做处理,不必关心视图层的操作.这里先来学习Vue的响应式原理,V ...

随机推荐

  1. Web 在线制表工具稳定吗?和桌面报表工具对比哪个好用?

    报表工具中最成熟常用的基本都是桌面设计器,但是 web 在线制表工具也占有部分市场,这是因为它也有一些优点: 1.报表设计和发布都在 web 端,无需额外安装桌面设计器 2.web 在线制表工具可直接 ...

  2. MVC过滤器简单刨析

    前言 简单介绍一下过滤器. 正文 看下过滤器类型: action: 在动作方法之前及之后执行 result: 在action结果被执行前或者之后执行,比如说返回一个视图,再执行视图前执行一个方法,再执 ...

  3. 【Windbg Preview】Failed to load data access DLL, 0x80004005

    最近使用Windbg的时候一直在用Preview版本,感觉解析一下就能直接加载起环境来太爽了.不过最近遇到一个dump加载不起来了. 但是最近一次加载却失败了,尝试了很久也不行 Failed to l ...

  4. 耗时又繁重的SQL诊断优化,以后就都交给数据库自治服务DAS吧!

    在我们业务系统中,数据库越来越扮演着举足轻重的角色. 和其它公司一样,在阿里巴巴业务场景下,大部分业务跟数据库有着非常紧密的关系,数据库一个微小的抖动都有可能对业务造成非常大的影响, 如何让数据库更稳 ...

  5. iOS App 启动优化

    ​简介: 作为程序猿来说,"性能优化"是我们都很熟悉的词,也是我们需要不断努⼒以及持续进⾏的事情:其实优化是⼀个很⼤的课题,因为细分来说的话有⼤⼤⼩⼩⼗⼏种优化⽅向 ,但是切忌在实 ...

  6. GRPC: 如何实现分布式日志跟踪?

    ​简介: 本文将介绍如何在 gRPC 分布式场景中,实现 API 的日志跟踪. 介绍 本文将介绍如何在 gRPC 分布式场景中,实现 API 的日志追踪. 什么是 API 日志追踪? 一个 API 请 ...

  7. [CosmWasm] 安装 Rust 和 wasm32 (Linux & Mac)

      先用 rustup 安装 Rust 语言,再确保你拥有wasm32目标. $ rustup default stable $ cargo version # If this is lower th ...

  8. C# - 能否让 SortedSet.RemoveWhere 内传入的委托异步执行

    TL;DR; 若想充分利用 RemoveWhere 带来的性能优势,建议传入判断是否删除元素的委托内采取同步操作.若一定要在该委托内使用异步操作,可以采用本文中绕行的方法,但摈弃了 RemoveWhe ...

  9. GitLab 升级迁移待办清单

    GitLab 大版本升级测试用例 项目 从模板项目 URL 导入,来创建新的项目 议题 通过 Quick Actions.关联新建.直接新建 模板 关联项 标签 工时 评论 看板 里程碑 分支 通过 ...

  10. go 操作 Excel

    文档地址: https://xuri.me/excelize/zh-hans/ package main import ( "fmt" "github.com/xuri/ ...