在使用element-ui的table组件时,想全局配置一个空数据状态,重复写十分蛋疼。
试了下用函数式组件,算是假装实现了一波继承。

在后面开发的过程中,发现想改个prop的默认值,不想每次用组件的时候都写一次去改,于是弄出下面的改进版,针对props也可以做修改,这样继承就更完善了

函数式组件,extends

  1. import { Table } from 'element-ui'
  2. const emptyComp = (h, text) => {
  3. const emptyTip = text || '暂无数据'
  4. return h('div', {
  5. slot: 'empty'
  6. }, [
  7. h('div', null, emptyTip)
  8. ])
  9. }
  10. const myTable = {
  11. props: {
  12. stripe: {
  13. type: Boolean,
  14. default: true
  15. }
  16. },
  17. extends: Table
  18. // 继承element-ui的table
  19. // 覆盖了table默认prop,根据extends的描述,配置将会合并
  20. }
  21. export default {
  22. functional: true,
  23. render: function (h, context) {
  24. const childNode = [...context.children, emptyComp(h, context.props.emptyTxt)]
  25. return h(myTable, context.data, childNode)
  26. }
  27. }

函数式组件,修改attrs

  1. import { Dialog } from 'element-ui'
  2. // 修改attrs,用assign来赋默认值
  3. // 注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接收 prop,则 props 选项是必须的。
  4. // 在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的 attribute 都会被自动隐式解析为 prop。
  5. // 这就是为什么我直接放在attrs里,也可以当props用的原因
  6. export default {
  7. functional: true,
  8. render (h, context) {
  9. context.data.attrs = Object.assign({
  10. closeOnClickModal: false,
  11. closeOnPressEscape: false
  12. }, context.data.attrs)
  13. return h(
  14. Dialog,
  15. context.data,
  16. context.children
  17. )
  18. }
  19. }

普通组件,extends

普通的render模式仍然会产生一层template,要用ref的方式去调用组件内部方法就比较尴尬了

  1. import { Table } from 'element-ui'
  2. const emptyComp = (h, text) => {
  3. const emptyTip = text || '暂无数据'
  4. return h('div', {
  5. slot: 'empty'
  6. }, [
  7. h('div', null, emptyTip)
  8. ])
  9. }
  10. const myTable = {
  11. props: {
  12. stripe: {
  13. type: Boolean,
  14. default: true
  15. }
  16. },
  17. extends: Table
  18. // 继承element-ui的table
  19. // 覆盖了table默认prop,根据extends的描述,配置将会合并
  20. }
  21. export default {
  22. render: function (h) {
  23. const slots = Object.keys(this.$slots)
  24. .reduce((arr, key) => arr.concat(this.$slots[key]), [])
  25. .map(vnode => {
  26. vnode.context = this._self
  27. return vnode
  28. })
  29. // 展开$slots为数组,并插入自己需要的插槽
  30. slots.push(emptyComp(h, this.emptyTxt))
  31. return h(myTable, {
  32. listeners: this.$listeners,
  33. props: this.$props,
  34. scopedSlots: this.$scopedSlots,
  35. attrs: this.$attrs
  36. }, slots)
  37. }
  38. }

函数式组件针对hooks的优雅写法,还没想到应用场景

  1. export default {
  2. functional: true,
  3. render (h, { parent, children }) {
  4. if (parent._isMounted) {
  5. return children
  6. } else {
  7. parent.$once('hooks:mounted', () => {
  8. parent.$forceUpdate()
  9. })
  10. }
  11. }
  12. }