vue jsx 写法跨组件传值/事件

对于跨组件传值,一般使用 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。