Vue父组件如何获取动态创建的多个子组件的数据
解决方案
你的问题核心是手动扩展挂载的组件没有被父组件的模板渲染逻辑识别,因此不会被自动收集到$refs中。这里提供两种更易维护的实现方案,优先推荐第一种符合Vue声明式设计的方案。
方案1:使用列表渲染实现动态组件(推荐)
放弃手动操作DOM挂载组件的逻辑,改用Vue原生的列表渲染能力实现,所有组件实例会被自动管理:
第一步:父组件新增数据源
父组件的data中新增数组用于存储所有高中条目的初始数据:
export default { components: { HighSchoolComponent }, data() { return { // 存储所有高中条目,默认可以放一个空条目初始化 highSchoolList: [ { id: 1, name: '', town: '', fos: '', start: '', end: '' } ] } }, // ...其他逻辑 }
第二步:修改父组件模板,用v-for渲染子组件
直接在模板中遍历数组渲染子组件,ref绑定到循环的组件上:
<div> <br> <div id="high_school_data_holder"> <resume-high-school-component v-for="(item, index) in highSchoolList" :key="item.id" :id="item.id" :name="item.name" :town="item.town" :fos="item.fos" :start="item.start" :end="item.end" ref="high_school_data" ></resume-high-school-component> </div> <button class="add" @click="newHighSchoolComponent"> <img src="/img/plus.svg" style="width: 1.2rem;"> </button> </div>
第三步:修改新增组件方法
点击按钮仅需要往数组中新增空的条目即可,Vue会自动渲染新的子组件:
methods: { newHighSchoolComponent() { const newId = this.highSchoolList.length + 1 this.highSchoolList.push({ id: newId, name: '', town: '', fos: '', start: '', end: '' }) }, // 获取所有子组件数据的方法 getHighSchoolData() { // 此时this.$refs.high_school_data是所有子组件实例的数组 return this.$refs.high_school_data.map(item => item.$data) } }
方案2:保留手动挂载逻辑,自行维护组件实例数组
如果不需要调整现有挂载逻辑,可以在父组件中自行维护实例数组,不需要操作DOM获取值:
第一步:父组件新增实例存储数组
data() { return { highSchoolInstances: [] } }
第二步:创建实例后存入数组
methods: { newHighSchoolComponent() { const HighSchoolCtor = Vue.extend(HighSchool); const vm = new HighSchoolCtor({}); vm.$mount(); $("#high_school_data_holder").append(vm.$el); // 把组件实例存入数组 this.highSchoolInstances.push(vm) }, // 获取数据直接遍历实例数组 getHighSchoolData() { return this.highSchoolInstances.map(item => item.$data) } }
原方案问题说明
你之前拿不到$refs是因为$refs仅会收集模板中声明的元素/组件,手动挂载到DOM的组件没有走父组件的模板编译流程,父组件不会自动识别并把它加入$refs集合。用操作DOM拿表单值的方式完全脱离了Vue的响应式能力,后续如果要加校验、数据联动等需求会非常难维护,优先推荐方案1实现。
内容的提问来源于stack exchange,提问作者Paulis
相关产品推荐
相关产品推荐

