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中方法都实 ...
随机推荐
- WPF绑定数据源到ListBox等selector的注意事项
如果使用CollectionViewSource绑定到控件上,会导致默认选择第一项,而使用List,SelectedItem就默认为空. 要避免默认选择第一项,就要设置 ListBox.IsSynch ...
- Spring 对 Junit4,Junit5 的支持上的运用
1. Spring 对 Junit4,Junit5 的支持上的运用 @ 目录 1. Spring 对 Junit4,Junit5 的支持上的运用 每博一文案 2. Spring对Junit4 的支持 ...
- containerd 源码分析:启动注册流程
0. 前言 containerd 是一个行业标准的容器运行时,其强调简单性.健壮性和可移植性.本文将从 containerd 的代码结构入手,查看 containerd 的启动注册流程. 1. 启动注 ...
- feign入门
.net core: feign.net是一个spring cloud feign组件的c#移植版 https://github.com/daixinkai/feign.net 在.net core ...
- C#笔记(1)窗体
1. 隐藏TabPage 在使用TabControl控件时,希望隐藏其中某个选项卡(即TabPage).设置该TabPage的父容器为null 即可,如TabPage.Parent = null .如 ...
- 生成树协议(STP)基本知识及实验(使用eNSP)
1.基本知识--摘至<网络之路--交换专题> (1)生成树的作用:在链路层消除环路上可能出现的广播风暴. (2)生成树的工作由三部分组成:选举过程.拓扑计算.端口行为确定. 选举过程:在二 ...
- BOM弹窗 滚动条
// window.alert('弹出内容') 警告框 // window.prompt('弹出内容') 输入框 // 以 字符串 形式 存储输入 ...
- nodejs模块总结 gulp小结
1,内置模块 fs const fs = require('fs') fs.read ...
- kettle从入门到精通 第十二课 kettle java代码过滤记录、利用Janino计算Java表达式
1.下图通过简单的示例讲解了根据java代码过滤记录和利用Janino计算Java表达式两个组件. 2.根据java代码过滤记录 1)步骤名称:自定义 2)接收匹配的行的步骤(可选):下面条件(jav ...
- SQL SERVER 同一台服务器,A库正常连接,B库提示“等待的操作过时”
SQL SERVER 同一台服务器,A库正常连接,B库提示"等待的操作过时" 解决方法: 在客户端(非SQL SERVER 服务器)用管理员身份运行CMD,输入netsh wins ...