为啥内部值会对整个 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 的变化做出反应?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的数组值会发生变化? [复制]

为啥 Keras Dropout 中的非零值会发生变化?

java - 为啥在java中的poll方法之后PriorityQueue中的值会发生变化? [复制]

为啥 GL_MAX_UNIFORM_BLOCK_SIZE 的值会发生变化?

如何让 rhandsontable 对输入值的变化和自身的变化做出反应?

*ngIf 不对布尔值变化做出反应