use*_*112 4 javascript vuejs3 vue-composition-api
我对 vuejs 非常热衷,但组合 API 让我在反应性上稍微迷失了一些:
\n在 .vue 子组件中,传递一个 prop(由另一个父组件),电影:
\nexport default {\n props:{\n movies: Array\n },\n setup(props){}\nRun Code Online (Sandbox Code Playgroud)\n。
\n放置在该子组件的setup函数体中:
\nA) console.log("props: ",props) // Proxy {}\nRun Code Online (Sandbox Code Playgroud)\n[above EXPECTED] 上面告诉我 props 对象是一个反应式代理对象。
\nB) console.log("props.movies: ",props.movies); // Proxy {}\nRun Code Online (Sandbox Code Playgroud)\n[以上意外] 上面告诉我 props 键“movies”也是一个反应式代理对象,为什么?(因此,为什么不仅主要 props 对象是反应性的?也许我应该认为这是理所当然的(例如,将其视为 props =reactive(props) 调用的结果) \n--> 答案: props 是 * *深 ** 反应对象(感谢 Michal Lev\xc3\xbd!)
\nC) let moviesLocal = props.movies ; // ERROR-> getting value from props in root scope of setup will cause the value to loose reactivity\nRun Code Online (Sandbox Code Playgroud)\n[上述意外] 由于 props.movies 是一个反应性对象,我假设我可以将其分配给一个局部变量,然后这个局部变量也会变得反应性。为什么情况并非如此(我收到上面显示的错误)
\nD) let moviesLocal = ref(props.movies);\n moviesLocal.value[0].Title="CHANGED in child component";\nRun Code Online (Sandbox Code Playgroud)\n[上述意外]\n我在子组件 (moviesLocal) 中制作了本地副本。我将这个变量设为反应性(参考)。更改反应式 movieLocal 的值也会导致父对象中的“电影”反应式对象发生变化,这是为什么?如果我更改 D: let movieLocal = ref(props.movies); 这甚至成立 让 movieLocal = ref({...props.movies});
\n多谢!期待了解这种行为
\n理解 Vue 反应性的重要部分是理解 JavaScript——特别是Value 和 Reference之间的区别。如果您不确定我在说什么,请仔细阅读这篇文章......
在以下示例中,我将使用props按以下方式创建的对象(实际上,它的创建方式并不完全如此,但运行时行为非常相似):
const props = reactive({ movies: [], price: 100 })
Run Code Online (Sandbox Code Playgroud)
B) console.log("props.movies: ",props.movies); // Proxy {}
Run Code Online (Sandbox Code Playgroud)
上面告诉我 props 键“movies”也是一个反应式代理对象,为什么?
因为当 Vue 创建新的响应式对象(通过将现有对象包装到代理中)时,该转换是深层的markRaw- 它会影响所有嵌套属性(可以通过使用例如或来更改此行为shallowRef)
就值与引用而言,它props是一个保存对反应式代理对象的引用的变量。该对象有一个属性movies,该属性保存对数组的反应式代理的引用(从技术上讲,数组也是对象)
C) let moviesLocal = props.movies ;
// ERROR-> getting value from props in root scope of setup will cause the value to loose reactivity
Run Code Online (Sandbox Code Playgroud)
由于 props.movies 是一个响应式对象,我假设我可以将其分配给一个局部变量,然后这个局部变量也会变得响应式。为什么情况并非如此
变量不是反应性的。只有对象可以是反应性的。在这种情况下,moviesLocal变量被分配引用与props.movies(moviesLocal === props.movies返回true)相同的反应对象。该对象仍然是反应性的。
让我们moviesLocal在模板中使用变量来渲染某种列表......
例如,如果父级改变了引用的数组props.movies(添加新项目push(),为等等分配不同的值props.movies[0]),则子级将收到有关更改的通知,并且其模板将重新渲染。
那么为什么会出现错误呢?“松散的反应性”在哪里?props.movies问题是当父级用不同的\新数组替换 的值时会发生什么。我们的moviesLocal变量仍将保存对先前反应数组的引用。我们的子组件仍然会对原始数组的更改(突变)做出反应,但失去了对属性更改做出反应的能力props.movies。
在此演示中对此进行了演示
有趣的是,在核心中,这种行为与 Vue 反应性无关。这只是普通的 JS。检查一下:
B) console.log("props.movies: ",props.movies); // Proxy {}
Run Code Online (Sandbox Code Playgroud)
local此时的值是多少?当然如此['Matrix']!const local = obj.movies只是价值分配。它不会以某种方式神奇地将local变量与对象属性的值“链接” obj.movies。
D) let moviesLocal = ref(props.movies);
moviesLocal.value[0].Title="CHANGED in child component";
Run Code Online (Sandbox Code Playgroud)
我在子组件(moviesLocal)中制作了本地副本。我将这个变量设为反应性(参考)。
再次强调,变量不是反应性的。它们指向(引用)的对象可以是反应性的。引用的数组props.movies已经是反应式代理。您刚刚创建了一个ref包含相同对象的对象
更改反应式 movieLocal 的值也会导致父对象中的“电影”反应式对象发生变化,这是为什么?
因为两者都指向(引用)内存中的相同数组(由 Vue 代理包装)。为其中一个分配一个新数组,这个“链接”将会中断......
用于toRef维持反应性。
const moviesLocalRef = toRef(props, 'movies')
Run Code Online (Sandbox Code Playgroud)
请参阅https://v3.vuejs.org/api/refs-api.html#toref
规则是reactive对象子属性必须始终从对象的根访问。a.b.c.d。你不能只是这样做break off a piece and modify it,因为从根开始解析的行为使得 Vue 能够跟踪更改。
在你的例子中,内部属性是相同的,但 Vue 失去了跟踪更改的能力。
作为旁注,您还可以创建计算参考。
const moviesLocalRef = computed(()=>props.movies)
Run Code Online (Sandbox Code Playgroud)
无论您使用computed ref或toRef,您都需要使用theRef.value模板外部来访问您的属性。正如我在结论中所说,这就是 Vue 保持反应性的原因。
以下是我选择考虑 Vue3 反应性的方式。
物体的动作dereferencing a property会触发魔法。
对于 a reactive object,您需要从 the 开始reactive object,然后drill down到您感兴趣的属性。对于 a ,您需要从 中ref拆箱。无论哪种方式,总有一个操作会触发内部机制并通知 Vue 谁在观看什么。valuerefget
这种drilling down情况会在模板和观察者中自动发生,他们知道自己收到了引用,但在其他地方却没有。
请参阅https://v3.vuejs.org/guide/reactivity.html#how-vue-tracks-这些-changes
| 归档时间: |
|
| 查看次数: |
15122 次 |
| 最近记录: |