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. 全局模型可解释之部分依赖图:Partial Dependence Plot

    本部分是来自大纲 模型可解释的一个子分支. 部分依赖图可以表示1个或者2个特征对模型的预测结果所能产生的边际效应.同时也能展示1个特征和label直接是否具有:线性相关性.单调性等. 当我们把pdp应 ...

  2. 第 1 章 Python 爬虫概念与 Web 基础

    第 1 章 Python 爬虫概念与 Web 基础 1.1 爬虫概念 1.1.1 什么是爬虫 爬虫,即网络爬虫,又称网络蜘蛛(Web Spider),是一种按照一定规则,用来自动浏览或抓取万维网数据的 ...

  3. 浏览器扩展开发-Firefox临时载入附加组件(图)

    科普:[FE] Quasar BEX 热加载区别: Chrome vs Firefox 1. 2.  3. Thats all. Refer:Firefox扩展开发 Link:https://www. ...

  4. [Blockchain] 开发完真实的 DApp 后才能得出的结论与看法

    1. 最近经常看到地方新闻有关 区块链在追踪溯源方面被实际应用,但是我本人认为这很大程度上可能是伪命题. 因为,是不是区块链.或者说有没有办法更改数据,这都很难说,本质上这个链还是由机构控制,所以对此 ...

  5. C# 获取指定文件夹中所有的文件(包括子文件夹的文件)

    有个需求中需要播放指定路径的声音,但你必须要有该路径的声音才可以播放,如果没有该文件则播放默认的声音,该方法用于初始化应用的时候获取指定目录的所有文件,便于后来播放声音的时判断路径是否存在. usin ...

  6. 使用open webui+ollama部署本地大模型

    使用open webui+ollama部署本地大模型 上次使用了angthingllm + ollama部署了本地大模型,详情见:https://www.cnblogs.com/jokingremar ...

  7. 使用qemu运行risc-v ubuntu

    参考 Ubuntu installation on a RISC-V virtual machine using a server install image and QEMU 用到的文件 fw_ju ...

  8. 【简说Python WEB】Flask应用的单元测试

    [简说Python WEB]Flask应用的单元测试 tests/test_basics.py import unittest from flask import current_app from a ...

  9. ITIL4之四维模型

    ITIL4的一个核心概念.它定义了四个维度(图中的1~4),这四个维度旨在确保组织能够在多方面考虑其服务提供,从而更有效地创造和交付价值. 四维模型的整合流程 确立价值载体:明确信息服务提供商的价值主 ...

  10. NVCC编译选项含义解析

    NVCC编译 nvcc 是cuda程序的编译器. 1. 编译阶段 用于指定编译阶段最基本的编译参数. -c: 同gcc,只预处理.编译和汇编为.o文件,不link -lib:生成一个库文件,windo ...