对于跨组件传值,一般使用 vuex,或者 enventbus。事件可以层层传递,也可以通过 watch 监听解决。但这些方法都不是很好,我更希望可以像 react 高阶组件那样写 vue 组件。
查了几个网页之后发现,vue 确实可以使用高阶组件,虽然不如 react 方便,但总算可以实现功能。这篇文章就是记录一下写法。
vue2.4 以后,没有声明的 props 都会在 this.$attrs 里(class 和 style 除外)。所有的事件监听器都会在 this.$listeners 里(native 修饰符除外)。所以,我们就可以方便地使用 v-bind=”$attrs” 和 v-on=”$listeners” 实现跨组件传递属性和事件。
<template> <el-button class="linear-blue-button" v-bind="$attrs" v-on="$listeners"> <slot /> </el-button> </template> <script> export default { name: 'LinearBlueButton' } </script>
使用 linear-blue-button:
<linear-blue-button :loading="loading" @click="handleSearch" >查询</linear-blue-button>
这是使用 template 的写法,在 render 函数里使用 jsx 需要稍微修改一下。另一个例子:
<script> import ChatItemTip from './Tip' import ChatItemText from './Text' export default { name: 'ChatItemCustom', components: { ChatItemTip, ChatItemText }, props: { rawMsg: { type: Object, required: true } }, render() { const { $attrs, $listeners } = this let com = null switch (this.rawMsg._type) { case 'tip': com = ChatItemTip break case 'text': com = ChatItemText break } return com ? <com raw-msg={this.rawMsg} {...{ props: $attrs, on: $listeners }}/> : null } } </script>
$attrs 赋给 props,$listeners 赋给 on。使用 render 函数和 jsx 和 react 就更像了——更自由的 vue。
要注意的是,在 vue3里,$attrs 是赋给 bind。