Vue3使用Composition API实现响应式

news2024/9/21 14:48:28

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 onRenderTrackedonRenderTriggered

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组件的渲染过程和响应式系统的运作。

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

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

相关文章

服装服饰商城小程序的作用是什么

要说服装商家&#xff0c;那数量是非常多&#xff0c;厂家/经销门店/小摊/无货源等&#xff0c;线上线下同行竞争激烈&#xff0c;虽然用户群体广涵盖每个人&#xff0c;但每个商家肯定都希望更多客户被自己转化&#xff0c;渠道运营方案营销环境等不可少。 以年轻人为主的消费…

30【Aseprite 作图】桌子——拆解

1 桌子只要画左上方&#xff0c;竖着5&#xff0c;斜着3个1&#xff0c;斜着两个2&#xff0c;斜着2个3&#xff0c;斜着一个5&#xff0c;斜着一个很长的 然后左右翻转 再上下翻转 在桌子腿部分&#xff0c;竖着三个直线&#xff0c;左右都是斜线&#xff1b;这是横着水平线不…

使用NuScenes数据集生成ROS Bag文件:深度学习与机器人操作的桥梁

在自动驾驶、机器人导航及环境感知的研究中&#xff0c;高质量的数据集是推动算法发展的关键。NuScenes数据集作为一项开源的多模态自动驾驶数据集&#xff0c;提供了丰富的雷达、激光雷达&#xff08;LiDAR&#xff09;、摄像头等多种传感器数据&#xff0c;是进行多传感器融合…

检索字符串

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 在Python中&#xff0c;字符串对象提供了很多应用于字符串查找的方法&#xff0c;这里主要介绍以下几种方法。 &#xff08;1&#xff09;count()方…

Visual Studio 的调试

目录 引言 一、调试的基本功能 设置断点 启动调试 检查变量 逐步执行代码 调用堆栈 使用即时窗口 二、调试技巧 条件断点 日志断点 数据断点 异常调试 三、调试高级功能 远程调试 多线程调试 内存调试 性能调试 诊断工具 四、调试策略与最佳实践 系统化的…

Docker-一文详解容器通信的基础网络模式及衍生的自定义网络模式

启动容器时&#xff0c;通过-p 宿主机端口:容器端口&#xff0c;就可以通过访问宿主机端口访问到容器&#xff0c;这种原理机制是啥&#xff0c;有没有其它方式可以让宿主机和容器通信&#xff0c;以及容器与容器之间如何通信。带着这几个问题开始学习Docker的网络知识。 文章…

浅谈路由器转发数据包

当路由器转发数据包时&#xff0c;它会经历一系列步骤&#xff0c;包括接收数据包、路由表查询、以及转发数据包。以下是详细的步骤描述&#xff1a; 1. 接收数据包 以太网帧到达端口&#xff1a;当一个以太网帧到达路由器的某个网络接口&#xff08;端口&#xff09;时&#…

STL库--stack

目录 stack的定义 stack容器内元素的访问 stack常用函数实例解析 stack的常见用途 stack的定义 其定义的写法和其他STL容器相同&#xff0c;typename可以任意基本类型或容器&#xff1a; stack<typename> name; stack容器内元素的访问 由于栈本身就是一种后进先出…

成都欣丰洪泰文化传媒有限公司助力品牌快速崛起

在当今数字化浪潮汹涌的时代&#xff0c;电商行业作为新经济的代表&#xff0c;正以其独特的魅力和无限的潜力&#xff0c;引领着商业模式的创新与变革。在这个充满机遇与挑战的领域里&#xff0c;成都欣丰洪泰文化传媒有限公司凭借其专业的电商服务能力和前瞻性的战略眼光&…

【Python】解决Python报错:TypeError: ‘int‘ object is not iterable

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

[测试开发]如何让IDEA实时显示内存

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

GoFly框架快速新增接口/上手写代码

拿到一个新框架大家可能无从下手&#xff0c;因为你对框架设计思路、结构不了解&#xff0c;从而产生恐惧&#xff0c;所以我们框架是通过简单可视化界面安装&#xff0c;安装后即可看到效果&#xff0c;然后点击先点点看各个功能&#xff0c;看现有的功能是怎么写的&#xff0…

[双指针] --- 快乐数 盛最多水的容器

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; 算法Journey 本篇博客我们分享一下双指针算法中的快慢指针以及对撞双指针&#xff0c;下面我们开始今天的学习吧~ &#x1f3e0; 快乐数 &#x1f4d2; 题…

如何让你的网站能通过域名访问

背景 当我们租一台云服务器&#xff0c;并在上面运行了一个Web服务&#xff0c;我们可以使用云服务器的公网IP地址进行访问&#xff0c;如下&#xff1a; 本文主要记录如何 实现让自己的网站可以通过域名访问。 买域名 可以登录腾讯云等主流公有云平台的&#xff0c;购买域名…

【保姆级介绍下Foxmail 邮箱】

&#x1f308;个人主页: 程序员不想敲代码啊 &#x1f3c6;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f44d;点赞⭐评论⭐收藏 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共…

精选10款手机必备精品APP,每一款都不容错过!

AI视频生成&#xff1a;小说文案智能分镜智能识别角色和场景批量Ai绘图自动配音添加音乐一键合成视频https://aitools.jurilu.com/ ​1.二维码而设计的应用程序——二维码设计 二维码设计 App 是一款专为用户创建和定制二维码而设计的应用程序。该应用适用于iOS和Android平台…

QT截图程序,可多屏幕截图二,增加调整截图区域功能

上一篇QT截图程序&#xff0c;可多屏幕截图只是实现了最基本的截图功能&#xff0c;虽然能用但是缺点也有&#xff0c;没办法更改选中的区域&#xff0c;这在实际使用时不太方便。这篇增加了这个功能。先看看效果。 实现代码为&#xff1a; 头文件 #ifndef MASKWIDGET_H #de…

IEEE Latex模版踩雷避坑指南

参考文献 原Latex模版 \begin{thebibliography}{1} \bibliographystyle{IEEEtran}\bibitem{ref1} {\it{Mathematics Into Type}}. American Mathematical Society. [Online]. Available: https://www.ams.org/arc/styleguide/mit-2.pdf\bibitem{ref2} T. W. Chaundy, P. R. Ba…

价值飙升30%,AI PC拉动半导体出货潮

由于处理器和DRAM的升级&#xff0c;大摩预测每台AI PC的半导体价值将增长20%-30%&#xff0c;PC平均售价也将提高7%。 台北国际电脑展即将于6月2日隆重开幕。 随着展会的临近&#xff0c;各种现象级的AI PC也蓄势待发。 就在上周&#xff0c;联想在业绩会上&#xff0c;首次…

2024 五月份国内外CTF 散装re 部分wp

cr3CTF warmup 附件拖入ida main函数无法反汇编&#xff0c;仔细看&#xff0c;有花指令&#xff0c;jnz实际上必定跳转。有非常多处&#xff0c;可以写脚本patch程序去掉花指令&#xff0c;只要匹配指令&#xff0c;再获取跳转地址&#xff0c;nop掉中间的代码就行。但…