render.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import { defineComponent, h } from 'vue'
  2. import { makeMap } from '@/utils/index'
  3. const isAttr = makeMap(
  4. 'accept,accept-charset,accesskey,action,align,alt,async,autocomplete,' +
  5. 'autofocus,autoplay,autosave,bgcolor,border,buffered,challenge,charset,' +
  6. 'checked,cite,class,code,codebase,color,cols,colspan,content,http-equiv,' +
  7. 'name,contenteditable,contextmenu,controls,coords,data,datetime,default,' +
  8. 'defer,dir,dirname,disabled,download,draggable,dropzone,enctype,method,for,' +
  9. 'form,formaction,headers,height,hidden,high,href,hreflang,http-equiv,' +
  10. 'icon,id,ismap,itemprop,keytype,kind,label,lang,language,list,loop,low,' +
  11. 'manifest,max,maxlength,media,method,GET,POST,min,multiple,email,file,' +
  12. 'muted,name,novalidate,open,optimum,pattern,ping,placeholder,poster,' +
  13. 'preload,radiogroup,readonly,rel,required,reversed,rows,rowspan,sandbox,' +
  14. 'scope,scoped,seamless,selected,shape,size,type,text,password,sizes,span,' +
  15. 'spellcheck,src,srcdoc,srclang,srcset,start,step,style,summary,tabindex,' +
  16. 'target,title,type,usemap,value,width,wrap' + 'prefix-icon'
  17. )
  18. const isNotProps = makeMap(
  19. 'layout,prepend,regList,tag,document,changeTag,defaultValue'
  20. )
  21. function useVModel(props, emit) {
  22. return {
  23. modelValue: props.defaultValue,
  24. 'onUpdate:modelValue': (val) => emit('update:modelValue', val),
  25. }
  26. }
  27. const componentChild = {
  28. 'el-button': {
  29. default(h, conf, key) {
  30. return conf[key]
  31. },
  32. },
  33. 'el-select': {
  34. options(h, conf, key) {
  35. return conf.options.map(item => h(resolveComponent('el-option'), {
  36. label: item.label,
  37. value: item.value,
  38. }))
  39. }
  40. },
  41. 'el-radio-group': {
  42. options(h, conf, key) {
  43. return conf.optionType === 'button' ? conf.options.map(item => h(resolveComponent('el-checkbox-button'), {
  44. label: item.value,
  45. }, () => item.label)) : conf.options.map(item => h(resolveComponent('el-radio'), {
  46. label: item.value,
  47. border: conf.border,
  48. }, () => item.label))
  49. }
  50. },
  51. 'el-checkbox-group': {
  52. options(h, conf, key) {
  53. return conf.optionType === 'button' ? conf.options.map(item => h(resolveComponent('el-checkbox-button'), {
  54. label: item.value,
  55. }, () => item.label)) : conf.options.map(item => h(resolveComponent('el-checkbox'), {
  56. label: item.value,
  57. border: conf.border,
  58. }, () => item.label))
  59. }
  60. },
  61. 'el-upload': {
  62. 'list-type': (h, conf, key) => {
  63. const option = {}
  64. // if (conf.showTip) {
  65. // tip = h('div', {
  66. // class: "el-upload__tip"
  67. // }, () => '只能上传不超过' + conf.fileSize + conf.sizeUnit + '的' + conf.accept + '文件')
  68. // }
  69. if (conf['list-type'] === 'picture-card') {
  70. return h(resolveComponent('el-icon'), option, () => h(resolveComponent('Plus')))
  71. } else {
  72. // option.size = "small"
  73. option.type = "primary"
  74. option.icon = "Upload"
  75. return h(resolveComponent('el-button'), option, () => conf.buttonText)
  76. }
  77. },
  78. }
  79. }
  80. const componentSlot = {
  81. 'el-upload': {
  82. 'tip': (h, conf, key) => {
  83. if (conf.showTip) {
  84. return () => h('div', {
  85. class: "el-upload__tip"
  86. }, '只能上传不超过' + conf.fileSize + conf.sizeUnit + '的' + conf.accept + '文件')
  87. }
  88. },
  89. }
  90. }
  91. export default defineComponent({
  92. // 使用 render 函数
  93. render() {
  94. const dataObject = {
  95. attrs: {},
  96. props: {},
  97. on: {},
  98. style: {}
  99. }
  100. const confClone = JSON.parse(JSON.stringify(this.conf))
  101. const children = []
  102. const slot = {}
  103. const childObjs = componentChild[confClone.tag]
  104. if (childObjs) {
  105. Object.keys(childObjs).forEach(key => {
  106. const childFunc = childObjs[key]
  107. if (confClone[key]) {
  108. children.push(childFunc(h, confClone, key))
  109. }
  110. })
  111. }
  112. const slotObjs = componentSlot[confClone.tag]
  113. if (slotObjs) {
  114. Object.keys(slotObjs).forEach(key => {
  115. const childFunc = slotObjs[key]
  116. if (confClone[key]) {
  117. slot[key] = childFunc(h, confClone, key)
  118. }
  119. })
  120. }
  121. Object.keys(confClone).forEach(key => {
  122. const val = confClone[key]
  123. if (dataObject[key]) {
  124. dataObject[key] = val
  125. } else if (isAttr(key)) {
  126. dataObject.attrs[key] = val
  127. } else if (!isNotProps(key)) {
  128. dataObject.props[key] = val
  129. }
  130. })
  131. if(children.length > 0){
  132. slot.default = () => children
  133. }
  134. return h(resolveComponent(this.conf.tag),
  135. {
  136. modelValue: this.$attrs.modelValue,
  137. ...dataObject.props,
  138. ...dataObject.attrs,
  139. style: {
  140. ...dataObject.style
  141. },
  142. }
  143. , slot ?? null)
  144. },
  145. props: {
  146. conf: {
  147. type: Object,
  148. required: true,
  149. },
  150. }
  151. })