计算属性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)
}
}
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。
发表评论