Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 警告:避免直接变异道具_Javascript_Vue.js_Vuejs2 - Fatal编程技术网

Javascript 警告:避免直接变异道具

Javascript 警告:避免直接变异道具,javascript,vue.js,vuejs2,Javascript,Vue.js,Vuejs2,我陷入了这样一种情况:我的子组件(自动完成)需要更新其父组件(曲线)的值,而父组件需要更新其中一个子组件(或在使用新的曲线组件时完全重新渲染) 在我的应用程序中,用户可以在曲线组件列表中选择一条曲线。我以前的代码工作正常,但当用户在列表中选择另一条曲线时,组件“自动完成”未更新(组件未使用父级的值更新其值) 此问题现已修复,但我收到以下警告: 避免直接改变道具,因为该值将被覆盖 每当父组件重新渲染时。相反,请使用数据或 基于道具值计算的属性。正在变异的支柱: “价值” 此警告的描述准确地解释了我

我陷入了这样一种情况:我的子组件(自动完成)需要更新其父组件(曲线)的值,而父组件需要更新其中一个子组件(或在使用新的曲线组件时完全重新渲染)

在我的应用程序中,用户可以在曲线组件列表中选择一条曲线。我以前的代码工作正常,但当用户在列表中选择另一条曲线时,组件“自动完成”未更新(组件未使用父级的值更新其值)

此问题现已修复,但我收到以下警告:

避免直接改变道具,因为该值将被覆盖 每当父组件重新渲染时。相反,请使用数据或 基于道具值计算的属性。正在变异的支柱: “价值”

此警告的描述准确地解释了我对组件的预期行为。尽管有此警告,但此代码工作正常

以下是代码(部分代码已删除以简化)

//curve.vue
从“./Autocomplete”导入自动完成
导出默认值{
名称:'曲线',
道具:{
值:对象
},
计算:{
曲线(){返回this.value}
},
组件:{Autocomplete}
}
//自动完成.vue
导出默认值{
名称:“自动完成”,
道具:{
价值:{
类型:字符串,
必填项:true
}
},
计算:{
内容:{
get(){返回this.value},
set(newValue){this.value=newValue}
}
}
}
很多人都得到了同样的警告,我尝试了一些我找到的解决方案,但在我的情况下,我无法使它们工作(使用事件,将Autocomplete的道具类型更改为对象,使用其他计算值,…)


有没有简单的解决办法?我是否应该忽略此警告?

您可以忽略它,一切都会正常工作,但这是一种不好的做法,这是vue告诉您的。如果不遵循单一责任原则,调试代码会困难得多

Vue建议您,只有拥有数据的组件才能修改数据

不确定为什么事件解决方案(
$emit
)在您的情况下不起作用,它会抛出错误还是什么

要消除此警告,还可以使用
.sync
修改器:

您可以尝试使用is代码,按照
prop
->
本地数据
->
$emit local data to prop
在每个组件和组件包装器中流动

ps:$emit('input',…)是v-model绑定的值(在props中)的更新

// curve.vue
<template>
  <autocomplete v-model="curve.y"></autocomplete>
</template>


<script>
  import Autocomplete from './autocomplete'

  export default {
    name: 'Curve',
    props: {
      value: Object
    },
    data() {
      return { currentValue: this.value }
    }
    computed: {
      curve() { return this.currentValue }
    },
    watch: {
      'curve.y'(val) {
        this.$emit('input', this.currentValue);
      }
    },
    components: { Autocomplete }
  }
</script>


// autocomplete.vue
<template>
  <input type="text" v-model="content"/>
</template>

<script>
  export default {
    name: 'Autocomplete',
    props: {
      value: {
        type: String,
        required: true
      }
    },
    data() {
      return { currentValue: this.value };
    },
    computed: {
      content: {
        get() { return this.value },
        set(newValue) {
          this.currentValue = newValue; 
          this.$emit('input', this.currentValue);
        }
      }
    }
  }
</script>
//curve.vue
从“./Autocomplete”导入自动完成
导出默认值{
名称:'曲线',
道具:{
值:对象
},
数据(){
返回{currentValue:this.value}
}
计算:{
曲线(){返回this.currentValue}
},
观察:{
“curve.y”(val){
此.emit('input',此.currentValue);
}
},
组件:{Autocomplete}
}
//自动完成.vue
导出默认值{
名称:“自动完成”,
道具:{
价值:{
类型:字符串,
必填项:true
}
},
数据(){
返回{currentValue:this.value};
},
计算:{
内容:{
get(){返回this.value},
设置(新值){
this.currentValue=newValue;
此.emit('input',此.currentValue);
}
}
}
}

使用
$emit
$on
未引发任何错误,但子项未正确更新。。。但将
v-model
替换为
v-on
,在计算值的设置器中添加
.sync
$emit
!!谢谢!我觉得有点傻,我花了这么多时间在文档中,却没有看到
.sync
…我很感激您在这个Vue.js文档中添加一个引用(加上提到文档作为源代码):以增加您的答案的价值。非常感谢。在文档中:对于要使用v-model的组件,您需要接受一个值属性并发出一个输入事件!!代码墙没有解释为什么警告会警告不良行为。
// curve.vue
<template>
  <autocomplete v-model="curve.y"></autocomplete>
</template>


<script>
  import Autocomplete from './autocomplete'

  export default {
    name: 'Curve',
    props: {
      value: Object
    },
    data() {
      return { currentValue: this.value }
    }
    computed: {
      curve() { return this.currentValue }
    },
    watch: {
      'curve.y'(val) {
        this.$emit('input', this.currentValue);
      }
    },
    components: { Autocomplete }
  }
</script>


// autocomplete.vue
<template>
  <input type="text" v-model="content"/>
</template>

<script>
  export default {
    name: 'Autocomplete',
    props: {
      value: {
        type: String,
        required: true
      }
    },
    data() {
      return { currentValue: this.value };
    },
    computed: {
      content: {
        get() { return this.value },
        set(newValue) {
          this.currentValue = newValue; 
          this.$emit('input', this.currentValue);
        }
      }
    }
  }
</script>