问题
I feel that impossible to pass data from child to parent without @- click event or events or input fields or something need to interaction just on load pass data from child data variable to parent in another data variable by using variable and control in this data from the parent variable, just on load, it’s possible?
Pass JSON data from child to parent and control it from the parent
something like this
```
//child.vue
<template>
<div>
{{getData}}
</div>
</template>
<script>
export default {
name: 'Contributors', // this is the name of the component
data () {
return {
getData: null
}
},
mounted () {
this.$http
.get('https://api.github.com/repos/moumen-soliman/frontend-helper/stats/contributors')
.then(response => (this.getData = response.data.reverse()))
.catch(error => console.log(error.response))
}
}
</script>
app.vue
<template>
<div id="app">
<contributors /> //here just pass json data but I can't control it or make it equal variable in app.vue
{{appGetData}} // i need to make it data equal current variable in parent data
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
appGetData: contributors.getData // I need something like this
}
}
}
</script>
```
回答1:
@event is the preferred way.
I've done this in the past by passing a function as a prop, but this is an antipattern, and should be avoided. Anyway that warning aside, here's how you could do it.
// child.vue
<template>
<div>
{{getData}}
</div>
</template>
<script>
export default {
name: 'Contributors', // this is the name of the component
data () {
return {
getData: null
}
},
props: {
setAppGetData: {
type: Function,
},
},
mounted () {
this.$http
.get('https://api.github.com/repos/moumen-soliman/frontend-helper/stats/contributors')
.then(response => (this.getData = response.data.reverse()))
.then(() => (this.setAppGetData(this.getData) ) // run function here
.catch(error => console.log(error.response))
},
}
</script>
// app.vue
<template>
<div id="app">
<contributors :setAppGetData="setAppGetData"/> //here just pass json data but I can't control it or make it equal variable in app.vue
{{appGetData}} // i need to make it data equal current variable in parent data
</div>
</template>
<script>
export default {
name: 'App',
data () {
return {
appGetData: null // I need something like this
}
},
methods: {
setAppGetData (data) {
this.appGetData = data
}
}
}
</script>
But it seems to me that in this case, a listener may still work better and be easier. You can just add another then
or use an internal watch
to trigger that event
one more then
mounted () {
this.$http
.get('https://api.github.com/repos/moumen-soliman/frontend-helper/stats/contributors')
.then(response => (this.getData = response.data.reverse()))
.then(() => (this.$emit('dataLoaded', this.getData) ) // emit data
.catch(error => console.log(error.response))
},
using watch
watch: {
getData(newValue) {
this.$emmit('dataUpdated', newValue)
}
},
回答2:
You can use sync
for this. Here's the flow:
In your parent, sync
the appGetData
property and bind it to the child component:
<contributors :app-get-data:sync="appGetData"/>
Now in our child component we can just emit this back:
this.$emit('update:appGetData', response.data.reverse())
And we can modify the child to use a property
and not data:
Props: ['appGetData']
Now your child can just pass that prop to the template:
{{ appGetData }}
And you have cohesive 2 way data synchronization where the parent is the single source of truth.
回答3:
Probably you want to try provide/inject.
But pay an attention on:
Note: the provide and inject bindings are NOT reactive. This is intentional. However, if you pass down an observed object, properties on that object do remain reactive.
Below is one simple demo (parent component provide its instance to child, then children add its data to one data property of parent component):
Vue.config.productionTip = false
let test = Vue.component('v-child', {
template: `<div><button @click="getData()">Get Data</button>I am child: {{internalData}}</div>`,
inject: {
_test: {
default() {
console.log('child must be inside one parent')
}
}
},
data() {
return {
internalData: {}
}
},
methods: {
getData: function () {
setTimeout(()=>{
this.internalData = {value: 'Puss In Boots'}
this.$set(this._test.$data.childrenData, this._test.$data.childrenData.length, this.internalData)
}, 1500)
}
}
})
Vue.component('v-parent', {
template: `<div><h2><button @click="changeData()">Next</button>Parent: {{childrenData}}</h2><hr><slot></slot></div>`,
provide () {
return {
_test: this
}
},
data() {
return {
childrenData: []
}
},
methods: {
changeData: function () {
if(this.childrenData.length>0) {
this.$set(this.childrenData[this.childrenData.length-1], 'value', 'So funny...')
} else {
console.log('Empty...')
}
}
}
})
new Vue({
el: '#app'
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<v-parent><v-child></v-child></v-parent>
</div>
回答4:
To pass values from Child component to Parent component you can use the Sync Modifier. Here's the Vue documentation for the same link
Here's what you can do to achieve the desired result:
In the parent, while passing a prop to your Child component, bind it using the .sync
as shown below
<contributors :appGetData.sync="appGetData"/>
Now, in the Child componet you can $emit
the updated appGetData
using the below code:
this.$emit('update:appGetData', response.data.reverse())
来源:https://stackoverflow.com/questions/52118421/pass-data-from-child-to-parent-without-events-just-on-load-it-s-possible-on-vue