文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

vue计算属性computed--getter和setter用法

2023-01-28 06:06

关注

计算属性computed和方法methods的区别

计算属性本质上是包含getter和setter的方法

当获取计算属性时,实际上是在调用计算属性的getter方法。vue会收集计算属性的依赖,并缓存计算属性的返回结果。只有当依赖变化后才会重新进行计算。

方法没有缓存,每次调用方法都会导致重新执行。

计算属性的getter和setter参数固定,getter没有参数,setter只有一个参数。而方法的参数不限。

由于有以上的这些区别,因此计算属性通常是根据已有数据得到其他数据,并在得到数据的过程中不建议使用异步、当前时间、随机数等副作用操作。

实际上,他们最重要的区别是含义上的区别。计算属性含义上也是一个数据,可以读取也可以赋值;方法含义上是一个操作,用于处理一些事情。

计算属性的完整写法

      computed: {
        propsName: {
          a:['aavsx'],
          get(){
            return this.a;
          },
          set(val){
            this.a = val
          }
        },
      }

注:

1.get方法是当属性被读取时触发,在计算属性中,如果计算属性依赖没有发生改变(例子中this.a就是计算属性的依赖,只要this.a不发生改变,它就不会再次调用get方法),get只会调用一次,并且会将返回结果缓存起来。

2.get方法必须需要一个返回值,否者会报出以下错误:


3.如果set方法没有改变get方法中的依赖(this.a),则get方法不会再次调用,而是直接使用缓存值

<template>
    <div>
    {{propsName = 'add'}} //结果是add
    {{propsName}}//结果是 a ,以为set方法没有改变this.a这个依赖
    </div>
</template>

<script>
export default {
  data(){
    return {
      a:'a',
      b:'b'
    }
  },
  computed: {
    propsName: {
      get(){
        return this.a
      },
      set(val){
       this.b = val
      }
    },
  }
}
</script>

一般情况下,计算属性只使用getter方法,所以计算属性可以简写为:

computed: {
  propName(){
    // getter
    //必须要有返回值
  }
}

vue3计算属性computed实现原理

computed实现原理

computed特性

computed可以传入一个函数,也可以传入一个对象(带有get和set方法),计算属性返回一个计算值,该值通过value属性访问,当参与计算的数据发生改变,则重新计算,不发生改变,则直接返回之前缓存的值

render 只执行了一次

   const { effect, reactive,computed } = VueReactivity

        const state = reactive({
            firstName:'s',
            lastName:'x'
        })
        let fullName = computed(()=>{
            console.log('runner')
            return state.firstName + state.lastName
        })
        console.log(fullName.value)
        console.log(fullName.value)
        console.log(fullName.value)

计算属性返回值可以作为属性参与effect更新

 const { effect, reactive,computed } = VueReactivity

        const state = reactive({
            firstName:'s',
            lastName:'x'
        })
       
        let fullName = computed({
            get(){
                return state.firstName + state.lastName
            },
            set(value){
                state.lastName = value
            }
        })
        fullName.value = 100
        effect(()=>{
            app.innerHTML = fullName.value
        })
        setTimeout(()=>{
            state.firstName = 'x'
        },1000)

实现思路

导出一个computed函数,函数内部有两个变量getter、setter

函数传入一个对象或者函数。

如果是函数,则将该函数赋值给getter,setter赋值为一个报错函数(即抛出错误)

如果是对象,则将其get和set分别赋值给getter和setter

创建computedRefImpl类,有两个形参(getter、setter),在computer函数中实例化并返回该类

类中在实例的constructor构造器中通过实例化ReactiveEffect类,传入getter,实现对计算属性函数传入的属性的数据绑定,传入第二个参数,在数据更新完之后将_dirty标记为true,并实现数据更新(triggerEffects)

私有变量_dirty控制数据是否更新

其有两个方法get value 和 set value

当调用get,让ReactiveEffect实例运行,获取其返回值赋值给内部变量_value,并返回改变量,将_dirty设置为false,表示没有新的数据改变了,可以使用缓存,判断当前环境是否存在activeEffect,存在则进行依赖收集(调用trackEffects)

调用set则运行setter

完整代码如下:

import { isFunction } from "@vue/shared"
import { activeEffect, trackEffects, triggerEffects,ReactiveEffect } from "./effect";

export function computed(getterOrOptions){
    let getter = null;
    let setter = null;
    let fn = ()=>{
        throw new Error("this function is onlyRead");
        
    }
    let isGetter = isFunction(getterOrOptions)
    if(isGetter){
        getter = getterOrOptions
        setter = fn
    }
    else {
        getter = getterOrOptions.get
        setter = getterOrOptions.set || fn
    }

    return new computedRefImpl(getter,setter)
}

class computedRefImpl{
    private _value = null
    private _dirty = true
    public effect = null
    public deps = null
    constructor(getter,public setter){
        this.effect = new ReactiveEffect(getter,()=>{
            if(!this._dirty){
                this._dirty = true
                triggerEffects(this.deps)
            }
        })
    }
    get value(){
        debugger
        if(activeEffect){
            // 存在effect,则进行依赖收集
            trackEffects(this.deps ||  (this.deps = new Set()) )
        }
        if(this._dirty){
            this._dirty = false
            this._value = this.effect.run()
        }
        return this._value
    }
    set value(newValue){
        this.setter(newValue)
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯