Vue3 之 computed 计算属性的使用与源码分析详细注释
计算属性的基本用法
computed 一般有两种常见的用法:
一:传入一个对象,内部有 set 和 get 方法,属于ComputedOptions形式。在内部会有getter / setter两个变量来进行保存.
const age = ref(18);
const myAge = computed({
get() {},
set() {},
});
二:传入一个 function,在内部会有getter来进行保存.
const age = ref(18);
const myAge = computed(() => {
return age.value + 10;
});
计算属性的源码
计算属性的源码大部分是依赖 effect 的实现。基于上一篇文章对 effect 源码的理解,effect 可以传递一个函数和一个对象 options。
而计算属性的本质就是一个 effect,在之前 effect 的源码中预先声明了 lazy和scheduler 属性,就是用于计算属性,因为计算属性默认不会被执行,
lazy 表示 effect 不会立即被执行,scheduler 会在 trigger 中判断是否传入了 scheduler,传入就执行 scheduler 方法。
scheduler 中,判断当前的_dirty 是否为 false,会把_dirty 置为 true,且执行 trigger 触发响应。
computed 也是基于类实现 ComputedRefImpl
其中 share.ts、effect.ts 文件中的方法,不在赘述,详见上一篇 响应式原理的文章
// computed.ts
import { isFunction, TrackOpTypes, TriggerOrTypes } from "./shared";
import { effect, track, trigger } from "./effect";
class ComputedRefImpl {
public _dirty = true; // 默认取值时不要用缓存
public _value;
public effect;
constructor(getter, public setter) {
this.effect = effect(getter, {
// 1. 计算属性本身就是一个effect
lazy: true, // 2. 默认不执行
scheduler: () => {
if (!this._dirty) {
this._dirty = true;
trigger(this, TriggerOrTypes.SET, "value");
}
},
});
}
get value() {
// 3.计算属性也要收集依赖,vue2中计算属性不具备收集依赖的,
if (this._dirty) {
this._value = this.effect(); // 4. 会将用户的返回值返回 也就是computed中 return
this._dirty = false; // 5. 设置缓存
}
track(this, TrackOpTypes.GET, "value"); // 6. 依赖收集: 因为可能会在effect中使用计算属性
/**
* const age = ref(18)
const myAge = computed(() => { // 此方法默认不会被执行
return age.value + 10;
})
// 当访问属性的时候执行
console.log(myAge.value)
console.log(myAge.value) // 多次取值,只取第一次执行结果走缓存
age.value = 100; // 更新age,myAge不会立刻重新计算
console.log(myAge.value) // 取值时才会重新计算
effect(() => { // 此effect中没有age 但是用到了计算属性,因此也需要依赖收集
console.log(myAge.value)
})
age.value = 500 // 收集依赖后,属性值更新,需要在scheduler中触发trigger执行,
*/
return this._value; // 7. 多次取值,只取第一次执行结果走缓存
}
set value(newValue) {
this.setter(newValue);
}
}
// 1. 如果getterOrOptions是函数,会直接赋值给getter。并在用户进行复制操作时 给出只读提示
// 2. 否则getterOrOptions为对象,会将set和get分别赋值给setter,getter。
export function computed(getterOrOptions) {
let getter;
let setter;
// 1. 如果getterOrOptions是函数,会直接赋值给getter。并在用户进行复制操作时 给出只读提示
if (isFunction(getterOrOptions)) {
getter = getterOrOptions;
setter = () => {
console.warn("computed value must be readonly");
};
} else {
// 2. 否则getterOrOptions为对象,会将set和get分别赋值给setter,getter。
getter = getterOrOptions.get;
setter = getterOrOptions.set;
}
return new ComputedRefImpl(getter, setter); // 3. 创建一个计算属性实例
}
shared 工具方法抽离
// share.ts
export const isFunction = (value) => typeof value == "function";
Vue3 之 computed 计算属性的使用与源码分析详细注释的更多相关文章
- vue computed计算属性和watch监听属性解疑答惑
computed计算属性 计算属性类似于方法,用于输出data中定义的属性数据的结果,data数据变化时,计算属性的结果会同步变化,需要注意的是计算属性不可与data定义的属性同名. 相比于方 ...
- Vue之computed计算属性
demo.html <!DOCTYPE html> <html lang="en" xmlns:v-bind="http://www.w3.org/19 ...
- 深入理解 Vue Computed 计算属性
Computed 计算属性是 Vue 中常用的一个功能,我们今天来说一下他的执行过长 拿官网简单的例子来看一下: <div id="example"> <p> ...
- Vue(七):computed计算属性
简介 计算属性关键词: computed. 计算属性在处理一些复杂逻辑时是很有用的. 实例1 可以看下以下反转字符串的例子: <div id="app"> {{ mes ...
- Vue的computed计算属性是如何实现的
一个开始 有如下代码,full是一个计算属性,开始,他的值是'hello world',1s后,msg变成了‘I like’, full的值同步变成了'I like world';其原理解析来看一下. ...
- 043——VUE中组件之使用.sync修饰符与computed计算属性实现购物车原理
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- computed 计算属性
wepyjs - 小程序组件化开发框架 https://tencent.github.io/wepy/document.html#/?id=wepy%e9%a1%b9%e7%9b%ae%e7%9a%8 ...
- vue computed计算属性 watch监听
计算属性 computed:{ 变量:function(){ return 计算好的值 } } 这时候计算好的值 就付给了你的变量 在实例中可以this.使用 注意 声明的变量的data中不可以重复声 ...
- Vue.js 源码分析(六) 基础篇 计算属性 computed 属性详解
模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的.在模板中放入太多的逻辑会让模板过重且难以维护,比如: <div id="example">{{ messag ...
- vue-methods方法与computed计算属性的差别
好吧,我就是单纯的举个例子:实现显示变量 message 的翻转字符串 第一种:methods:我们可以通过在表达式中调用方法来达到同样的效果: 第二种:computed:计算属性 上面的2中方法都实 ...
随机推荐
- NOIP模拟64
T1 三元组 解题思路 一看题面,好像是一道数学题,但不完全是,或者说根本不是... 比较好想到的是 \(\mathcal{O}(n^2)\) 和 \(\mathcal{O}(nk)\) 的做法,然后 ...
- ajax兼容处理
// ajax的兼容处理 // 1.创建ajax对象 // 标准浏览器 // const xhr = new XMLHttpRequest(); ...
- 一文了解 - -> SpringMVC
一.SpringMVC概述 Spring MVC 是由Spring官方提供的基于MVC设计理念的web框架. SpringMVC是基于Servlet封装的用于实现MVC控制的框架,实现前端和服务端的交 ...
- INFINI Gateway 如何防止大跨度查询
背景 业务每天生成一个日期后缀的索引,写入当日数据. 业务查询有时会查询好多天的数据,导致负载告警. 现在想对查询进行限制--只允许查询一天的数据(不限定是哪天),如果想查询多天的数据就走申请. 技术 ...
- 第二届算法、图像处理与机器视觉国际学术会议(AIPMV2024)
第二届算法.图像处理与机器视觉国际学术会议(AIPMV2024) 2024 2nd International Conference on Algorithm, Image Processing an ...
- vue3 父子组件间的传值通信
1.父转子 // 父组件 <template> <div> <div> <p>{{ count }}</p> <Son :countF ...
- Python中的属性
Python中的属性主要分为类属性,对象属性. 1.类属性 类属性:类所有,所有的实例对象都能够共享,类定义时就直接指定的属性,能通过类名和实力对象名访问,当当前的类属性被实例对象通过对象名.属性名的 ...
- 交通规划四阶段法:基于 Python 的交通分布预测算法复现 - 附完整代码链接
目录 交通规划四阶段法:基于 Python 的交通分布预测算法复现 - 附完整代码链接 我只是想使用这些代码 下载代码文件 代码的使用方法 合作 部分代码内容的展示 交通规划四阶段法:基于 Pytho ...
- python sweetviz_数据分析及解决报告图表中文乱码
python sweetviz_数据分析 python 做数据分析,传入数据进去,就可以使用python现有的插件,进行数据分析,生成数据分析的报表,可以将复杂的数据,通过图表的形式,清晰将数据展示出 ...
- 面试官:告诉我为什么static和transient关键字修饰的变量不能被序列化?
一.写在开头 在上一篇学习序列化的文章中我们提出了这样的一个问题: "如果在我的对象中,有些变量并不想被序列化应该怎么办呢?" 当时给的回答是:不想被序列化的变量我们可以使用tra ...