Javascript 用v型模型改变道具的属性是一种不好的做法吗?

Javascript 用v型模型改变道具的属性是一种不好的做法吗?,javascript,vue.js,vuejs2,vue-component,vuex,Javascript,Vue.js,Vuejs2,Vue Component,Vuex,他们非常严格地说,在组件内部改变道具是不好的做法。此外,还描述了两种情况,其中开发人员可能会试图违反此规则: 设置默认值时 当给定的属性值应该发生变化时 自从我开始使用vue.js以来,我发现自己很想使用v-model更新props属性。搜索网页时,我发现了一些讨论,其中包括解决方法或使用vuex 我的问题是:使用v-model更新道具的属性是正确的还是错误的,因为它改变了父状态。 IMO我想改变父状态,考虑这个例子 Crud组件,用于加载特定的“表单”组件: <template>

他们非常严格地说,在组件内部改变道具是不好的做法。此外,还描述了两种情况,其中开发人员可能会试图违反此规则:

  • 设置默认值时
  • 当给定的属性值应该发生变化时
自从我开始使用vue.js以来,我发现自己很想使用
v-model
更新props属性。搜索网页时,我发现了一些讨论,其中包括解决方法或使用vuex

我的问题是:使用
v-model
更新道具的属性是正确的还是错误的,因为它改变了父状态。 IMO我想改变父状态,考虑这个例子

Crud组件,用于加载特定的“表单”组件:

<template>
    <awesome-form @formSubmit="onFormSubmit" :entity="entity"></awesome-form>
</template>

<script>
import AwesomeForm from 'SomeForm'
export default {
  data () {
    return {
      entity: {}
    }
  },
  components: {
    AwesomeForm
  },
  methods: {
    onFormSubmit () {
      axios.post('/backend', this.entity)
    }
  }
}
</script>
<template>
    <form @submit.prevent="submit">
        <input type="text" name="username" v-model="entity.username" />
        ...
    </form>
</template>
<script>
  export default {
    props: {
      entity: {
        type: Object
      }
    },
    methods: {
      submit () {
        this.$emit('formSubmit')
      }
    }
  }
</script>

从“某种形式”导入某种形式
导出默认值{
数据(){
返回{
实体:{}
}
},
组成部分:{
冬虫夏草
},
方法:{
onFormSubmit(){
axios.post('/backend',this.entity)
}
}
}
特定表单组件:

<template>
    <awesome-form @formSubmit="onFormSubmit" :entity="entity"></awesome-form>
</template>

<script>
import AwesomeForm from 'SomeForm'
export default {
  data () {
    return {
      entity: {}
    }
  },
  components: {
    AwesomeForm
  },
  methods: {
    onFormSubmit () {
      axios.post('/backend', this.entity)
    }
  }
}
</script>
<template>
    <form @submit.prevent="submit">
        <input type="text" name="username" v-model="entity.username" />
        ...
    </form>
</template>
<script>
  export default {
    props: {
      entity: {
        type: Object
      }
    },
    methods: {
      submit () {
        this.$emit('formSubmit')
      }
    }
  }
</script>

...
导出默认值{
道具:{
实体:{
类型:对象
}
},
方法:{
提交(){
此.$emit('formSubmit')为
}
}
}
这与预期的一样,使数据绑定非常容易。但我想这被认为是不好的,因为它更新了父状态。但最终这正是我想要的

这真的很糟糕吗?还有什么替代方案

  • 为每个更新和单个属性设置事件(超级冗余)
  • 始终使用vuex。。。(真的吗?)

我发现您的最佳实践是使用
.sync
修饰符,如中所述:

//忽略以下两行,它们只是在“运行代码段”中禁用警告
Vue.config.devtools=false;
Vue.config.productionTip=false;
Vue.component('awesome-form'{
道具:[“实体”],
模板:`
`,
方法:{
提交(){
此.$emit('form-submit')
}
}
})
新Vue({
el:“应用程序”,
数据(){
返回{
实体:{
用户名:“”,
电子邮件:“”
}
}
},
方法:{
onFormSubmit(){
console.log(this.entity)
}
}
});

{{entity}}

使用v-model更新道具的属性是正常的还是错误的,因为它改变了父状态

当然这很糟糕,因为表单道具在顶级父级上作为
props
传递。所以,即使使用
v-model
,当您试图更改child中的值时,也应该会看到Vue发出的警告

所以当我看到某个表单组件时,我希望它需要一些值,如
v-model
,因为表单是关于编辑某些内容的。这是基于
v-model
的动态表单的示例思想:

Vue.component('awesome-form'{
道具:['value'],
模板:`#很棒的表单模板`,
方法:{
更新(键,val){
//我们应该在每次更改时创建新对象
让updatedCopy=Object.assign({},this.value,{[key]:val});
此.$emit('input',updatedCopy)
}
},
观察:{
价值(val){
log('值更新:'+JSON.stringify(val))
}
}
})
var vm=新的Vue({
el:“#应用程序”,
数据:{
表格:{
text1:'123',
文本2:'345'
}
},
方法:{
提交(){
console.log('submitted!');
}
}
})

提交

请在Vue论坛中查看此项和此项感谢您的反馈@BoussadjraBrahim。链接讨论的特点似乎只是对道具进行变异,而不是对道具的属性进行变异。当必须为每个可能的属性设置事件/侦听器时,代码将非常庞大,但收效甚微(或者我确实没有抓住要点)。还感谢指向的指针,它似乎与问题有关。当我在写我的答案时,我尝试了,但没有成功,之后我发现
sync
修饰符可以适合您的用例。非常感谢您的反馈。这看起来和我想要的解决方案一模一样。我仍然很好奇当不使用
.sync
时到底会发生什么。我猜父组件中的实体将不知道任何更新?我猜父组件中的实体将不知道任何更新是什么意思?对不起,我不清楚。我的意思是:代码甚至可以在不使用
sync
修饰符的情况下工作。我在思考使用和不使用
sync
的区别。我猜这是关于通知道具一个变化。我将不得不进一步研究这个问题。但看起来这是最干净的了。再次感谢你<代码>同步
修改器出现在2.3版中,用于解决双向绑定的问题,如所解释的那样,这是一个干净的代码感谢您的宝贵输入和解决方案,以克服通用或生成模型的限制。事实上,当更新道具的属性时,我没有看到警告,因为这似乎很难在编译时检测到。你说我的尝试是不好的做法是非常受欢迎的。在我的用例中,我将一个对象交给几个组件,比如向导。每个步骤都以不同的方式修改此对象。由于关系非常明确,我觉得vuex商店对于这种常见场景来说似乎太麻烦了。现在看来,
sync
似乎是一条可行之路。是的,在这种情况下,将道具传递给孩子们-
sync
解决方案可能更合适。Vuex允许您在嵌套级别较大的孩子时避免“道具地狱”,并且通过所有级别将道具交付给一些底层孩子可能是一件痛苦的事情(如果您希望您的应用程序将随着新组件的增长而增长,这也是一种解决方案)。祝你好运:)再次感谢你的回复。这绝对有道理。我真的很高兴所有富有成效和有益的见解。