从el-table的slot自定义内容里学到的

1,954 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

问题

前几天总结了一篇文章,主要是讲最近项目遇到的问题,然后里面讲了一个使用了el-table的自定义内容遇到的问题。

我再描述下这个问题,就是el-table的自定义内容需要加上slot-scope="scope",才能渲染出自定义内容,不然不会渲染。

<el-table-column label="状态">
  <template slot-scope="scope">
    <el-tag>标签</el-tag>
  </template>
</el-table-column>

因为这个是旧项目,依赖版本一直没有升级,vue2.5.17,elment-ui2.4.8

至于为什么无法渲染,那只能去看看element-uiel-table源码,才能找到原因。

首先去到node-moduleselment-ui目录, 找到package下面的table目录,在src目录下里面有个table-column.js,自定义内容的逻辑就在这个js里面。

自定义的代码如下

image.png

renderCell方法,这个就是渲染单元格的。

_self就是当前组件this,可以看到它用scopedSlots取到自定义的内容。

如果有内容就用自定义内容渲染。

这个scopedSlots很少用。平时用的多的是$slot取自定义内容。这两个有何区别呢?

vue的官方文档有写:

image.png

主要是用来访问作用域插槽。 如果你的插槽不是作用域插槽,则无法访问到。

所以这个就是导致, 如果你的el-table的自定义内容如果不提供作用域插槽,则无法渲染的问题。

但是下面还说了,从2.6.0开始,所有的$slot都会在scopedSlots里面找到,如果不是作用域插槽,也会存在。

那这样说,我只要升级下我的vue版本可以了。

然后我把我的vue升级到2.6以上版本了,运行项目一看,果然,之前没生效的自定义内容已经生效了。

image.png

scopedSlots

那我们再来讲讲scopedSlots

这个scopedSlots主要是用来访问作用域插槽,用在render函数比较多。

如果你平时用的template模板比较多,这个scopedSlots可能就接触的少些。

渲染函数它是用js来渲染html,比template模板更快编译,因为template还得先转成render函数。

但是渲染函数可读性没有template模板好,我们推荐还是使用template模板。

用法

如果你的插槽,是默认插槽,则scopedSlots有个default属性代表默认插槽。

如果你的插槽是有作用域的,则它会以作用域插槽的属性值来代表当前的作用域插槽。

然后这些属性对应的值是函数,执行后会返回虚拟dom,也可以传参数,下面有讲到。

默认插槽

子组件:

// child.vue
export default {
  render (h) {
    return h('div', this.$scopedSlots.default())
  }
 }

父组件:

<child>
  答案cp3
</child>

这个会最终渲染成div,内容是答案cp3

image.png

作用域插槽

子组件:

// child.vue
export default {
  render (h) {
    return h('div', this.$scopedSlots.name())
  }
 }

父组件:

<child>
  <template v-slot:name="scope">答案cp3</template>
</child>

最终也是渲染成div, 内容是答案cp3。但是它是通过$scopedSlots.name作用域插槽访问的。

传参

插槽是可以传参的,从子组件传到父组件,传参后的插槽就变成作用域插槽了。

子组件:

// child.vue
export default {
  data () {
    return {
      name: '答案cp3'
    }
  },
  render (h) {
    return h('div', this.$scopedSlots.name({
      name: this.name
    }))
  }
 }

父组件:

<child>
  <template v-slot:name="scope">{{scope.name}}</template>
</child>

最终也是渲染成div, 内容是答案cp3但是值是从子组件传给父组件的。

要是在vue组件中使用render语法,那就不能提供template,否则render语法不会生效。