文章目录
- 背景
- v-for 循环创建子组件
- 组件封装
- 启示录
背景
前端开发过程中,需要动态添加操作面板,而操作面板可以封装成独立的组件,被父组件引用。比如这个添加收货信息的场景,父组件中可以添加多个收货地址:
要实现在父组件中动态添加组件的功能有哪些技术点呢?本文来讨论一下这个简单场景里面的技术要点。
v-for 循环创建子组件
显然,父组件应该使用 v-for
来创建多个子组件,这里父子组件需要进行双向通信,表现为:
- 编辑操作,父组件回显信息时,需要传递给子组件收货信息;
- 父组件的保存操作,需要收集子组件的数据。
所以呢,要用两种组件通信方式 props
和 $refs
。父组件传递给子组件的 props
数据,虽然只能由父组件修改,但是它也是子组件的数据,子组件可以读取、但不能修改;同时,子组件又需要维护自己的数据,便于子组件编辑。
为了达到双向通信的目的,可以采取的操作如下:
- 子组件维护自己的数据,但数据的初始化是利用
props
完成的; - 父组件使用
v-for
创建子组件时,为每个组件设置ref
属性,通过$refs
获取每个子组件的数据。
这里有个知识点,值得关注,父组件的 v-for
语句中怎么动态设置子组件的 ref
属性呢?
找到的解决方案是使用字符串的占位符号拼接上 index
来设置,例如,创建 N 个 el-button
子组件,且为每个组件设置各自的 ref 名称,代码如下:
<el-button
:key="index"
:ref="`btn${index}`"
v-for="(btn,index) in btns">
{{ btn.name}}
</el-button>
v-for
循环创建子组件常见的一个警告是Component lists rendered with v-for should have explicit keys.
,所以需要绑定这个属性 :key="index"
。
组件封装
封装原型图中的 Child
标记的组件,命名为 AddressPanel
,组件参数有:
参数 | 说明 |
address | 属性:地址 |
postCode | 属性:邮编 |
telephone | 属性:电话 |
panelIndex | 属性:当前面板的编号,remove 事件时需要 |
@addPanel | 事件:添加一个面板,父组件的 panels 添加一个新记录 |
@removePanel | 事件:删除一个面板,移除父组件的 panels[panelIndex] 处的记录 |
AddressPanel
组件定义的伪代码:
props: ['address', 'postCode', 'telephone', 'panelIndex'],
data(){
return {
data:{ //保证能修改数据,使用 props 属性来初始化数据
address:address,
postCode:postCode,
telephone:telephone
}
}
}
父组件引用的伪代码:
<div v-for="(panel, index) in panels">
<address-panel
:address="panel.address"
:postCode="panel.postCode"
:telephone="panel.telephone"
:panelIndex="index"
:ref="`panel${index}`"
</address-panel>
</div>
启示录
本文探讨的是父子组件双向通信的方式,以及 v-for
循环创建子组件时怎么动态设置 ref
属性,都是 Vue
基本的知识点,因为封装一个可以重复动态添加的组件而遇到的问题。
测试动态 ref
时,用了 ElementUI
的在线运行编辑器,可能是国外的服务器,也可能是家里网络太慢,响应时间很是磨人的。这是今天 Vue 学习的内容,又离入门近了一点!