当有一个el-dialog
在很多组件中都有用到,并且其逻辑一致,这个时候可以考虑把它抽象为一个单独的.vue
文件。但此时组件和组件间无法传递ref
类型,应该如何绑定v-model
来控制组件的开启和关闭呢?使用什么办法给组件传递值呢?
模版引用
如果我们直接使用el-dialog
,一般都是这样:
1 | <script setup lang="ts"> |
我们可以直接操作是否显示。这是因为我们能够合理的使用 openLogic()
。但如果这个组件内部只有一个el-dialog
,即他被整体抽象出来了,我们就没地方执行openLogic()
了。
这个时候就在亲组件里使用模版引用吧。以下是componentDialog.vue
的核心部分:
1 | <script setup lang="ts"> |
向外界暴露了一个open
方法。这个时候,在亲组件parent.vue
里:
1 | <script setup lang="ts"> |
我们通过Vue的模版引用拿到了这个组件的引用。这样就可以执行组件暴露出的方法并完成openLogic()
了。至于关闭,直接在子组件内定义即可。
问题 - ref的时机
假设我的componentDialog.vue
需要一些值,我们一般会想到使用props传递数据。那么当DOM被渲染的时候,组件就会试图拿到parent.vue
中的数据,而这些数据可能在parent.vue
执行一些逻辑后的后续的操作中才被初始化。
我遇到了这个问题,每次我打开parent.vue
,子组件就会立刻被初始化,并且通过未初始化的值向后端发送请求,这导致了一些错误。我下意识的想法是使用v-if
。
然而,模版引用并不是响应式的!ref
只在DOM渲染的时候去获取对应的组件,然而最开始v-if
是false,这就导致引用类型没有正常初始化,因为DOM也没有被渲染。当把v-if
设定为true之后就去使用引用类型,则会报错。因为此时引用类型是undefined
。这个坑对于v-for
也是存在的。
我的解决方案是,仍然沿用问题一的逻辑,子组件暴露的函数需要一些参数,而亲代将需要的数据作为函数参数进行传递,这就推迟了子组件向后端索要数据的时机,从而避免错误。这样就弃用了亲传子常用的props属性。
组件事件
子组件如何通知亲代组件关于某件事情的行为?使用组件事件即可。
子组件可以自定义一些事件,并在合适的时机触发这些事件。亲组件可以自定义一些函数和子组件的事件绑定。当子组件的事件被触发,亲组件相应绑定的函数就会被执行。
举例如下, componentDialog.vue
:
1 | <script> |
parent.vue
1 | <script setup lang="ts"> |
你可以定义很多emit
。这就完成了子传亲的行为。