如何在子组件中使用在父组件中使用 Vue.js 更新的数据?
How can I use data in the child component that are updated in parent component using Vue.js?
我的父组件如下所示:
<template>
...
<PaymentMethod/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
...
methods: {
add() {
...
}
}
}
</script>
我的子组件看起来像:
<template>
...
<b-form-select v-model="selected" :options="methodOptions" />
...
<b-form-select v-model="termSelected" :options="termOptions" />
...
</template>
<script>
export default {
data () {
return {
selected: null,
termSelected: null
}
},
...
}
</script>
如果从父组件调用add
方法,我希望它获取在子组件中选择的数据
我该怎么做?
使用 Vuex,您的 store.js 将如下所示:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = {
selected: null
};
const mutations = {
SET_SELECTED(state, selected) {
state.selected =selected;
}
}
export default new Vuex.Store({
state,
mutations
})
在 app.js 中:
import store from './vuex/store';
const app = new Vue({
el: '#app',
store,
...})
在父组件中:
<template>
...
<PaymentMethod :selected="selected" />
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data(){
returen {
selected:null
}
},
methods: {
add() {
...
this.$store.commit("SET_SELECTED",this.selected)
}
}
}
</script>
在子组件中:
<template>
...
<b-form-select @change="selectItem" v-model="selected"
:options="methodOptions" />
...
</template>
<script>
export default {
data () {
return {
selected:null
}
},
methods:{
selectItem(){
this.$store.commit("SET_SELECTED",this.selected
}
...
}
有两种方法:
1.您可以在 child 组件中选择数据时发出事件:
<template>
...
<b-form-select v-model="selected" :options="methodOptions" />
...
</template>
<script>
export default {
data () {
return {
selected: null
}
},
...
methods: {
onSelect() {
this.$emit('selectData', this.selected);
}
}
}
</script>
然后在parent组件中处理这个事件:
<template>
...
<PaymentMethod @selectData="changeChildData($event)"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
...
data() {
return {
childData: null
}
},
methods: {
changeChildData(newData) {
this.childData = newData;
},
add() {
...
}
}
}
</script>
2。或者您可以使用存储 Vuex
或者事件总线(Vuex的简化版):
import Vue from 'vue';
export const EventBus = new Vue();
您将数据从 child 传递到事件总线
<script>
import { EventBus } from '../EventBus.js';
export default {
data () {
return {
selected: null
}
},
...
methods: {
onSelect() {
EventBus.$emit('selectData', this.selected);
}
}
}
</script>
并从 parent 订阅它的变化
<script>
import { EventBus } from '../EventBus.js';
export default {
...
data() {
return {
childData: null
}
},
created() {
EventBus.$on('selectData', (data) => {
this.childData = data;
});
},
methods: {
add() {
...
}
}
}
</script>
最好和推荐的方法是使用 $emit
下面的例子可以告诉你怎么做?
Vue.component('child-tmp', {
props: ['post'],
template: `
<button @click="$emit('add-like')">Like</button>
`
})
new Vue({
el: "#app",
data: {
posts: [{
title: "Heading goes here 1",
content: "Something sadofnd idfidif disong.",
likes: 0
},
{
title: "Heading 2 goes here",
content: "Something sadofnd idfidif disong.",
likes: 0
}],
totalLikes: 0
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<h2>Posts:</h2>
<section>
<div v-for="post in posts">
<h2>
{{post.title}}
</h2>
<p>
{{post.content}}
</p>
<child-tmp v-bind:post="post" v-on:add-like="post.likes = post.likes+1"></child-tmp><span style="margin-left:10px;">{{post.likes}}</span>
</div>
</section>
</div>
在上面的代码片段中,您可以看到我们正在使用 props 从父级读取数据到子级,我们使用 $emit 从子级传递数据,并使用 v-on:add-like 来接收发出的数据。
一种解决方案是使用 sync
修饰符以及计算的 getter 和 setter:
Parent 组件
<template>
...
<PaymentMethod :method.sync="method" :term.sync="term"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data () {
return {
method: null,
term: null
}
},
...
}
</script>
Child 组件
<template>
...
<b-form-select v-model="_method" :options="methodOptions" />
...
<b-form-select v-model="_term" :options="termOptions" />
...
</template>
<script>
export default {
props: ['method', 'term'],
computed: {
_method: {
get () {
return this.method
},
set (value) {
this.$emit('update:method', value)
}
},
_term: {
get () {
return this.term
},
set (value) {
this.$emit('update:term', value)
}
},
},
...
}
</script>
现在,使用 parent 组件的 add
方法,您可以访问 child 的选定 method
和 term
选项:
methods: {
add() {
// this.method is the value of _method
// this.term is the value of _term
}
}
更新
既然你已经声明你想要所选术语/方法的值和文本,我建议进行以下更改:
Parent
<template>
...
<PaymentMethod :methods="methods"
:terms="terms"
:method.sync="method"
:term.sync="term"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data () {
return {
// define your method and term arrays in the parent component.
// pass them as props to the child component.
methods: [{...}, {...}, {...}],
terms: [{...}, {...}, {...}],
method: null,
term: null
}
},
// use computed properties to retrieve the selected method / term option.
computed: {
selectedMethod () {
return this.methods.find(method => method.value === this.method)
},
selectedTerm () {
return this.terms.find(term => term.value === this.term)
},
}
...
}
</script>
Child
<template>
...
<b-form-select v-model="_method" :options="methods" />
...
<b-form-select v-model="_term" :options="terms" />
...
</template>
<script>
export default {
props: ['method', 'term', 'methods', 'terms'],
computed: {
_method: {
get () {
return this.method
},
set (value) {
this.$emit('update:method', value)
}
},
_term: {
get () {
return this.term
},
set (value) {
this.$emit('update:term', value)
}
},
},
...
}
</script>
我的父组件如下所示:
<template>
...
<PaymentMethod/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
...
methods: {
add() {
...
}
}
}
</script>
我的子组件看起来像:
<template>
...
<b-form-select v-model="selected" :options="methodOptions" />
...
<b-form-select v-model="termSelected" :options="termOptions" />
...
</template>
<script>
export default {
data () {
return {
selected: null,
termSelected: null
}
},
...
}
</script>
如果从父组件调用add
方法,我希望它获取在子组件中选择的数据
我该怎么做?
使用 Vuex,您的 store.js 将如下所示:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state = {
selected: null
};
const mutations = {
SET_SELECTED(state, selected) {
state.selected =selected;
}
}
export default new Vuex.Store({
state,
mutations
})
在 app.js 中:
import store from './vuex/store';
const app = new Vue({
el: '#app',
store,
...})
在父组件中:
<template>
...
<PaymentMethod :selected="selected" />
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data(){
returen {
selected:null
}
},
methods: {
add() {
...
this.$store.commit("SET_SELECTED",this.selected)
}
}
}
</script>
在子组件中:
<template>
...
<b-form-select @change="selectItem" v-model="selected"
:options="methodOptions" />
...
</template>
<script>
export default {
data () {
return {
selected:null
}
},
methods:{
selectItem(){
this.$store.commit("SET_SELECTED",this.selected
}
...
}
有两种方法:
1.您可以在 child 组件中选择数据时发出事件:
<template>
...
<b-form-select v-model="selected" :options="methodOptions" />
...
</template>
<script>
export default {
data () {
return {
selected: null
}
},
...
methods: {
onSelect() {
this.$emit('selectData', this.selected);
}
}
}
</script>
然后在parent组件中处理这个事件:
<template>
...
<PaymentMethod @selectData="changeChildData($event)"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
...
data() {
return {
childData: null
}
},
methods: {
changeChildData(newData) {
this.childData = newData;
},
add() {
...
}
}
}
</script>
2。或者您可以使用存储 Vuex
或者事件总线(Vuex的简化版):
import Vue from 'vue';
export const EventBus = new Vue();
您将数据从 child 传递到事件总线
<script>
import { EventBus } from '../EventBus.js';
export default {
data () {
return {
selected: null
}
},
...
methods: {
onSelect() {
EventBus.$emit('selectData', this.selected);
}
}
}
</script>
并从 parent 订阅它的变化
<script>
import { EventBus } from '../EventBus.js';
export default {
...
data() {
return {
childData: null
}
},
created() {
EventBus.$on('selectData', (data) => {
this.childData = data;
});
},
methods: {
add() {
...
}
}
}
</script>
最好和推荐的方法是使用 $emit
下面的例子可以告诉你怎么做?
Vue.component('child-tmp', {
props: ['post'],
template: `
<button @click="$emit('add-like')">Like</button>
`
})
new Vue({
el: "#app",
data: {
posts: [{
title: "Heading goes here 1",
content: "Something sadofnd idfidif disong.",
likes: 0
},
{
title: "Heading 2 goes here",
content: "Something sadofnd idfidif disong.",
likes: 0
}],
totalLikes: 0
}
})
<script src="https://unpkg.com/vue"></script>
<div id="app">
<h2>Posts:</h2>
<section>
<div v-for="post in posts">
<h2>
{{post.title}}
</h2>
<p>
{{post.content}}
</p>
<child-tmp v-bind:post="post" v-on:add-like="post.likes = post.likes+1"></child-tmp><span style="margin-left:10px;">{{post.likes}}</span>
</div>
</section>
</div>
在上面的代码片段中,您可以看到我们正在使用 props 从父级读取数据到子级,我们使用 $emit 从子级传递数据,并使用 v-on:add-like 来接收发出的数据。
一种解决方案是使用 sync
修饰符以及计算的 getter 和 setter:
Parent 组件
<template>
...
<PaymentMethod :method.sync="method" :term.sync="term"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data () {
return {
method: null,
term: null
}
},
...
}
</script>
Child 组件
<template>
...
<b-form-select v-model="_method" :options="methodOptions" />
...
<b-form-select v-model="_term" :options="termOptions" />
...
</template>
<script>
export default {
props: ['method', 'term'],
computed: {
_method: {
get () {
return this.method
},
set (value) {
this.$emit('update:method', value)
}
},
_term: {
get () {
return this.term
},
set (value) {
this.$emit('update:term', value)
}
},
},
...
}
</script>
现在,使用 parent 组件的 add
方法,您可以访问 child 的选定 method
和 term
选项:
methods: {
add() {
// this.method is the value of _method
// this.term is the value of _term
}
}
更新
既然你已经声明你想要所选术语/方法的值和文本,我建议进行以下更改:
Parent
<template>
...
<PaymentMethod :methods="methods"
:terms="terms"
:method.sync="method"
:term.sync="term"/>
...
<b-btn class="float-right" variant="primary" @click="add">
OK
</b-btn>
...
</template>
<script>
export default {
data () {
return {
// define your method and term arrays in the parent component.
// pass them as props to the child component.
methods: [{...}, {...}, {...}],
terms: [{...}, {...}, {...}],
method: null,
term: null
}
},
// use computed properties to retrieve the selected method / term option.
computed: {
selectedMethod () {
return this.methods.find(method => method.value === this.method)
},
selectedTerm () {
return this.terms.find(term => term.value === this.term)
},
}
...
}
</script>
Child
<template>
...
<b-form-select v-model="_method" :options="methods" />
...
<b-form-select v-model="_term" :options="terms" />
...
</template>
<script>
export default {
props: ['method', 'term', 'methods', 'terms'],
computed: {
_method: {
get () {
return this.method
},
set (value) {
this.$emit('update:method', value)
}
},
_term: {
get () {
return this.term
},
set (value) {
this.$emit('update:term', value)
}
},
},
...
}
</script>