首页 > 编程语言 >Vue源码学习(十一):计算属性computed初步学习

Vue源码学习(十一):计算属性computed初步学习

时间:2023-10-15 22:57:23浏览次数:74  
标签:key userDef Vue computed watcher 源码 dirty 计算 属性

好家伙,

 

 

1.Computed实现原理

if (opts.computed) {
    initComputed(vm,opts.computed);
}
function initComputed(vm, computed) {
    // 存放计算属性的watcher
    const watchers = vm._computedWatchers = {};
    for (const key in computed) {
        const userDef = computed[key];
        // 获取get方法
        const getter = typeof userDef === 'function' ? userDef : userDef.get;
        // 创建计算属性watcher
        watchers[key] = new Watcher(vm, userDef, () => {}, { lazy: true });
        defineComputed(vm, key, userDef)
    }
}

computed依赖跟踪的处理逻辑与watcher相似

 

1.1.watcher

每个计算属性也都是一个watcher,计算属性需要表示lazy:true,这样在初始化watcher时不会立即调用计算属性方法

class Watcher {
    constructor(vm, exprOrFn, callback, options) {
        this.vm = vm;
        this.dirty = this.lazy
        // ...
        this.value = this.lazy ? undefined : this.get(); // 调用get方法 会让渲染watcher执行
    }
}    

 

1.2.dirty属性

 默认计算属性需要保存一个dirty属性,用来实现缓存功能

function defineComputed(target, key, userDef) {
    if (typeof userDef === 'function') {
        sharedPropertyDefinition.get = createComputedGetter(key)
    } else {
        sharedPropertyDefinition.get = createComputedGetter(userDef.get);
        sharedPropertyDefinition.set = userDef.set;
    }
    // 使用defineProperty定义
    Object.defineProperty(target, key, sharedPropertyDefinition)
}
function createComputedGetter(key) {
    return function computedGetter() {
        const watcher = this._computedWatchers[key];
        if (watcher) {
            if (watcher.dirty) { // 如果dirty为true
                watcher.evaluate();// 计算出新值,并将dirty 更新为false
            }
            // 如果依赖的值不发生变化,则返回上次计算的结果
            return watcher.value
        }
    }
}

为什么使用缓存?

1.减少不必要的计算开销:计算属性的值是根据依赖的响应式数据计算而来的。如果每次访问计算属性都重新计算一次,无论依赖数据有没有变化,都会导致不必要的计算开销。

            通过使用 dirty 属性,可以标记计算属性是否需要重新计算,从而避免不必要的计算。

2.提高性能与响应速度:通过缓存计算属性的值,当访问计算属性时,如果依赖数据没有发生改变,可以直接返回之前的缓存值,而不必重新计算。

             这样可以提高性能并且快速响应用户的数据访问请求。

3.依赖数据发生变化时再重新计算:当依赖的响应式数据发生变化时,计算属性才需要重新计算。

                通过将 dirty 属性设置为 true,可以在下一次访问计算属性时触发重新计算,并将计算结果缓存起来。

 

1.3.watcher.evaluate()方法

evaluate() {
    this.value = this.get()
    this.dirty = false
}
 

update() {
    if (this.lazy) {
        this.dirty = true;
    } else {
        queueWatcher(this); //更新方法
    }
}

 

 当依赖的属性变化时,会通知watcher调用update方法,此时我们将dirty置换为true。这样再取值时会重新进行计算。

if (watcher) {
    if (watcher.dirty) {
        watcher.evaluate();
    }
    if (Dep.target) { // 计算属性在模板中使用 则存在Dep.target
        watcher.depend()
    }
    return watcher.value
}
 

depend() {
    let i = this.deps.length
    while (i--) {
        this.deps[i].depend()
    }
}

 

 如果计算属性在模板中使用,就让计算属性中依赖的数据也记录渲染watcher,这样依赖的属性发生变化也可以让视图进行刷新

标签:key,userDef,Vue,computed,watcher,源码,dirty,计算,属性
From: https://www.cnblogs.com/FatTiger4399/p/17766224.html

相关文章

  • 开源项目 | 一款基于NodeJs+Vue3的强大的在线设计图片工具
     一、项目概述一款漂亮且功能强大的在线海报图片设计器,仿稿定设计。适用于海报图片生成、电商分享图、文章长图、视频/公众号封面等多种场景。二、技术特性丝滑的操作体验,丰富的交互细节,基础功能完善采用服务端生成图片,确保多端出图统一性,支持各种CSS特性简易AI......
  • vue3中setup
    和vue2不同的是vue3中的script中带有setup标签里面的setup相当于vue2中的data和methds空间可以放置函数,也可以执行函数在写时需要有return返回值<scriptsetup></script>setup执行发生在页面之前所以不能使用this函数,一般通过ref绑定组件上的值进行修改 使用函数例子......
  • 手撕Vue-数据驱动界面改变上
    经过上一篇的介绍,已经实现了监听数据的变化,接下来就是要实现数据变化后,界面也跟着变化,这就是数据驱动界面改变。想要实现数据变化之后更新UI界面,我们可以使用发布订阅模式来实现,先定义一个观察者类,再定义一个发布订阅类,然后再通过发布订阅的类来管理观察者类。接下来我们就......
  • 手撕Vue-监听数据变化
    经过上一篇的介绍,已经实现了将模板编译成具体数据,接下来要介绍的是如何监听数据的变化,本章主要完成这个需求即可。在我们文章的开始,我写了一个Vue双向数据绑定原理的文章当中封装了一个Observer类,这个类的作用就是监听数据的变化,当数据发生变化的时候,会通知订阅者,订阅者会去......
  • Vue的学习
    为什么需要前端框架当前前端开发的状态前端基础语言html:构建页面内容结构css:美化和布局页面内容Javascript:提供交互能力和动态三者整合就是我们看到的网页页面---所有的页面和页面功能都能完成现在能做什么浏览器展示的网页+小程序网站,网页游戏等等当前的状态有什么问题基......
  • 手撕Vue-编译模板数据
    经上一篇编译指令数据后,我们已经可以将指令数据编译成具体需要展示的数据了,上一篇只是编译了指令数据,还没有编译模板数据,这一篇我们就来编译模板数据。也就是{{}}这种模板的形式我们该如何编译,其实和指令数据编译的思路是一样的,废话不多说,直接上代码。改造一下buildText方法......
  • 《人人都是数据分析师》高清高质量PDF电子书+源码
    下载:https://pan.quark.cn/s/3f61395b8d51......
  • 《Head First JavaScript程序设计》高清高质量 原版电子书PDF+源码
    下载:https://pan.quark.cn/s/9b368a216582......
  • 手撕Vue-编译指令数据
    经过上一篇的分析,完成了查找指令和模板的功能,接下来就是编译指令的数据了。所以本章节主要处理的方法则是buildElement方法,我们先分析一下我们所拿到的数据在进行编码,这样会更加清晰一些。我将name,value打印出来,分别对应的值是name:v-model,value:name,在今后我们的命......
  • vue学习六
    <divid="app6"><divv-for="iteminlist">{{item}}</div></div><script>constapp6=newVue({el:'#app6',data:{list:["1&qu......