feat(core): 添加 ref 响应式引用功能
- 实现了 ref 函数用于创建响应式引用 - 添加了 RefImpl 类来管理引用值的响应式行为 - 集成了 trackRefValue 函数进行依赖追踪 - 扩展了 vue 包的导出以包含 ref 功能 - 在 shared 包中添加了 isObject 工具函数 - 创建了 toReactive 辅助函数用于对象响应式转换 - 新增 ref.html 示例文件展示 ref 使用方法 - 移除了旧的 reactive-test.html 示例文件
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
export { reactive } from './reactive'
|
export { reactive } from './reactive'
|
||||||
export { effect } from './effect'
|
export { effect } from './effect'
|
||||||
|
export { ref } from './ref'
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { mutableHandlers } from './baseHandlers'
|
import { mutableHandlers } from './baseHandlers'
|
||||||
|
import { isObject } from '@vue/shared'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 响应性Map缓存对象
|
* 响应性Map缓存对象
|
||||||
@@ -39,3 +40,6 @@ function createReactiveObject(
|
|||||||
proxyMap.set(target, proxy)
|
proxyMap.set(target, proxy)
|
||||||
return proxy
|
return proxy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const toReactive = <T extends unknown>(value: T): T =>
|
||||||
|
isObject(value) ? reactive(value as object) : value
|
||||||
|
|||||||
42
packages/reactivity/src/ref.ts
Normal file
42
packages/reactivity/src/ref.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import { createDep, Dep } from './dep'
|
||||||
|
import { toReactive } from './reactive'
|
||||||
|
import { activeEffect, track, trackEffects } from './effect'
|
||||||
|
|
||||||
|
export interface Ref<T = any> {
|
||||||
|
value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ref(value?: unknown) {
|
||||||
|
return createRef(value, false)
|
||||||
|
}
|
||||||
|
function createRef(rawValue: unknown, shallow: boolean) {
|
||||||
|
if (isRef(rawValue)) {
|
||||||
|
return rawValue
|
||||||
|
}
|
||||||
|
return new RefImpl(rawValue, shallow)
|
||||||
|
}
|
||||||
|
class RefImpl<T> {
|
||||||
|
private _value: T
|
||||||
|
public dep?: Dep = undefined
|
||||||
|
public readonly __v_isRef = true
|
||||||
|
constructor(
|
||||||
|
value: T,
|
||||||
|
public readonly __v_isShallow: boolean
|
||||||
|
) {
|
||||||
|
this._value = __v_isShallow ? value : toReactive(value)
|
||||||
|
}
|
||||||
|
get value() {
|
||||||
|
trackRefValue(this)
|
||||||
|
return this._value
|
||||||
|
}
|
||||||
|
set value(newValue) {}
|
||||||
|
}
|
||||||
|
export function trackRefValue(ref) {
|
||||||
|
if (activeEffect) {
|
||||||
|
trackEffects(ref.dep || (ref.dep = createDep()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//是否为ref
|
||||||
|
export function isRef(r: any): r is Ref {
|
||||||
|
return !!(r && r.__v_isRef === true)
|
||||||
|
}
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
//判断是否为一个数组
|
//判断是否为一个数组
|
||||||
export const isArray = Array.isArray
|
export const isArray = Array.isArray
|
||||||
|
|
||||||
|
export const isObject = (val: unknown) =>
|
||||||
|
val !== null && typeof val === 'object'
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<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">
|
|
||||||
<p id="p1"></p>
|
|
||||||
<p id="p2"></p>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
<script>
|
|
||||||
const { reactive } = Vue
|
|
||||||
const obj=reactive('张三')//不能接收简单数据类型
|
|
||||||
console.log(obj)
|
|
||||||
</script>
|
|
||||||
</html>
|
|
||||||
23
packages/vue/examples/reactivity/ref.html
Normal file
23
packages/vue/examples/reactivity/ref.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<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 { ref,effect } = Vue
|
||||||
|
const obj=ref({
|
||||||
|
name:'张三'
|
||||||
|
})
|
||||||
|
effect(()=>{
|
||||||
|
document.querySelector('#app').innerText=obj.value.name
|
||||||
|
})
|
||||||
|
setTimeout(()=>{
|
||||||
|
obj.value.name='李四'
|
||||||
|
},2000)
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
@@ -1 +1 @@
|
|||||||
export { reactive, effect } from '@vue/reactivity'
|
export { reactive, effect, ref } from '@vue/reactivity'
|
||||||
|
|||||||
Reference in New Issue
Block a user