当前位置: 首页 > news >正文

@vue/composition-api功能介绍

前言

@vue/composition-api 是通过一个插件的方式,为 Vue2(2.7自带,2.6及以下可用) 提供类似 Vue3 composition API 的函数式编程能力。它的实现思路主要有:

1、提供组合式函数,在函数内部追踪响应性依赖。

2、将组合产生的响应式状态保存到组件实例上,并在渲染期间还原。

3、重写组件的生命周期钩子,在钩子函数中恢复组合函数的上下文环境。

通过 setup() 函数作为入口,在其执行期间运行各响应式 API 追踪依赖,形成响应式状态,然后保存到实例上;在生命周期钩子中变更执行上下文,再次执行组合函数来恢复响应式状态,从而达到类似 Vue3 的编程体验。

为什么需要CompositionAPI

传统的Vue2 OptionAPI

我们以todolist为例,看一个基于vue2的OptionAPI的案例:

<template><div class="hello"><h1>{{ msg }}</h1><inputclass="add-todo"v-focustype="text"placeholder="add something"v-model="newTodo"@keyup.enter="addTodo"/><div v-for="todo in todoList" :key="todo.id" class="todo-row"><input type="checkbox" v-model="todo.completed" /><div v-if="!todo.editing" @dblclick="editTodo(todo)">{{ todo.title }}</div><inputv-elsetype="text"v-model="todo.title"@blue="doneEdit(todo)"@keyup.enter="doneEdit(todo)"@keyup.esc="cancelEdit(todo)"/></div></div>
</template><script lang="ts">
import Vue from "vue";
import {reactive,ref,computed,onMounted,ComputedRef,
} from "@vue/composition-api";type Todo = {id: number;completed: boolean;editing: boolean;title: string;
};
export default Vue.extend({name: "HelloWorld",props: {msg: String,},mounted() {console.warn(`component mounted..`);},data() {return {todoList: [{id: 1,title: "hello",completed: false,editing: false,},{id: 2,title: "world",completed: false,editing: false,},],newTodo: undefined as undefined | string,};},computed: {getLatestTodoId(): number {const lastTodo: Todo = this.todoList[this.todoList.length - 1];return lastTodo.id;},},methods: {addTodo() {if (this.newTodo === undefined) return;this.todoList.push({id: this.getLatestTodoId + 1,title: this.newTodo,completed: false,editing: false,});},editTodo(todo: Todo) {todo.editing = !todo.editing;},cancelEdit(todo: Todo) {const editingTodo: Todo | undefined = this.todoList.find((todo: Todo) => todo.editing === true);if (editingTodo === undefined) return;editingTodo.editing = false;},doneEdit(todo: Todo) {const editingTodo: Todo | undefined = this.todoList.find((todo: Todo) => todo.editing === true);if (editingTodo === undefined) return;editingTodo.title = todo.title;editingTodo.editing = false;},},directives: {focus: {inserted(el) {el.focus();},},},
});
</script>

改良的Vue2 setup CompositionAPI

改造成用@vue/composition-api的案例:

<template><div class="hello"><section style="margin-bottom:32px;"><h1 v-if="show">{{ msg }}</h1><button @click="toggle">Toggle above to hide</button></section><inputclass="add-todo"v-focustype="text"placeholder="add something"v-model="state.newTodo"@keyup.enter="addTodo"/><div v-for="todo in state.todoList" :key="todo.id" class="todo-row"><input type="checkbox" v-model="todo.completed" /><div v-if="!todo.editing" @dblclick="editTodo(todo)">{{ todo.title }}</div><inputv-elsetype="text"v-model="todo.title"@blur="doneEdit(todo)"@keyup.enter="doneEdit(todo)"@keyup.esc="cancelEdit(todo)"v-focus/></div></div>
</template><script lang="ts">
import Vue from "vue";import { totoListLogic } from "@/compositions/todoListLogic";
import { toggleLogic } from "@/compositions/toggleLogic";export default Vue.extend({name: "HelloWorld",props: {msg: String,},setup() {// todo business logicconst {state,getLatestTodoId,addTodo,editTodo,cancelEdit,doneEdit,} = totoListLogic();// toggle business logicconst { show, toggle } = toggleLogic();return {state,addTodo,editTodo,doneEdit,cancelEdit,show,toggle,};},directives: {focus: {inserted(el) {el.focus();},},},
});
</script>

以及对应的compositions函数:

toggleLogic.ts

import { ref } from "@vue/composition-api";export const toggleLogic = () => {const show = ref(true);const toggle = () => {show.value = !show.value;};return { show, toggle };
};

todoListLogic.ts

import { reactive, computed, ComputedRef } from "@vue/composition-api";type Todo = {id: number;completed: boolean;editing: boolean;title: string;
};
export const totoListLogic = () => {const state = reactive({todoList: [{id: 1,title: "hello",completed: false,editing: false,},{id: 2,title: "world",completed: false,editing: false,},],newTodo: undefined as undefined | string,});const getLatestTodoId: ComputedRef<number> = computed((): number => {const lastTodo: Todo = state.todoList[state.todoList.length - 1];return lastTodo.id;});function addTodo() {if (state.newTodo === undefined) return;state.todoList.push({id: getLatestTodoId.value + 1,title: state.newTodo,completed: false,editing: false,});}function editTodo(todo: Todo) {todo.editing = !todo.editing;}function cancelEdit(todo: Todo) {todo.editing = false;}function doneEdit(todo: Todo) {const editingTodo: Todo | undefined = state.todoList.find((todo: Todo) => todo.editing === true);if (editingTodo === undefined) return;editingTodo.title = todo.title;editingTodo.editing = false;}return { state, getLatestTodoId, addTodo, editTodo, cancelEdit, doneEdit };
};

优势对比

Composition API 相比于 Options API 的优势主要有:

1. 更好的逻辑复用性- 通过组合函数抽取逻辑,更方便的在组件内外复用
- 更好地代码分割,按功能拆分成更小的逻辑块2. 更好的代码组织- 将同一功能的代码收敛在一个函数中,提高内聚性
- 减少组件中的选项混杂,提高可读性3. 更好的类型推导- 组合式函数可以利用 Typescript 进行更精确的类型定义
- 提高代码可读性和可维护性4. 更优雅的处理逻辑抽取- 将复杂逻辑抽取为可重用的函数,组件只关注业务级代码
- 避免复杂的 mixins 和 HOC 嵌套5. 更灵活的逻辑复用粒度- 可以将任意粒度的逻辑封装为组合函数进行复用
- 更灵活的逻辑 boundaries6. 更直观的响应式编程- 通过组合式函数内的响应式变量,更直观地表达响应性
- 避免模版和业务逻辑交织在一起7. 更优雅的增量采用- 可以与现有的 Options API 共存
- 逐步使用 Composition API 改造旧组件

总体来说,Composition API 对于大型复杂应用的维护和扩展有很大优势,能够设计出更清晰、灵活的代码结构。

怎么用@vue/composition-api

安装

vue2.7以上自带,不需要安装;vue2.7以下手动安装npm install @vue/composition-api,并安装插件:

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'Vue.use(VueCompositionAPI)

后续文章会介绍其原理。

API介绍

下面介绍几个常见的API,后续文章会一一介绍其原理:

ref

ref函数可以把一个普通的值转成响应式的数据。它返回一个可变的ref对象,对象上挂载了一个.value属性,我们可以通过这个.value属性读取或者修改ref的值。

示例如下:

import { ref } from '@vue/composition-api'const count = ref(0)console.log(count.value) // 0count.value++ 
console.log(count.value) // 1

ref很像是一个容器,它把基本类型的数据像Number、String等"装箱",让其成为响应式的数据源。

reactive

reactive用来把一个对象转换成响应式的数据。它返回的是一个代理对象,原对象中的所有属性访问和变更,都会转化成响应式的。

示例如下:

import { reactive } from '@vue/composition-api'const obj = reactive({ count: 0 })obj.count++ // 响应式更新

reactive更适合组件的所有状态都定义在一个对象中的场景,它可以一次性把整个对象状态都转成响应式。

computed

computed函数用来创建一个计算属性,它根据依赖进行缓存和懒执行。

示例如下:

import { computed } from '@vue/composition-api'const count = ref(1)const doubled = computed(() => count.value * 2)console.log(doubled.value) // 懒执行得到 2count.value++ // 修改依赖console.log(doubled.value) // 缓存得到 4

computed避免了重复执行函数,也自动追踪了依赖关系。

watch

watch函数用于侦听特定的数据源,并在回调函数中执行副作用。

示例如下:

import { ref, watch } from '@vue/composition-api'const count = ref(0)watch(count, (newCount, oldCount) => {console.log(`count变化:${oldCount} -> ${newCount}`) 
})count.value++ // 触发watcher

它就像一个监听器,可以看到count的变化并作出反应。

toRefs

toRefs 可以把一个 reactive 对象的属性都转成 ref 形式。

示例如下:

import { reactive, toRefs } from '@vue/composition-api'const state = reactive({count: 0
})const { count } = toRefs(state)console.log(count.value) // 0count.value++ // 修改 ref 形式的值

这样可以方便地解构一个 reactive 对象,同时保持响应式特性。需要注意的是reactive对象,默认给template是不可用的,只有转为ref才行。

setup

setup 是组合式 API 的入口,所有的组合函数都在此执行。

示例如下:

import { ref, reactive } from '@vue/composition-api'export default {setup() {const count = ref(0)const obj = reactive({ foo: 'bar' })// ... 进行逻辑处理return {count,obj}}  
}

生命周期

组合式API提供了一系列与组件生命周期对应的钩子函数,用来注册生命周期钩子。

示例如下:

import { onMounted } from '@vue/composition-api'export default {setup() {onMounted(() => {console.log('组件挂载了!')})}
}

有如下钩子函数:

onBeforeMount - created()
onMounted - mounted()
onBeforeUpdate - beforeUpdate()
onUpdated - updated()
onBeforeUnmount - beforeDestroy()
onUnmounted - destroyed()

相关文章:

@vue/composition-api功能介绍

前言 vue/composition-api 是通过一个插件的方式,为 Vue2&#xff08;2.7自带&#xff0c;2.6及以下可用&#xff09; 提供类似 Vue3 composition API 的函数式编程能力。它的实现思路主要有: 1、提供组合式函数,在函数内部追踪响应性依赖。 2、将组合产生的响应式状态保存到…...

WebSocket整合直播

由于浏览器不支持对于rtmp协议推拉流&#xff0c;所以需要后台对传输的数据进行处理&#xff0c;将数据转接&#xff0c;为了实现其实时性&#xff0c;使用websocket将数据传输 先使用obs和vlc测试正常的推拉流是否正常 然后在跑本地后台传输视频 使用JavaCV技术传输音视频 …...

【Linux】IO 篇:文件调用原理,文件描述符,FILE的内涵,解析重定向,理解缓冲区

文章目录 一、系统调用接口二、文件调用1. 文件描述符 fd2. 文件调用原理3. FILE 三、重定向dup2 四、缓冲区简易 FILE 的代码实现 文件被加载之前&#xff0c;被存在磁盘上&#xff0c;操作文件&#xff0c;文件的部分内容则会被调度到 内存中。 要分析文件&#xff0c;我们也…...

力扣:47. 全排列 II(Python3)

题目&#xff1a; 给定一个可包含重复数字的序列 nums &#xff0c;按任意顺序 返回所有不重复的全排列。 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;力扣 示例&#xff1a; 示例 1&#xff1a; 输入&#xff1a;nums [1,1,2] 输出&#xff1a;[…...

Android uart-修改串口节点名

需求: 应客户软件的需求,需要将Android系统里面的/dev/ttyS3节点名称修改为/dev/ttyS9; 实现: 1、判断 driver->name是否为"ttyS",index是否为3,如果是的话替换为ttyS9; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c old mode 100644 new …...

【HarmonyOS】键盘遮挡输入框时,实现输入框显示在键盘上方

【关键字】 harmonyOS、键盘遮挡input&#xff0c;键盘高度监听 【写在前面】 在使用API6、API7开发HarmonyOS应用时&#xff0c;常出现页面中需要输入input&#xff0c;但是若input位置在页面下方&#xff0c;在input获取焦点的时候&#xff0c;会出现软键盘挡住input情况&a…...

day19-二叉树的最大最小深度

二叉树的最大/最小深度 给定一个二叉树 root &#xff0c;返回其最大/小深度。 二叉树的 最大/小深度 是指从根节点到最远/近叶子节点的最长路径上的节点数。 思路 求最大深度比较简单&#xff0c;我们先解决最大深度。 最大深度 递归 class Solution { public:int maxD…...

Ansible-roles

Ansible-roles 一、roles作用 把playbook剧本里的各个play看作为角色&#xff0c;将各个角色的tasks任务、vars变量、templates模板、files文件等内容放置到角色的目录中统一管理&#xff0c;需要的时候可在playbook中直接使用roles调用&#xff0c;所以roles可以实现playboo…...

NullPointerException导致手机重启案例分析

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、 Framework 层对象 空指针导致手机重启。二、解决方案&#xff0c;规避空指针三、Telecom APK 控制导致的重启举例 一、 Framework 层对象 空指针导…...

JAVA 反编译工具

Releases deathmarine/Luyten GitHub 安装exe 打开拖入文件即可...

(AcWing)分组背包问题

有 N 组物品和一个容量是 V 的背包。 每组物品有若干个&#xff0c;同一组内的物品最多只能选一个。 每件物品的体积是 vij&#xff0c;价值是 wij&#xff0c;其中 i 是组号&#xff0c;j 是组内编号。 求解将哪些物品装入背包&#xff0c;可使物品总体积不超过背包容量&…...

JSP项目国际化词条统计

国际化字条匹配并导出为excel格式 需求 将jsp页面里的key值&#xff0c;就是<spring:message code"gsyezer_Single_crystal"/>里的gsyezer_Single_crystal。和对应的字条对应上&#xff0c;并以excel表格形式输出。 jsp页面key值示例 <label for"&…...

Java课题笔记~ MyBatis缓存

为了减少重复查询给数据库带来的压力&#xff0c;MyBatis提供了缓存机制&#xff0c;这种机制能够缓存查询的结果&#xff0c;避免重复的查询。 MyBatis提供了两种缓存方式&#xff1a; 一种为针对于SqlSession的缓存【默认开启】 另一种为针对于全局的缓存【手动开启】 一…...

数据结构--循环队列、链队

基础知识 //循环队列数据结构 typedef struct { QElemType data[MaxQSize];//数据域 int front,rear; //队头队尾指针 }SqQueue; //链队结点数据结构 typedef struct QNode { int data;//数据域 struct QNode* next;//指针域 }QNode, * QueuePtr; typedef struct { struct Q…...

hbuilderx主题色分享-github风格

效果 步骤 hbuilderx总共有三种主题&#xff0c;绿柔主题Default,酷黑主题Monokai,雅黑主题Atom One Dark,修改主题色是基于三种主题之一的&#xff0c;不能直接创建一个新主题&#xff0c;比如下方配置是基于Atom One Dark(对象名为[Atom One Dark])&#xff0c;则当前hbuild…...

【C++】类与对象(1)

文章目录 前言一、什么是类1.类的定义2.类的访问限定符3.类的作用域 二、类的实例化三、类对象的存储方式四、this指针总结 前言 C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。C是基于面向对象的&#x…...

Java课题笔记~ MyBatis核心配置

一、核心配置文件概览 MyBatis配置文件中有MyBatis框架的核心配置&#xff0c;负责对MyBatis进行全局管理。它包含许多控制MyBatis功能的重要元素。 <configuration><!--设置配置文件--><properties><property name"" value""/>…...

从0开始自学网络安全(黑客)

前言 黑客技能是一项非常复杂和专业的技能&#xff0c;需要广泛的计算机知识和网络安全知识。你可以参考下面一些学习步骤&#xff0c;系统自学网络安全。 在学习之前&#xff0c;要给自己定一个目标或者思考一下要达到一个什么样的水平&#xff0c;是学完找工作&#xff08;…...

kotlin 编写一个简单的天气预报app(四)增加界面显示

编写界面来显示返回的数据 用户友好性&#xff1a;通过界面设计和用户体验优化&#xff0c;可以使天气信息更易读、易理解和易操作。有效的界面设计可以提高用户满意度并提供更好的交互体验。 增加城市名字的TextView <TextViewandroid:id"id/textViewCityName"…...

英语不好能学好Python吗?Python常用英文单词汇总

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 有些小可爱对英语好不好对学习python有没有什么影响有着很深的疑惑。 其实python学习&#xff0c;主要靠多敲多练&#xff0c;主打一个熟能生巧 那今天我就给大家带来Python常用英文单词汇总&#xff0c; 新手期小可…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

如何理解 IP 数据报中的 TTL?

目录 前言理解 前言 面试灵魂一问&#xff1a;说说对 IP 数据报中 TTL 的理解&#xff1f;我们都知道&#xff0c;IP 数据报由首部和数据两部分组成&#xff0c;首部又分为两部分&#xff1a;固定部分和可变部分&#xff0c;共占 20 字节&#xff0c;而即将讨论的 TTL 就位于首…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...