为啥内部值会对整个 ref 的变化做出反应?
Posted
技术标签:
【中文标题】为啥内部值会对整个 ref 的变化做出反应?【英文标题】:Why does an internal value react to changes from the whole ref?为什么内部值会对整个 ref 的变化做出反应? 【发布时间】:2022-01-10 23:26:31 【问题描述】:我有一个对象...
export class Note
type = ''
id: string = v4()
creationDate: string = DateTime.now().toISO()
modificationDate: string = DateTime.now().toISO()
text = ''
title = ''
tags: string[] = []
deleted = false
deletedAt?: string = ''
erased = false
erasedAt?: string = ''
archived = false
archivedAt?: string = ''
deleteOn?: string = ''
pinned = false
// methods follow
...我作为道具传递给组件
<script lang='ts' setup>
const props = defineProps(
currentNote: type: Object, default: () => return ,
)
const note = toRef(props, 'currentNote') as Ref<Note>
const toWatch = computed(() => [toRef(note, 'title'), toRef(note, 'text'), toRef(note, 'tags'), toRef(note, 'type')])
watch(toWatch, debounce(() => console.log(JSON.stringify(note)); note.value.writeToOffline(), 1000), deep: true)
(...)
然而,watch
回调会在note
的任何属性发生变化时触发。
上面的结构是只观察选定的属性,但显然它们带有任何变化。
我的代码中的逻辑有什么问题?
【问题讨论】:
【参考方案1】:不可重现。查看下面的演示...
-
对
archived
的更改不会触发观察者
对title
的更改也不会触发观察者-注意toWatch
中的代码计算-代码与您的示例相同:Vue.toRef(note, 'title')
对text
的更改会触发观察程序 - 要解决上述问题,您需要使用Vue.toRef(note.value, 'text')
例如。将 ref 值而不是 ref 本身传递给 toRefs
所有这些都可以在没有deep: true
的情况下工作,因为watch
可以观看一组引用(而且似乎ref
也包含refs
的数组)
class Note
constructor()
this.type = '';
this.id = 'asdsad';
this.text = 'text';
this.title = 'title';
this.tags = [];
this.deleted = false;
this.deletedAt = '';
this.erased = false;
this.erasedAt = '';
this.archived = false;
this.archivedAt = '';
this.deleteOn = '';
this.pinned = false;
const app = Vue.createApp(
setup()
const note = Vue.reactive(new Note())
const modifyArchived = function()
note.archived = !note.archived
const modifyTitle = function()
note.title = note.title + '+'
const modifyText = function()
note.text = note.text + '+'
return
note,
modifyArchived,
modifyTitle,
modifyText
,
)
app.component('child',
props: ['currentNote'],
setup(props)
const note = Vue.toRef(props, 'currentNote')
const changes = Vue.ref(0)
const toWatch = Vue.computed(() => [Vue.toRef(note, 'title'), Vue.toRef(note.value, 'text'), Vue.toRef(note, 'tags'), Vue.toRef(note, 'type')])
Vue.watch(toWatch, () => changes.value++ /*, deep: true */)
return
note,
changes
,
template: `
<div>Child: (changes = changes )</div>
<div>archived: note.archived </div>
<div>title: note.title </div>
<div>text: note.text </div>
`
)
app.mount('#app')
<script src="https://unpkg.com/vue@3.2.23/dist/vue.global.js"></script>
<div id='app'>
<div>Parent:</div>
<div><button @click="modifyArchived">Modify archived (no trigger)</button></div>
<div><button @click="modifyTitle">Modify title (no trigger - not ok!)</button></div>
<div><button @click="modifyText">Modify text (trigger - ok!)</button></div>
<child :current-note="note"></child>
</div>
【讨论】:
谢谢。我修改了您的示例 (jsfiddle.net/WoJWoJ/Lsp67vqo) 以准确重现我的问题(无论如何都会触发监视回调的非监视属性),但我无法重现它。我必须再次查看我的代码,因为那里一定有什么东西。感谢您提醒我在toRef()
中使用 .value
。以上是关于为啥内部值会对整个 ref 的变化做出反应?的主要内容,如果未能解决你的问题,请参考以下文章
java - 为啥在java中的poll方法之后PriorityQueue中的值会发生变化? [复制]
为啥 GL_MAX_UNIFORM_BLOCK_SIZE 的值会发生变化?