VueJS 从父组件访问子组件的数据

我用的是 网络包用 Vue-cli 脚手架

我的 Vue 组件结构/层次结构目前看起来如下:

  • 应用程序
    • PDF 范本
      • 背景资料
      • 动态模板图像
      • 静态模板图像
      • 降价

在应用程序级别,我想要一个 vuejs 组件方法,它可以将所有子组件的数据聚合到一个单独的 JSON 对象中,这个对象可以发送到服务器。

是否有一种方法来访问子组件的数据? 具体来说,多层深度?

如果没有,那么传递可观察的数据/参数的最佳实践是什么,这样当子组件修改它时,我就可以访问新的值?我试图避免组件之间的硬依赖关系,因此到目前为止,使用组件属性传递的唯一内容就是初始化值。

更新:

可靠的回答在回顾了这两个问题的答案后,我发现有用的资源:

138715 次浏览

For this kind of structure It's good to have some kind of Store.

VueJS provide solution for that, and It's called Vuex.If you are not ready to go with Vuex, you can create your own simple store.

Let's try with this

MarkdownStore.js

export default {


data: {
items: []
},


// Methods that you need, for e.g fetching data from server etc.


fetchData() {
// fetch logic
}


}

And now you can use those data everywhere, with importing this Store file

HomeView.vue

import MarkdownStore from '../stores/MarkdownStore'


export default {


data() {
sharedItems: MarkdownStore.data
},


created() {
MarkdownStore.fetchData()
}


}

So that's the basic flow that you could use, If you dont' want to go with Vuex.

what is the best practice for passing down oberservable data/parameters, so that when it's modified by child components I have access to the new values?

The flow of props is one way down, a child should never modify its props directly.

For a complex application, vuex is the solution, but for a simple case vuex is an overkill. Just like what @Belmin said, you can even use a plain JavaScript object for that, thanks to the reactivity system.

Another solution is using events. Vue has already implemented the EventEmitter interface, a child can use this.$emit('eventName', data) to communicate with its parent.

The parent will listen on the event like this: (@update is the shorthand of v-on:update)

<child :value="value" @update="onChildUpdate" />

and update the data in the event handler:

methods: {
onChildUpdate (newValue) {
this.value = newValue
}
}

Here is a simple example of custom events in Vue:
http://codepen.io/CodinCat/pen/ZBELjm?editors=1010

This is just parent-child communication, if a component needs to talk to its siblings, then you will need a global event bus, in Vue.js, you can just use an empty Vue instance:

const bus = new Vue()


// In component A
bus.$on('somethingUpdated', data => { ... })


// In component B
bus.$emit('somethingUpdated', newData)

In my child component, there are no buttons to emit changed data. It's a form with somewhat 5~10 inputs. the data will be submitted once you click the process button in another component. so, I can't emit every property when it's changing.

So, what I did,

In my parent component, I can access child's data from "ref"

e.g

<markdown ref="markdowndetails"></markdown>
<app-button @submit="process"></app-button>


// js
methods:{
process: function(){
// items is defined object inside data()
var markdowns = this.$refs.markdowndetails.items
}
}

Note: If you do this all over the application I suggest move to vuex instead.

you can meke ref to child component and use it as this this.$refs.refComponentName.$data

parent-component

<template>
<section>
<childComponent ref="nameOfRef" />
</section>
</template>


methods: {
save() {
let Data = this.$refs.nameOfRef.$data;
}
},

In my case I have a registration form that I've broken down into components.

As suggested above I used $refs, In my parent I have for example:

In Template:

<Personal ref="personal" />

Script - Parent Component

export default {
components: {
Personal,
Employment
},
data() {
return {
personal: null,
education: null
}
},
mounted: function(){
this.personal = this.$refs.personal.model
this.education = this.$refs.education.model
}
}

This works well as the data is reactive.