一、$attrs、$props、$listeners 

$attrs:当前组件的属性,通俗的讲也就是在组件标签定义的一系列属性,如input的value,placeholder等,但是不包括在当前组件里面定义的props属性

$listeners:当前组件监听的事件,通俗的讲也就是在使用组件的时候在标签中定义的事件,如@input,以及一些自定义事件@tempFn等

$props:当前组件从父组件那里接收的参数,通俗的讲和$attr差不多,但是只包括在当前组件中定义了的props属性。Vue 实例代理了对其 props 对象 property 的访问。

$data:Vue 实例观察的数据对象。Vue 实例代理了对其 data 对象 property 的访问。

$scopedSlots:用来访问作用域插槽。对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。

通俗的讲:$attr + $props = 在使用组件时定义得所有属性,不包含事件。

那么在当前组件中使用v-bind="$attrs",v-bind="$props",v-on="$listeners"也就是把之前父组件那里给它的属性再全部传到它的子组件。

二、如何在 render 中使用

由于 render 函数中没有 v-bind、v-on 等内置指令,因此我们将如何使用呢?

render () {
  const props = {
    ...this.$attrs,
    ...this.$props,
  }
  const on = {
    this.$listeners,
  }
  return (
    <a-table
      {...{ props, scopedSlots: { ...this.$scopedSlots } }}
      {...{ on }}
    >
      Object.keys(this.slots).map(name => (<template slot={name}>{this.$slots[name]}</template>))
    </a-table>
  )
}

这里使用了展开运算符,更多详情,请查看:vue 中,如何使用 JSX 语法

三、$scopedSlots

用来访问作用域插槽。对于包括 默认 slot 在内的每一个插槽,该对象都包含一个返回相应 VNode 的函数。vm.$scopedSlots 在使用渲染函数开发一个组件时特别有用。

render () {
  return (
    <a-table
      onChange={this.loadData}
      {...{ scopedSlots: ...this.$scopedSlots }}
    />
  )
}

注意:从 2.6.0 开始,这个 property 有两个变化:

1.作用域插槽函数现在保证返回一个 VNode 数组,除非在返回值无效的情况下返回 undefined。

2.所有的 $slots 现在都会作为函数暴露在 $scopedSlots 中。如果你在使用渲染函数,不论当前插槽是否带有作用域,我们都推荐始终通过 $scopedSlots 访问它们。这不仅仅使得在未来添加作用域变得简单,也可以让你最终轻松迁移到所用插槽都是函数的 Vue3。

listName: [
  { label: '运单号', value: 'taskNo' },
  { label: '状态',
    value: 'status',
    scopedSlots: {
      default: (scope) => {
        return (
          <span>{util.getFormatValue(scope.row.status, putGoodsData.status) || '-'}</span>
        )
      },
    }
  },
],

render (h) {
  return <el-table
    data={this.tableData}
    border>
    {this.listName.map(item => {
      return <el-table-column
        key={item.value}
        prop={item.value}
        label={item.label}
        scopedSlots={item.scopedSlots}
      >
      </el-table-column>
    }
    )}
    <el-table-column
      fixed="right"
      label="操作"
      scopedSlots={this.handleOperation().scopedSlots}>
    </el-table-column>
  </el-table>
}

handleOperation () {
  return {
    scopedSlots: {
      default: (scope) => {
        return (
          <div>
            { scope.row.status === 0 && <el-button type="text" size="small" onClick={_ => this.handleDelete(scope.row)}>删除</el-button>}
          </div>
        )
      },
    },
  }
},

补充:this.$slots

用来访问被插槽分发的内容。每个具名插槽有其相应的 property (例如:v-slot:foo 中的内容将会在 vm.$slots.foo 中被找到)。default property 包括了所有没有被包含在具名插槽中的节点,或 v-slot:default 的内容。

请注意插槽不是响应性的。如果你需要一个组件可以在被传入的数据发生变化时重渲染,我们建议改变策略,依赖诸如 props 或 data 等响应性实例选项。

注意:v-slot:foo 在 2.6 以上的版本才支持。对于之前的版本,你可以使用废弃了的语法

在使用渲染函数书写一个组件时,访问 vm.$slots 最有帮助。更多详情,请查看 vue 官网之 vm.$slots

除了通过 this.$slots  访问静态插槽的内容,每个插槽都是一个 VNode 数组,也可以通过 this.$scopedSlots 访问作用域插槽,每个作用域插槽都是一个返回若干 VNode 的函数:

// $slots
render: function (createElement) {
  // `<div><slot></slot></div>`
  return createElement('div', this.$slots.default)
}
// $scopedSlots
props: ['message'],
render: function (createElement) {
  // `<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

如果要用渲染函数向子组件中传递作用域插槽,可以利用 VNode 数据对象中的 scopedSlots 字段:

render: function (createElement) {
  // `<div><child v-slot="props"><span>{{ props.text }}</span></child></div>`
  return createElement('div', [
    createElement('child', {
      // 在数据对象中传递 `scopedSlots`
      // 格式为 { name: props => VNode | Array<VNode> }
      scopedSlots: {
        default: function (props) {
          return createElement('span', props.text)
        }
      }
    })
  ])
}

 

Logo

前往低代码交流专区

更多推荐