feat(computed): 添加计算属性功能实现
- 实现了 ComputedRefImpl 类来管理计算属性 - 添加了 computed 函数用于创建计算属性 - 在 ReactiveEffect 中添加 computed 属性引用 - 将 computed 导出到 reactivity 和 vue 主包 - 添加了 isFunction 工具函数判断函数类型 - 创建了计算属性的 HTML 示例文件进行演示
This commit is contained in:
30
packages/reactivity/src/computed.ts
Normal file
30
packages/reactivity/src/computed.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { isFunction } from '@vue/shared'
|
||||||
|
import { Dep } from './dep'
|
||||||
|
import { ReactiveEffect } from './effect'
|
||||||
|
import { trackRefValue } from './ref'
|
||||||
|
|
||||||
|
export class ComputedRefImpl<T> {
|
||||||
|
public dep?: Dep = undefined
|
||||||
|
private _value!: T
|
||||||
|
public readonly effect: ReactiveEffect<T>
|
||||||
|
public readonly __v_isRef = true
|
||||||
|
constructor(getter) {
|
||||||
|
this.effect = new ReactiveEffect(getter)
|
||||||
|
this.effect.computed = this
|
||||||
|
}
|
||||||
|
get value() {
|
||||||
|
trackRefValue(this) //触发依赖
|
||||||
|
this._value = this.effect.run()
|
||||||
|
return this._value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function computed(getterOrOptions) {
|
||||||
|
let getter
|
||||||
|
const onlyGetter = isFunction(getterOrOptions)
|
||||||
|
if (onlyGetter) {
|
||||||
|
getter = getterOrOptions
|
||||||
|
}
|
||||||
|
const cRef = new ComputedRefImpl(getter)
|
||||||
|
return cRef
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
import { createDep, Dep } from './dep'
|
import { createDep, Dep } from './dep'
|
||||||
import { isArray } from '@vue/shared'
|
import { isArray } from '@vue/shared'
|
||||||
|
import { ComputedRefImpl } from './computed'
|
||||||
|
|
||||||
type KeyToDepMap = Map<any, Dep>
|
type KeyToDepMap = Map<any, Dep>
|
||||||
/**
|
/**
|
||||||
@@ -19,6 +20,7 @@ export function effect<T = any>(fn: () => T) {
|
|||||||
export let activeEffect: ReactiveEffect | undefined
|
export let activeEffect: ReactiveEffect | undefined
|
||||||
|
|
||||||
export class ReactiveEffect<T = any> {
|
export class ReactiveEffect<T = any> {
|
||||||
|
computed?: ComputedRefImpl<T>
|
||||||
constructor(public fn: () => T) {}
|
constructor(public fn: () => T) {}
|
||||||
run() {
|
run() {
|
||||||
//当前被激活的effect实例
|
//当前被激活的effect实例
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
export { reactive } from './reactive'
|
export { reactive } from './reactive'
|
||||||
export { effect } from './effect'
|
export { effect } from './effect'
|
||||||
export { ref } from './ref'
|
export { ref } from './ref'
|
||||||
|
export { computed } from './computed'
|
||||||
|
|||||||
@@ -9,3 +9,7 @@ export const isObject = (val: unknown) =>
|
|||||||
*/
|
*/
|
||||||
export const hasChanged = (value: any, oldValue: any): boolean =>
|
export const hasChanged = (value: any, oldValue: any): boolean =>
|
||||||
!Object.is(value, oldValue)
|
!Object.is(value, oldValue)
|
||||||
|
|
||||||
|
export const isFunction = (val: unknown): val is Function => {
|
||||||
|
return typeof val === 'function'
|
||||||
|
}
|
||||||
|
|||||||
26
packages/vue/examples/reactivity/computed.html
Normal file
26
packages/vue/examples/reactivity/computed.html
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Document</title>
|
||||||
|
<script src="../../dist/vue.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
const { reactive,effect,computed } = Vue
|
||||||
|
const obj=reactive({
|
||||||
|
name:'张三'
|
||||||
|
})
|
||||||
|
const computedObj= computed(()=>{
|
||||||
|
return '姓名:'+obj.name
|
||||||
|
})
|
||||||
|
effect(()=>{
|
||||||
|
document.querySelector('#app').innerText=computedObj.value
|
||||||
|
})
|
||||||
|
setTimeout(()=>{
|
||||||
|
obj.name='李四'
|
||||||
|
},2000)
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
@@ -1 +1 @@
|
|||||||
export { reactive, effect, ref } from '@vue/reactivity'
|
export { reactive, effect, ref, computed } from '@vue/reactivity'
|
||||||
|
|||||||
Reference in New Issue
Block a user