【问题标题】:Is it possible to watch injected property是否可以观看注入的财产
【发布时间】:2021-02-03 12:27:16
【问题描述】:

我正在构建一个使用 Vue 3 的应用程序,并且我在父组件中提供了一个属性,随后我将其注入到多个子组件中。注入此属性的组件有什么方法可以观察它的变化吗?

父组件看起来像:

<template>
  <child-component/>
  <other-child-component @client-update="update_client" />
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      client: {}
    }
  },
  methods: {
    update_client(client) {
      this.client = client
    }
  },
  provide() {
    return {
      client: this.client
    }
  },
}
</script>

子组件看起来像:

<script>
export default {
  name: 'ChildComponent',
  inject: ['client'],
  watch: {
    client(new_client, old_client) {
      console.log('new client: ', new_client);
    }
  }
}
</script>

我试图实现这一点,当提供的变量在父级中更新时,应该通知其被注入的子级组件。由于某种原因,客户端更新时没有调用客户端监视方法。

有没有更好的方法来做到这一点?

更新

经过进一步测试,我发现这里有一个更大的问题,即使在父组件中更新了客户端之后,在子组件中,客户端属性仍然是原始的空对象并且没有更新。由于提供的属性是响应式的,因此它被注入的所有地方都应该自动更新。

【问题讨论】:

  • 您是否为注入的client 添加了反应性? v3.vuejs.org/guide/…
  • 是的,因为它的值是从 data() 中的属性设置的,所以它是自动响应的。

标签: vue.js vuejs3


【解决方案1】:

手表需要使用deep

示例:

<script>
  export default {
    name: 'ChildComponent',
    inject: ['client'],
    watch: {
      client: {
        handler: (new_client, old_client) => {
          console.log('new client: ', new_client);
        },
        deep: true
      }
    }
  }
</script>

【讨论】:

  • 向手表配置添加深度并没有帮助
【解决方案2】:

如官方文档 (https://vuejs.org/v2/api/#provide-inject) 中所述,默认情况下,提供和注入绑定不是反应式的。但是,如果您传递一个观察到的对象,该对象上的属性将保持反应性。

对于对象,Vue 无法检测属性添加或删除。所以你代码中的问题可能在这里:

  data() {
    return {
      client: {}
    }
  },

由于您更改了此对象的客户端属性( this.client.client = client ),您应该在数据中声明此键,如下所示:

  data() {
    return {
      client: { client: null }
    }
  },

现在它变成了反应式。

我做了一个代码沙箱来重现你的代码,观察注入的属性:https://codesandbox.io/s/vue-inject-watch-ffh2b

【讨论】:

    【解决方案3】:

    由于某种原因,我让它工作的唯一方法是只更新初始注入对象的属性,而不是替换整个对象。尽管设置了deep: true,我也无法让watch 使用注入的属性。

    更新的父组件:

    <template>
      <child-component/>
      <other-child-component @client-update="update_client" />
    </template>
    
    <script>
    export default {
      name: 'App',
      data() {
        return {
          client: {}
        }
      },
      methods: {
        update_client(client) {
          this.client.client = client
        }
      },
      provide() {
        return {
          client: this.client
        }
      },
    }
    </script>
    

    更新子组件:

    <template>
      <button @click="get_client">Get client</button>
    </template>
    <script>
    export default {
      name: 'ChildComponent',
      inject: ['client'],
      methods: {
        get_client() {
          console.log('updated client: ', client);
        }
      }
    }
    </script>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-14
      • 2017-01-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-16
      • 2019-09-12
      相关资源
      最近更新 更多