strange behaviors of Proxy objects with getter in script setup
Vue version
3.3.4
Link to minimal reproduction
Steps to reproduce
- Define Proxy object with getter in
<scrip setup>
or define it in another module and import (result are same). For example:
<script setup>
const obj = {a: 1, b: 2, c: 3};
const proxy = new Proxy(obj, {
get: (target, key) => key in target ? target[key] : 'Not present'
});
</script>
- Call any property from proxy in
<template>
section. For example:
<template>
<div>{{ proxy.a }}</div>
<div>{{ proxy.notExists }}</div>
</template>
What is expected?
Proxy getter call result
What is actually happening?
Each property on template calls getter twice. First time with '__v_isRef'
key, second call with requested key.
This can be seen if add some logic to Proxy getter function:
const proxy = new Proxy(obj, {
get: (target, key) => {
console.log(key);
return key in target ? target[key] : 'Not present'
};
});
System Info
System:
OS: Windows 10 10.0.22621
CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
Memory: 1.68 GB / 31.93 GB
Binaries:
Node: 18.3.0 - D:\ZBIN\node-v18.3.0-x64\node.EXE
npm: 8.12.1 - D:\ZBIN\node-v18.3.0-x64\npm.CMD
Browsers:
Chrome: 113.0.5672.127
Edge: Spartan (44.22621.1344.0), Chromium (113.0.1774.57)
Internet Explorer: 11.0.22621.1
npmPackages:
vue: 3.3.4 => 3.3.4
Any additional comments?
Temporary fix in user code:
const proxy = new Proxy(obj, {
get: (target, key) => {
if (key === '__v_isRef') {
return undefined;
}
...
}
});
@Bobsans Why do you want to use Proxy directly when you have ref/reactive?
Here is the line where __v_isRef accessedhttps://github.com/vuejs/core/blob/a95e612b252ae59eaf56e0b8ddba66948d4ac20e/packages/reactivity/src/ref.ts#L80
In template unref is used to avoid .value access https://github.com/vuejs/core/blob/a95e612b252ae59eaf56e0b8ddba66948d4ac20e/packages/reactivity/src/ref.ts#L212
unref is using isRef which is accessing __v_isRef, hence the console logs.
Here is list of non-trackable keys (Vue takes care of these properties internally) https://github.com/vuejs/core/blob/a95e612b252ae59eaf56e0b8ddba66948d4ac20e/packages/reactivity/src/baseHandlers.ts#L35
Please explain the intention behind using Proxy directly instead of ref/reactive, for me this is working as expected.