13.实战 6:可用 slot-scope 自定义列的表格组件——Table

实战 6:可用 slot-scope 自定义列的表格组件——Table

上一节,我们基于 Render 函数实现了在表格中自定义列模板的组件 Table,虽说 Render 函数能够完全发挥 JavaScript 的编程能力,实现几乎所有的自定义工作,但本质上,使用者写的是一个庞大的 JS 对象,它不具备 DOM 结构,可读性和可维护性都比较差。对于大部分写 Vue.js 的开发者来说,更倾向于使用 template 的语法,毕竟它是 Vue.js 独有的特性。本小节则在上一节的 Table 组件基础上修改,实现一种达到同样渲染效果,但对使用者更友好的 slot-scope 写法。

什么是 slot-scope

slot(插槽)我们都很熟悉,它是 Vue.js 组件的 3 个 API 之一,用于分发内容。那 slot-scope 是什么呢?先来看一个场景,比如某组件拥有下面的模板:

  • {{ book.name }}

使用者传递一个数组 books,由组件内的 v-for 循环显示,这里的 {{ book.name }} 是纯文本输出,如果想自定义它的模板(即内容分发),就要用到 slot,但 slot 只能是固定的模板,没法自定义循环体中的一个具体的项,事实上这跟上一节的 Table 场景是类似的。

常规的 slot 无法实现对组件循环体的每一项进行不同的内容分发,这就要用到 slot-scope,它本质上跟 slot 一样,只不过可以传递参数。比如上面的示例,使用 slot-scope 封装:

  • {{ book.name }}

在 slot 上,传递了一个自定义的参数 book,它的值绑定的是当前循环项的数据 book,这样在父级使用时,就可以在 slot 中访问它了:


  


使用 slot-scope 指定的参数 slotProps 就是这个 slot 的全部参数,它是一个对象,在 slot-scope 中是可以传递多个参数的,上例我们只写了一个参数 book,所以访问它就是 slotProps.book。这里推荐使用 ES6 的解构,能让参数使用起来更方便:


  


除了可以传递参数,其它用法跟 slot 是一样的,比如也可以“具名”:


  {{ book.name }}




这就是作用域 slot(slot-scope),能够在组件的循环体中做内容分发,有了它,Table 组件的自定义列模板就不用写一长串的 Render 函数了。

为了把 Render 函数和 slot-scope 理解透彻,下面我们用 3 种方法来改写 Table,实现 slot-scope 自定义列模板。

方案一

第一种方案,用最简单的 slot-scope 实现,同时也兼容 Render 函数的旧用法。拷贝上一节的 Table 组件目录,更名为 table-slot,同时也拷贝路由,更名为 table-slot.vue。为了兼容旧的 Render 函数用法,在 columns 的列配置 column 中,新增一个字段 slot 来指定 slot-scope 的名称:




相比原先的文件,只在 'render' in col 的条件下新加了一个 template 的标签,如果使用者的 column 配置了 render 字段,就优先以 Render 函数渲染,然后再判断是否用 slot-scope 渲染。在定义的作用域 slot 中,将行数据 row、列数据 column 和第几行 index 作为 slot 的参数,并根据 column 中指定的 slot 字段值,动态设置了具名 name。使用者在配置 columns 时,只要指定了某一列的 slot,那就可以在 Table 组件中使用 slot-scope。我们以上一节的可编辑整行数据为例,用 slot-scope 的写法实现完全一样的效果:





示例中在 内的每一个