我有一个非常简单的父/子组件。我想两种方式都使用子组件-首先用于添加新条目的操作,其次用于更新实体的操作。
我已经构建了以下组件:https://codepen.io/anon/pen/bJdjyx这里我不使用道具,而是使用自定义事件将值从父级同步到子级。
添加-模板:
<div id="app">
<v-app>
<v-content>
<v-container grid-list-xl>
<my-address
:addresscompany.sync="addressCompany"
:addressstreet.sync="addressStreet"
></my-address>
<v-btn @click="submit">Submit</v-btn>
</v-container>
</v-content>
</v-app>
</div>
<script type="text/x-template" id="address-template">
<div>
<v-text-field
name="company"
v-model="addressCompany"
@change="updateCompany()">
</v-text-field>
<v-text-field
name="street"
v-model="addressStreet"
@change="updateStreet()">
</v-text-field>
</div>
</script>
添加-脚本:
let addressComponent = {
template: '#address-template',
data() {
return {
addressCompany: '',
addressStreet: '',
}
},
methods: {
updateCompany () {
this.$emit('update:addresscompany', this.addressCompany);
},
updateStreet () {
this.$emit('update:addressstreet', this.addressStreet);
}
}
};
new Vue({
el: '#app',
components: {'my-address' : addressComponent},
data() {
return {
addressCompany: '',
addressStreet: '',
}
},
methods: {
submit () {
console.log('Company ' + this.addressCompany);
console.log('Street ' + this.addressStreet);
}
}
})
但是该模板不适用于编辑案例,因为我需要道具才能将值传递给子对象。所以我想出了这个:https://codepen.io/anon/pen/zXGLQG
更新-模板:
<div id="app">
<v-app>
<v-content>
<v-container grid-list-xl>
<my-address
:addresscompany.sync="addressCompany"
:addressstreet.sync="addressStreet"
></my-address>
<v-btn @click="submit">Submit</v-btn>
</v-container>
</v-content>
</v-app>
</div>
<script type="text/x-template" id="address-template">
<div>
<v-text-field
name="company"
:value="addressCompany"
@change="updateCompany()">
</v-text-field>
<v-text-field
name="street"
:value="addressStreet"
@change="updateStreet()">
</v-text-field>
</div>
</script>
更新-脚本:
let addressComponent = {
template: '#address-template',
props: ['addressCompany', 'addressStreet'],
data() {
return {
}
},
methods: {
updateCompany () {
this.$emit('update:addresscompany', this.addressCompany);
},
updateStreet () {
this.$emit('update:addressstreet', this.addressStreet);
}
}
};
new Vue({
el: '#app',
components: {'my-address' : addressComponent},
data() {
return {
addressCompany: 'Company',
addressStreet: 'Street',
}
},
methods: {
submit () {
console.log('Company ' + this.addressCompany);
console.log('Street ' + this.addressStreet);
}
}
})
主要区别在于,对于更新情况,我不对子元素使用v模型,因为我无法直接更改道具。但是使用:value时,不会触发更新事件。
那么使用该子组件进行添加和更新的正确方法是什么?在将Vuex用于这些目的之前,必须有一种标准的Vue方式吗?
谢谢!
答案 0 :(得分:0)
我经常使用以下模式:
创建一个作为您的实体抽象的组件,在下面的示例中,我将Person.vue
与firstName
和lastName
道具一起使用。
Vue.component('Person' , {
template: `
<div>
<input type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"/>
<input type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"/>
</div>
`,
props: {
firstName: String,
lastName: String
}
});
此组件的范围严格限于绑定到
Person
对象,对其更改做出反应并更新父对象,并抛出sync
事件修饰符。
接下来,创建一个包装组件,该包装组件将处理实际对象的状态,即Person.js
。它的子组件Person.vue
不在乎您是否处于“添加”或“编辑”模式。该组件仅负责对模型的更改做出反应。
此组件应从API调用或数据存储区加载Person
对象(更新模式),或创建一个新的空对象,即new Person()
(添加模式)。
下面是一个简单的示例,理想情况下,父组件(在这种情况下为app)将被拆分,从而减少了对helper属性的使用。
function Person (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Vue.component('Person' , {
template: `
<div>
<input type="text"
:value="firstName"
@input="$emit('update:firstName', $event.target.value)"/>
<input type="text"
:value="lastName"
@input="$emit('update:lastName', $event.target.value)"/>
</div>
`,
props: {
firstName: String,
lastName: String
}
});
new Vue({
el: '#app',
template: `
<div>
<!-- Add mode, should be its own component -->
<section v-if="promptAdd">
<Person v-bind.sync="newPerson"/>
<button type="button" @click="onAdded">Add</button>
</section>
<!-- Update mode, should be its own component -->
<section v-else>
<p>Users:</p>
<div v-for="(person, index) in arr" :key="index">
<Person v-bind.sync="person"/>
</div>
<button type="button"
@click="addNew">Add New User</button>
</section>
</div>
`,
data: () => ({
promptAdd: false,
newPerson: undefined,
arr: [
new Person('Bob', 'Smith')
]
}),
methods: {
addNew() {
this.newPerson = new Person();
this.promptAdd = true;
},
onAdded () {
this.arr.push({ ...this.newPerson });
this.promptAdd = false;
this.newPerson = undefined;
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app"></div>