vue.js docs相当严格,说对组件内部的props进行突变是不好的做法。此外,还描述了两种情况,在这种情况下,开发人员可能会想违反此规则:
自从vue.js开始以来,我发现自己很想使用v-model
更新props属性。在网上搜索时,我发现了一些讨论,其中包括解决方法或使用vuex。
我的问题是:正在使用v-model
更新道具的属性,还是不好,因为它会更改父状态。
我想改变父母的状态,考虑这个例子
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>
这与预期的工作原理相同,并且使数据绑定超级容易。但是我猜这被认为是不好的,因为它会更新父状态。但是最终,这正是我想要的。
这真的很糟糕吗?还有哪些替代方案?
答案 0 :(得分:2)
我发现您的最佳做法是使用official docs
中提到的// ignore the following two lines, they just disable warnings in "Run code snippet"
Vue.config.devtools = false;
Vue.config.productionTip = false;
Vue.component('awesome-form', {
props: ['entity'],
template: `
<div>
<form @submit.prevent="submit">
<input type="text" class="form-control" name="username" v-model="entity.username">
<input type="email" class="form-control" name="email" v-model="entity.email">
<input type="submit" class="btn btn-primary" value="submit"/>
</form>
</div>`,
methods: {
submit() {
this.$emit('form-submit')
}
}
})
new Vue({
el: "#app",
data() {
return {
entity: {
username: '',
email: ''
}
}
},
methods: {
onFormSubmit() {
console.log(this.entity)
}
}
});
修饰符:
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<div id="app">
<awesome-form @form-submit="onFormSubmit" :entity.sync="entity"></awesome-form>
<p> {{entity}}</p>
</div>
data.table
答案 1 :(得分:2)
正在使用v-model OK更新道具的属性,或者因为它会更改父状态而为错误
绝对不好,因为表单道具以props
的形式在顶级父级上传递。因此,即使尝试使用v-model
更改子级中的值,也应该从Vue看到警告。
因此,当我看到某个表单组件时,我希望它需要一些v-model
值,因为表单是关于编辑某些内容的。这是基于v-model
的动态形式的示例示例:
Vue.component('awesome-form', {
props: ['value'],
template: `#awesome-form-template`,
methods: {
update(key, val) {
// we should create new object on each change
let updatedCopy = Object.assign({}, this.value, { [key]: val });
this.$emit('input', updatedCopy)
}
},
watch: {
value(val) {
console.log('value updated: ' + JSON.stringify(val))
}
}
})
var vm = new Vue({
el: '#app',
data: {
form: {
text1: '123',
text2: '345'
}
},
methods: {
submit() {
console.log('submitted!');
}
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<awesome-form @form-submit="submit" v-model="form"></awesome-form>
</div>
<script type="text/x-template" id='awesome-form-template'>
<form @submit.prevent="$emit('form-submit')">
<div v-for="(val, key) in value" :key="key">
<input
type="text"
:value="value[key]"
@input="update(key, $event.target.value)"
:name="key">
</div>
<button type='submit'>Submit</button>
</form>
</script>
对于每个更新和单个属性都具有事件(超级冗余)
但是,如果您需要添加一些特定于每个输入的验证逻辑,则必须为每次更新或类似操作定义事件。
您还可以使用自定义mixin jsfiddle从问题评论(@BoussadjraBrahim)中基于sync
修饰符检查解决方案,它可以根据您的情况进行灵活调整。