这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

从computed的特性出发

computed最耀眼的几个特性是啥?

1. 依赖追踪

import { reactive, computed } from 'vue'

const state = reactive({
a: 1,
b: 2,
c: 3,
})
const sum = computed(() => {
return state.a + state.b
})

我们定义了一个响应式数据state和一个计算属性sum, Vue会自动追踪sum依赖的数据state.astate.b,并建立相应的依赖关系。

也就是只有state.astate.b发生变化的时候,sum才会重新计算而state.c任由它怎么变,sum都将丝毫不受影响。

2. 缓存

还是上面的例子,如果state.astate.b打死都不再改变值了,那么我们读取sum的时候,它将会返回上一次计算的结果,而不是重新计算。

3. 懒计算

这个特性比较容易被忽略,简单地说只有计算属性真正被使用(读取)的时候才会进行计算,否则咱就仅仅是定义了一个变量而已。

import { reactive, computed } from 'vue'

const state = reactive({
a: 1,
b: 2,
c: 3
}) const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
}) setTimeout(() => {
// 没有读取sum.value之前,sum不会进行计算
console.log('1-sum', sum.value)
// 我们改变了a的值,但是sum并不会立刻进行计算
state.a = 4 setTimeout(() => {
// 而是要等到再次读取的时候才会触发重新计算
console.log('2-sum', sum.value)
}, 1000)
}, 1000)

挨个实现computed特性

1. 懒计算

我们依旧围绕effect函数来搞事情,到目前为止,effect注册的回调都是立刻执行。

const state = reactive({
a: 1,
b: 2,
c: 3
})
// 有没有很像计算属性的感觉
const sum = effect(() => {
console.log('执行计算') // 立刻被打印
const value = state.a + state.b
return value
}) console.log(sum) // undefined

想要实现computed的懒执行,咱们可以参考上篇文章Vue3:原来你是这样的“异步更新”的思路,添加一个额外的参数lazy

它要实现的功能是:如果传递了lazytrue,副作用函数将不会立即执行,而是将执行的时机交还给用户,由用户决定啥时候执行。

当然啦!回调的结果我们也应该一并返回(例如上面的value值)

你能想象,我们仅仅需要改造几行代码就能离computed近了一大步。

const effect = function (fn, options = {}) {
const effectFn = () => {
// ... 省略
// 新增res存储fn执行的结果
const res = fn()
// ... 省略
// 新增返回结果
return res
}
// ... 省略
// 新增,只有lazy不为true时才会立即执行
if (!options.lazy) {
effectFn()
}
// 新增,返回副作用函数让用户执行
return effectFn
}

测试一波

const state = reactive({
a: 1,
b: 2,
c: 3,
});
// 有没有很像计算属性的感觉
const sum = effect(() => {
console.log("执行计算"); // 调用sum函数后被打印
const value = state.a + state.b;
return value;
}, {
lazy: true
});
// 不执行sum函数,effect注册的回调将不会执行
console.log(sum()); // 3

2. 依赖追踪

咱们初步实现了懒执行的特性,为了更像computed一点,我们需要封装一个函数。

function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
}) const obj = {
get value () {
return effectFn()
}
} return obj
}

这就有点那么味道啦!

测试一波

可以看到computed只会依赖state.astate.b,而不会依赖state.c,这得益于我们前面几篇文章实现的响应式系统,所以到了计算属性这里,我们不用改动任何代码,天然就支持。

不过还是有点小问题,我们读取了两次sum.value,sum却被执行了两次,这和computed缓存的特性就不符了。

别急,马上就要实现了这个最重要的特性了。

const state = reactive({
a: 1,
b: 2,
c: 3
}) const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
}) console.log(sum.value)
console.log(sum.value)

3. 缓存

回顾一下computed的缓存特性:

  1. 只有当其依赖的东西发生变化了才需要重新计算
  2. 否则就返回上一次执行的结果。

为了缓存上一次计算的结果,咱们需要定义一个value变量,现在的关键是怎么才能知道其依赖的数据发生变化了呢?

function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
})
let value
let dirty = true const obj = {
get value () {
// 2. 只有数据发生变化了才去重新计算
if (dirty) {
value = effectFn()
dirty = false
} return value
}
} return obj
}

测试一波

const state = reactive({
a: 1,
b: 2,
c: 3
}) const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
}) console.log(sum.value) // 3
console.log(sum.value) // 3 state.a = 4 console.log(sum.value) // 3 答案是错误的

寄上任务调度

不得不说,任务调度实在太强大了,不仅仅可以实现数组的异步批量更新、在computedwatch中也是必不可少的。

function computed (getter) {
const effectFn = effect(getter, {
lazy: true,
// 数据发生变化后,不执行注册的回调,而是执行scheduler
scheduler () {
// 数据发生了变化后,则重新设置为dirty,那么下次就会重新计算
dirty = true
}
})
let value
let dirty = true const obj = {
get value () {
// 2. 只有数据发生变化了才去重新计算
if (dirty) {
value = effectFn()
dirty = false
} return value
}
} return obj
}

测试一波

const state = reactive({
a: 1,
b: 2,
c: 3
}) const sum = computed(() => {
console.log('执行计算')
return state.a + state.b
}) console.log(sum.value) // 3
console.log(sum.value) // 3 state.a = 4 console.log(sum.value) // 3 答案是错误的

完美!!!这下面试官再也难不倒我了!!!

本文转载于:

https://juejin.cn/post/7259405321020424251

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--为啥面试官总喜欢问computed是咋实现的?的更多相关文章

  1. 基础面试,为什么面试官总喜欢问String?

    关于 Java String,这是面试的基础,但是还有很多童鞋不能说清楚,所以本文将简单而又透彻的说明一下那个让你迷惑的 String 在 Java 中,我们有两种方式创建一个字符串 String x ...

  2. 一线大厂面试官最喜欢问的15道Java多线程面试题

    前言 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分.如果你想获得更多职位,那么你应该准备很多关于多线程的问题. 他们会问面试者很多令人混淆的Java线程问题.面试官只是想确信面试者 ...

  3. 2019年面试官最喜欢问的28道ZooKeeper面试题

    前言 ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务.它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护.域名服务.分布式同步.组服务等. ZooKeeper 的 ...

  4. 深度分析:面试腾讯,阿里面试官都喜欢问的String源码,看完你学会了吗?

    前言 最近花了两天时间,整理了一下String的源码.这个整理并不全面但是也涵盖了大部分Spring源码中的方法.后续如果有时间还会将剩余的未整理的方法更新到这篇文章中.方便以后的复习和面试使用.如果 ...

  5. 阿里面试官最喜欢问的21个HashMap面试题

    1.HashMap 的数据结构? A:哈希表结构(链表散列:数组+链表)实现,结合数组和链表的优点.当链表长度超过 8 时,链表转换为红黑树. transient Node<K,V>\[\ ...

  6. 聊聊CAS - 面试官最喜欢问的并发编程专题

    什么是CAS 学习Java并发编程,CAS(Compare And Set)机制都是一个不得不掌握的知识点.除了通过synchronized进行并发控制外,还可以通过CAS的方式控制,大家熟悉的Ree ...

  7. 2021超详细的HashMap原理分析,面试官就喜欢问这个!

    一.散列表结构 散列表结构就是数组+链表的结构 二.什么是哈希? Hash也称散列.哈希,对应的英文单词Hash,基本原理就是把任意长度的输入,通过Hash算法变成固定长度的输出 这个映射的规则就是对 ...

  8. 走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串

    原文:走向DBA[MSSQL篇] 面试官最喜欢的问题 ----索引+C#面试题客串 对大量数据进行查询时,可以应用到索引技术.索引是一种特殊类型的数据库对象,它保存着数据表中一列或者多列的排序结果,有 ...

  9. Java面试官最常问的volatile关键字

    在Java相关的职位面试中,很多Java面试官都喜欢考察应聘者对Java并发的了解程度,以volatile关键字为切入点,往往会问到底,Java内存模型(JMM)和Java并发编程的一些特点都会被牵扯 ...

  10. 大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)

    大厂面试官最常问的@Configuration+@Bean(JDKConfig编程方式)   现在大部分的Spring项目都采用了基于注解的配置,采用了@Configuration 替换标签的做法.一 ...

随机推荐

  1. vue-element-admin iframes 组件 保留 iframe 操作状态

    由于没有时间去维护这个功能,这个仓库我暂停了,当前博客内容和代码只作为实现思路参考 代码贴前面,gitee地址:https://gitee.com/chkhk/vue-element-admin 可以 ...

  2. Windows OhmGraphite 配置

    Windows OhmGraphite 配置 由于windows_exporter无法监控温度相关的指标,那么就需要使用OhmGraphite进行监控该指标. 下载 访问 https://github ...

  3. 介绍 ComPDFKit 转换 SDK 1.5.0

    介绍 ComPDFKit 转换 SDK 1.5.0 了解有关 ComPDFKit PDF SDK 的更多信息:https ://www.compdf.com/ ComPDFKit Conversion ...

  4. 【Unity3D】发射(Raycast)物理射线(Ray)

    1 前言 ​ 碰撞体组件Collider 中介绍了 2 个碰撞体之间的碰撞检测,本文将介绍物理射线与碰撞体之间的碰撞检测.物理射线由 Ray 定义,通过 Physics.Raycast / Physi ...

  5. golang在 ubuntu下交叉编译报错 gcc: error: unrecognized command line option ‘-mthreads’; did you mean ‘-pthread’?

    前置说明: 之前一直都是用centos 7做开发机, 因为工作需要用c2 工具sliver编译木马而依赖 mingw64,但是centos安装这个非常麻烦, 就换了ubuntu开发机; 现需要交叉编译 ...

  6. 细说Spring Boot初始化DispatcherServlet

    DispatcherServlet概述 在Spring Boot框架未出现之前,要开发一个基于Spring MVC框架的项目,通常需要在Java web项目的描述符文件web.xml中添加如下配置: ...

  7. 海康摄像头开发笔记(一):连接防爆摄像头、配置摄像头网段、设置rtsp码流、播放rtsp流、获取rtsp流、调优rtsp流播放延迟以及录像存储

    前言   Hik防爆摄像头录像,因为防爆摄像头会有对应的APP软件,与普通的网络摄像头和球机不一样,默认认为它不可以通过web网页配置,所以弄了个来实测确认.  经测试实际上也是可以通过web网页配置 ...

  8. 【Azure 应用服务】App Service 默认页面暴露Tomcat版本信息,存在安全风险

    问题描述 在创建Azure App Service时,服务端的配置使用Java 8 + Tomcat 8.5.默认的根目录页面显示出App Service Tomcat版本信息,存在一定的安全隐患. ...

  9. Task Manager 的设计简述

    讲解 Task Manager 之前,在这里先介绍一些 Task Manager 会使用到的概念术语. 图数据库 Nebula Graph 中,存在一些长期在后台运行的任务,我们称之为 Job.存储层 ...

  10. linux 命令行使用codeql

    目录 CodeQL 概述 安装 直接使用在线查询(lgtm) vscode使用codeql 下载 库文件 测试 linux控制台运行 下载 安装 创建数据库 编写QL查询数据库 简单解释 CodeQL ...