Vue如何给计算属性computed传参的思考,看完就明白了!

一、缘起

事情的起因是这样的,有位朋友(无中生友)遇到了如下需求:

在这里插入图片描述

上面是一个商品列表,每个商品对应一个价格、优惠、数量,并且数量可以动态改变,最后动态计算出一个总价。当然,这只是一个简单地乘法计算,往往在实际项目开发中,遇到的需求要复杂的多,计算也更复杂。

大部分人第一时间想到是利用函数传参返回计算结果,显示在页面上。实现方式如下:

function getSumMoney(row) {return row.price * row.num * row.discount;
}

结果如下:
在这里插入图片描述

当改变数量时,总价也跟着变化,看似没有任何问题,达到了我们的预期结果。其实不然,我们看下面的gif演示就会发现问题。

在这里插入图片描述

观察上面的gif动图,细心地你已经发现问题了。观察浏览器的打印日志发现,每次改变一个商品的数量时,其它商品的数量虽然没有变化,但是也会在计算一次。还有,当浏览器视口宽度高度变化时,我们并没有改变商品的数量,同样的也会每次触发计算,这个方法会被不断反复的调用。

在这里插入图片描述

这是为什么呢?

这是因为当监听到表格的数据data变化时,会重新渲染列表;当浏览器视口宽度高度变化时,会引发重排,列表也会重新渲染。

当计算量大且复杂时,这种情况是相当耗性能的,并且体验也不好。我们期望的结果是哪一行变化时重新计算哪一行,数据不变的行不需要重新计算。

二、computed如何传参?

针对以上情况,大家第一时间可能想到是利用计算属性computed传入一个参数。计算属性computed是基于它们的响应式依赖进行缓存的,只在相关响应式依赖发生改变时它们才会重新求值。

那么问题来了,Vue中计算属性computed如何传参?

答:计算属性是不能直接传参的。在vue3中的组合式API中,computed是无法传入参数的。在vue2的选项式API中,computed可以通过闭包函数(也叫匿名函数)间接传参来实现。

代码如下:

<el-table-column prop="sum" label="总价"><template #default="scope">{{ computedPrice(scope.row) }}</template>
</el-table-column>
computed: {computedPrice() {return function(row) {console.log(row)return row.price * row.num * row.discount;}}
}

在这里插入图片描述

很明显以上方法也没有实现我们想要的结果!那么到底怎么才能实现我们的预期结果呢?

三、分析与实现

我们仔细分析一下,其实这个需求就是希望为每一个数据参数对应一个计算属性computed,当每一行数据不变时,就返回这个没有改变的计算属性。反之某一行数据变化了,那么它对应的计算属性也发生了变化。也就是说,一个参数对应一个计算属性,每一行数据里面都有一个计算属性方法。

例如:

const tableData = ref([{product: '华为 Mate 60Pro',price: 8000,num: 1,discount: 0.9,totalPrice: computed(() => {// do something})},{product: '华为 Pura 70Pro',price: 7000,num: 1,discount: 0.95,totalPrice: computed(() => {// do something})},{product: '华为 Mate X5',price: 11500,num: 1,discount: 0.88,totalPrice: computed(() => {// do something})}
])

在这里插入图片描述

如果要这么实现非常复杂笨拙,而且当列表有非常多数据时现实起来也不切实际。那么我们可以封装一个函数useComputed,把我们真正要计算的函数传入useComputed并返回一个新的函数computedPrice,只需要用computedPrice去进行总价的计算即可。

完整代码如下:

<template><div class="container"><el-table :data="tableData" border style="width: 100%"><el-table-column prop="product" label="产品" /><el-table-column prop="price" label="价格" /><el-table-column prop="discount" label="优惠" /><el-table-column prop="num" label="数量"><template #default="scope"><el-input-number v-model="scope.row.num" :min="1" :max="10" :key="scope.row.price" /></template></el-table-column><el-table-column prop="sum" label="总价"><template #default="scope">{{ computedPrice(scope.row) }}</template></el-table-column></el-table></div>
</template><script setup>import { ref, computed } from 'vue';const tableData = ref([{product: '华为 Mate 60Pro',price: 8000,num: 1,discount: 0.9,},{product: '华为 Pura 70Pro',price: 7000,num: 1,discount: 0.95,},{product: '华为 Mate X5',price: 11500,num: 1,discount: 0.88,},])function useComputed(fn) {const map = new Map();return function(...args) {const key = JSON.stringify(args);if(map.has(key)) {return map.get(key)}const result = computed(() => {return fn(...args)})map.set(key, result);return result;}}function totalPrice(row) {console.log(row)return row.price * row.num * row.discount;}const computedPrice = useComputed(totalPrice)
</script>

效果如下:

在这里插入图片描述

上图可以看到,哪一行数据变化了就重新计算哪一行,数据不变的行不进行计算,完美的达到了我们想要的结果。

下面就对重要代码进行分析:

function useComputed(fn) {// 创建Map缓存结果const map = new Map();// 返回一个函数return function(...args) {// args是一个数组,把参数转成字符串,当做Map的keyconst key = JSON.stringify(args);console.log(key); // [{"product":"华为 Mate 60Pro","price":8000,"num":1,"discount":0.9}]把这一长串当做key// 判断是否有对应的计算属性if(map.has(key)) {// 有就返回计算属性return map.get(key)}// 没有就创建一个计算属性const result = computed(() => {return fn(...args)})// 把创建的计算属性返回的结果result和参数关联map.set(key, result);return result;}
}

在这里插入图片描述

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

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

相关文章

Ubuntu修改命令提示符格式PS1

命令提示符组成 通过Xshell进入Ubuntu的默认提示符是这样的 rootDESKTOP:~# root: 当前登录用户DESKTOP&#xff1a;主机名~: 当前目录名&#xff08;即用户主目录&#xff09;#&#xff1a;超级用户权限(root用户显示)$: 普通用户权限(非root用户显示) 修改命令提示符 step1…

nginx实战演练

目录 一.Nginx架构和安装&#xff08;未完待续&#xff09; <1>.Nginx概述 <2>.Nginx架构和进程 <3>.Nginx模块 <4>.Nginx安装(编译安装) 二.Nginx基础配置 <1>.关闭debug <2>.将nginx软件添加到环境变量 <3>.开机自启动脚…

Qt/C++地图标注点的添加删除移动旋转/指定不同图标和动图/拿到单击信号

一、前言说明 标注点在地图开发中是最常见的应用场景之一&#xff0c;比如在地图上需要显示设备的位置&#xff0c;基本上都是添加标注点&#xff0c;指定图片和尺寸已经经纬度坐标位置。这个功能在每种地图内核中都提供的&#xff0c;这个并没有任何难点&#xff0c;在这个功…

CeresPCL 最小二乘插值(曲线拟合)

一、简介 在多项式插值时,当数据点个数较多时,插值会导致多项式曲线阶数过高,带来不稳定因素。因此我们可以通过固定幂基函数的最高次数 m(m < n),来对我们要拟合的曲线进行降阶。之前的函数形式就可以变为: 既然是最小二乘问题,那么就仍然可以使用Ceres来进行求解。 …

★ C++基础篇 ★ vector 类

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将继续和大家一起学习C基础篇第六章----vector类 ~ 目录 一 vector的介绍及使用 1.1 vector的介绍 1.2 vector的使用 1.2.1 vector的定义 1.2.2 vector iterator 的使用 1.2.3 vector 空间增长问题 1.2.4 vecto…

使用 Fyne 构建 GUI 应用:设置标签文本和自增计数器

引言 Fyne 是一个用 Go 语言编写的跨平台 GUI 框架&#xff0c;它提供了一套丰富的组件来帮助开发者快速构建出漂亮的用户界面。在本文中&#xff0c;我们将通过一个简单的案例来演示如何使用 Fyne 创建 GUI 应用程序&#xff0c;该程序包含设置标签文本和自增计数器的功能。 …

高可用集群keepalived从部署到实战一篇解决

目录 一.高可用集群 1.1 集群类型 1.2 系统可用性 1.3 系统故障 1.4 实现高可用 1.5.VRRP&#xff1a; 1.5.1 VRRP 相关术语 1.5.2 VRRP 相关技术 二.Keepalived 部署 2.1 keepalived 简介 2.2keepalived架构 2.3 Keepalived 环境准备 2.4 Keepalived 相关文件 2.…

Python编写Word文档

目录 0. 安装依赖 1. 创建word文档 2. 添加标题、居中、字体16大小 3. 添加标题一 4. 添加一段话并设置字体颜色 封装函数 5. 换页 6. 插入表格 0. 安装依赖 python-docx1.1.2 1. 创建word文档 from docx import Documentdoc Document() 2. 添加标题、居中、字体1…

智碳云/高能耗企业 水-电-气-热-油-空压机等能源数据采集系统【源码】

智碳云/高能耗企业 水-电-气-热-油-空压机等能源数据采集系统【源码】 介绍基于SpringCloud的能源管理系统-能源管理平台源码-能源在线监测平台-双碳平台源码-SpringCloud全家桶-能管管理系统源码-能管系统软件架构

【记git 重命名文件失败,和正确方法】

【背景】 想要重命名一个文件&#xff0c;并同步到远程 【过程】 1.我是直接把 “驱动增加he.c” 文件重命名为 “驱动增加播放he接口方法” &#xff0c;想着直接提交就会同步重命名git仓记录的文件名。然后就可以推送到远程仓库&#xff0c;同步重命名远程仓库的文件名。 2.然…

全球滑坡(降雨诱发的)数据(有时间属性)

滑坡一般指狭义概念的滑坡,是指构成斜坡的有滑动历史和滑动可能性的岩、土体边坡,在重力作用下伴随着其下部软弱面(带)上的剪切作用过程而产生整体性运动的现象。 滑坡的发育阶段滑坡的发生、发展过程是有阶段性的。根据大量的现场实际资料、观测成果、滑坡模型试验和相关的岩土…

ant design pro v6 如何做好角色管理

先上图&#xff1a; 整个角色管理是如何做的吗&#xff1f; 首先你要处理后端&#xff0c;要先把角色存到用户那。 这是用户管理部分的内容&#xff1a; 可以看到一个用户是有多个角色的。 看到没有&#xff0c;存的是数组 数组的是一个 role 对象 role 对象是这样&#xf…

【专题】2024年7月人工智能AI行业报告合集汇总PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p37350 随着人工智能技术的飞速发展&#xff0c;AI已经成为当今时代的重要驱动力。本报告将聚焦于人工智能AI行业的最新动态&#xff0c;涵盖客户服务、体验营销、资产管理以及国产AI大模型应用等多个领域。通过深入研究和分析&#xff0c;我们…

C++ 设计模式——抽象工厂模式

抽象工厂模式 抽象工厂模式 抽象工厂模式主要组成部分代码实现抽象工厂模式模式的 UML 图抽象工厂模式 UML 图解析优点和缺点适用场景 抽象工厂模式提供一个接口&#xff0c;用于创建一系列相关或相互依赖的对象&#xff0c;而无需指定它们的具体类。它通常用于需要创建多个产品…

2024年必读!《大模型应用开发极简入门》—— 一书掌握LLM大模型精髓

大家好&#xff0c;今天给大家推荐一本大模型应用开发入门书籍《大模型应用开发极简入门》&#xff0c;本书对很多AI概念做了讲解和说明&#xff01; 朋友们如果有需要 《大模型应用开发极简入门》&#xff0c;扫码获取~ 本书主要讲解了以下几个方面的大模型技术&#xff1a; …

[图解]片段16 ESS状态机图-SysMLEA建模住宅安全系统

1 00:00:00,220 --> 00:00:03,580 然后我们看初始这里 2 00:00:03,590 --> 00:00:09,500 有一个指向它的一个迁移的事件 3 00:00:09,710 --> 00:00:13,730 站点可用&#xff0c;这个实际上是错误的 4 00:00:14,020 --> 00:00:15,050 这不是事件 5 00:00:15,900…

NCSN公式推导(一)

通过估计数据分布的梯度进行生成建模 Paper Title&#xff1a;Generative Modeling by Estimating Gradients of the Data Distribution Paper是斯坦福大学发表在NIPS 2019的工作 Paper地址 Abstract 我们引入了一种新的生成模型&#xff0c;其中样本通过朗之万动力学生成&…

Power Query抓取多页数据导入到Excel

原文链接 举例网站&#xff1a;http://vip.stock.finance.sina.com.cn/q/go.php/vLHBData/kind/ggtj/index.phtml?last5&p1 操作步骤 &#xff08;版本为&#xff1a;Excel2010&#xff09;&#xff1a; Step-01&#xff1a;单击【Power Query】-【从Web】&#xff0c;…

日期类代码实现-C++

一、目标 通过前面对类和对象的介绍我们可以自己通过C代码初步实现一个简单的日期类。 实现的主要操作有&#xff1a; 1.日期类的构造函数 2.日期类的拷贝构造函数&#xff08;在头文件中实现&#xff09; 3.日期类的比较运算符重载 4.日期类的计算运算符重载 5.流插入运…

【Linux】 gdb-调试器初入门(简单版使用)

&#x1f525;系列文章&#xff1a;《Linux入门》 目录 一、背景 二、什么是GDB &#x1f337;定义 &#x1f337;GDB调试工具---提供的帮助 三、GDB的安装教程-Ubuntu &#x1f337;gdb的安装 四、哪类程序可被调试 &#x1f337;程序的发布方式 &#x1f337;Debug版…