在Vue.js中使用prop.sync和watcher进行双向绑定

esyap4oy  于 6个月前  发布在  Vue.js
关注(0)|答案(2)|浏览(89)

我很难理解父组件和子组件之间的双向绑定。到目前为止,我所读到的似乎都推荐在观看prop的同时使用prop.sync。例如:
父项:

<child-component :childProp.sync="parentData"></child-component>

字符串
孩子:

<template>
  <input v-model="childData" @input="$emit('update:childProp', childData);"></input>
</template>
<script>
  export default {
    props: ['childProp'],
    data() {
      childData: childProp
    },
    watch: {
      childProp(newValue) {
        this.childData = newValue;
      }
    }
  }
</script>


我的问题是,当更新parentData或childData时,这是否会产生某种冗余?流程将是这样的(对于parentData已更改):
1.父数据更改->
1.触发器监视->
1.子数据更改->
1.触发器.sync ->

  1. parentData已更新。
    我假设循环在第5步停止,因为parentData的更新值与旧值相同,所以parentData实际上没有更改,因此第2步的监视器没有被触发。
    我的问题是,如果我的推理是正确的,那么对parentData所做的更改将传递给child并反映给它自己,反之亦然。反映就是冗余。到目前为止,我是对的吗?还是说我对这一点的理解完全错误了?
    如果我错了,请帮助我理解我错在哪里。但如果我是对的,那么有没有另一种方法来实现双向绑定而没有这种冗余?
7xzttuei

7xzttuei1#

我想你可以这样简化子组件代码:

<template>
  <input :value="childProp" @input="$emit('update:childProp', $event);"></input>
</template>
<script>
  export default {
    props: ['childProp']
  }
</script>

字符串

cedebl8k

cedebl8k2#

注意:我对Vue很陌生,所以可能会错过一些重要的东西。
此外,以下所有内容都是基于使用Vue 2。

1.我遇到了相反的效果--更改子对象中的值会影响模板,但不会触发父对象的监视器

在我的实际案例中,父组件处理服务器对几个子组件的调用,这些子组件处理设置UI。当父组件更改props(例如,从服务器获取当前设置后)时,子组件的状态应该发生变化,而不会产生其他影响。但是当子组件更改props(例如,在用户交互时)时,父组件应该触发对服务器的请求,以更新相关设置。

2.我的解决方案

这是Vue的v-model的一个变体,用于自定义组件。
子组件没有使用.sync修饰符,而是为每个应该同步的prop提供一个valueprop和一个internalValuedata属性。
所有对internalValue的更改都不会直接应用,而是通过changeInternalValue函数应用,该函数接受shouldEmit参数。shouldEmit对于子更改为true,对于父更改为false(例如,来自value的监视器)。
大概是这样的:

Vue.component('my-component', {
    props: ['isEnabled'],      
    data: {
         isEnabledInternal: this.isEnabled,
    },
    watch: {
        isEnabled: {
            handler: function(newVal) {
                this.changeInternalIsEnabled(newVal, false);
            },
            immediate: true,
        },
    },
    methods: {
        onToggle: function(newVal) { // triggered from component's template on user interaction
            this.changeInternalIsEnabled(newVal, true);
        },
        changeInternalIsEnabled: function(newVal) {            
            if (newVal !== this.isEnabledInternal) {
                this.isEnabledInternal = newVal;
                if (shouldEmit) {
                    this.$emit('my-component-changed', this.isEnabledInternal);
                }                
            }
        },
    },
});

字符串
父组件监听my-component-changed事件,并根据事件的值(通过其模板中的<my-component @my-component-changed="setEnabledAndDoStuff">)更改isEnabled。这将触发子组件的监视器,但不会再次发出事件。

相关问题