Tree.jsx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* eslint-disable */
  2. import warning from 'warning'
  3. import { Tree as VcTree, TreeNode } from '../vc-tree'
  4. import animation from 'ant-design-vue/es/_util/openAnimation'
  5. import PropTypes from 'ant-design-vue/es/_util/vue-types'
  6. import {
  7. initDefaultProps,
  8. getOptionProps,
  9. filterEmpty,
  10. getComponentFromProp,
  11. getListeners
  12. } from 'ant-design-vue/es/_util/props-util'
  13. import { cloneElement } from 'ant-design-vue/es/_util/vnode'
  14. import { ConfigConsumerProps } from 'ant-design-vue/es/config-provider/configConsumerProps'
  15. import Icon from 'ant-design-vue/es/icon'
  16. import './style';
  17. function TreeProps () {
  18. return {
  19. showLine: PropTypes.bool,
  20. /** 是否支持多选 */
  21. multiple: PropTypes.bool,
  22. /** 是否自动展开父节点 */
  23. autoExpandParent: PropTypes.bool,
  24. /** checkable状态下节点选择完全受控(父子节点选中状态不再关联) */
  25. checkStrictly: PropTypes.bool,
  26. /** 是否支持选中 */
  27. checkable: PropTypes.bool,
  28. /** 是否禁用树 */
  29. disabled: PropTypes.bool,
  30. /** 默认展开所有树节点 */
  31. defaultExpandAll: PropTypes.bool,
  32. /** 默认展开对应树节点 */
  33. defaultExpandParent: PropTypes.bool,
  34. /** 默认展开指定的树节点 */
  35. defaultExpandedKeys: PropTypes.array,
  36. /** (受控)展开指定的树节点 */
  37. expandedKeys: PropTypes.array,
  38. /** (受控)选中复选框的树节点 */
  39. checkedKeys: PropTypes.oneOfType([
  40. PropTypes.array,
  41. PropTypes.shape({
  42. checked: PropTypes.array,
  43. halfChecked: PropTypes.array
  44. }).loose
  45. ]),
  46. /** 默认选中复选框的树节点 */
  47. defaultCheckedKeys: PropTypes.array,
  48. /** (受控)设置选中的树节点 */
  49. selectedKeys: PropTypes.array,
  50. /** 默认选中的树节点 */
  51. defaultSelectedKeys: PropTypes.array,
  52. selectable: PropTypes.bool,
  53. /** 展开/收起节点时触发 */
  54. // onExpand: (expandedKeys: string[], info: AntTreeNodeExpandedEvent) => void | PromiseLike<any>,
  55. /** 点击复选框触发 */
  56. // onCheck: (checkedKeys: string[] | { checked: string[]; halfChecked: string[] }, e: AntTreeNodeCheckedEvent) => void,
  57. /** 点击树节点触发 */
  58. // onSelect: (selectedKeys: string[], e: AntTreeNodeSelectedEvent) => void,
  59. /** 单击树节点触发 */
  60. // onClick: (e: React.MouseEvent<HTMLElement>, node: AntTreeNode) => void,
  61. /** 双击树节点触发 */
  62. // onDoubleClick: (e: React.MouseEvent<HTMLElement>, node: AntTreeNode) => void,
  63. /** filter some AntTreeNodes as you need. it should return true */
  64. filterAntTreeNode: PropTypes.func,
  65. /** 异步加载数据 */
  66. loadData: PropTypes.func,
  67. loadedKeys: PropTypes.array,
  68. // onLoaded: (loadedKeys: string[], info: { event: 'load', node: AntTreeNode; }) => void,
  69. /** 响应右键点击 */
  70. // onRightClick: (options: AntTreeNodeMouseEvent) => void,
  71. /** 设置节点可拖拽(IE>8) */
  72. draggable: PropTypes.bool,
  73. // /** 开始拖拽时调用 */
  74. // onDragStart: (options: AntTreeNodeMouseEvent) => void,
  75. // /** dragenter 触发时调用 */
  76. // onDragEnter: (options: AntTreeNodeMouseEvent) => void,
  77. // /** dragover 触发时调用 */
  78. // onDragOver: (options: AntTreeNodeMouseEvent) => void,
  79. // /** dragleave 触发时调用 */
  80. // onDragLeave: (options: AntTreeNodeMouseEvent) => void,
  81. // /** drop 触发时调用 */
  82. // onDrop: (options: AntTreeNodeMouseEvent) => void,
  83. showIcon: PropTypes.bool,
  84. icon: PropTypes.func,
  85. switcherIcon: PropTypes.any,
  86. prefixCls: PropTypes.string,
  87. filterTreeNode: PropTypes.func,
  88. openAnimation: PropTypes.any,
  89. treeNodes: PropTypes.array,
  90. treeData: PropTypes.array,
  91. /**
  92. * @default{title,key,children}
  93. * 替换treeNode中 title,key,children字段为treeData中对应的字段
  94. */
  95. replaceFields: PropTypes.object,
  96. blockNode: PropTypes.bool
  97. }
  98. }
  99. export { TreeProps }
  100. export default {
  101. name: 'ATree',
  102. model: {
  103. prop: 'checkedKeys',
  104. event: 'check'
  105. },
  106. props: initDefaultProps(TreeProps(), {
  107. checkable: false,
  108. showIcon: false,
  109. openAnimation: {
  110. on: animation,
  111. props: { appear: null }
  112. },
  113. blockNode: false
  114. }),
  115. inject: {
  116. configProvider: { default: () => ConfigConsumerProps }
  117. },
  118. created () {
  119. warning(
  120. !('treeNodes' in getOptionProps(this)),
  121. '`treeNodes` is deprecated. please use treeData instead.'
  122. )
  123. },
  124. TreeNode,
  125. methods: {
  126. renderSwitcherIcon (prefixCls, switcherIcon, { isLeaf, expanded, loading }) {
  127. const { showLine } = this.$props
  128. if (loading) {
  129. return <Icon type="loading" class={`${prefixCls}-switcher-loading-icon`} />
  130. }
  131. if (isLeaf) {
  132. return showLine ? <Icon type="file" class={`${prefixCls}-switcher-line-icon`} /> : null
  133. }
  134. const switcherCls = `${prefixCls}-switcher-icon`
  135. if (switcherIcon) {
  136. return cloneElement(switcherIcon, {
  137. class: {
  138. [switcherCls]: true
  139. }
  140. })
  141. }
  142. return showLine ? (
  143. <Icon
  144. type={expanded ? 'minus-square' : 'plus-square'}
  145. class={`${prefixCls}-switcher-line-icon`}
  146. theme="outlined"
  147. />
  148. ) : (
  149. <Icon type="caret-down" class={switcherCls} theme="filled" />
  150. )
  151. },
  152. updateTreeData (treeData) {
  153. const { $slots, $scopedSlots } = this
  154. const defaultFields = { children: 'children', title: 'title', key: 'key' }
  155. const replaceFields = { ...defaultFields, ...this.$props.replaceFields }
  156. return treeData.map(item => {
  157. const key = item[replaceFields.key]
  158. const children = item[replaceFields.children]
  159. const { on = {}, slots = {}, scopedSlots = {}, class: cls, style, ...restProps } = item
  160. const treeNodeProps = {
  161. ...restProps,
  162. icon: $scopedSlots[scopedSlots.icon] || $slots[slots.icon] || restProps.icon,
  163. switcherIcon:
  164. $scopedSlots[scopedSlots.switcherIcon] ||
  165. $slots[slots.switcherIcon] ||
  166. restProps.switcherIcon,
  167. title:
  168. $scopedSlots[scopedSlots.title] ||
  169. $slots[slots.title] ||
  170. restProps[replaceFields.title],
  171. dataRef: item,
  172. on,
  173. key,
  174. class: cls,
  175. style
  176. }
  177. if (children) {
  178. return { ...treeNodeProps, children: this.updateTreeData(children) }
  179. }
  180. return treeNodeProps
  181. })
  182. },
  183. getCheckedKeys () {
  184. return this.$refs.tree.getCheckedKeys()
  185. },
  186. clearExpandedKeys () {
  187. return this.$refs.tree.clearExpandedKeys()
  188. },
  189. getHalfCheckedKeys () {
  190. return this.$refs.tree.getHalfCheckedKeys()
  191. }
  192. },
  193. render () {
  194. const props = getOptionProps(this)
  195. const { $slots, $scopedSlots } = this
  196. const { prefixCls: customizePrefixCls, showIcon, treeNodes, blockNode } = props
  197. const getPrefixCls = this.configProvider.getPrefixCls
  198. const prefixCls = getPrefixCls('tree', customizePrefixCls)
  199. const switcherIcon = getComponentFromProp(this, 'switcherIcon')
  200. const checkable = props.checkable
  201. let treeData = props.treeData || treeNodes
  202. if (treeData) {
  203. treeData = this.updateTreeData(treeData)
  204. }
  205. const vcTreeProps = {
  206. props: {
  207. ...props,
  208. prefixCls,
  209. checkable: checkable ? <span class={`${prefixCls}-checkbox-inner`} /> : checkable,
  210. children: filterEmpty($scopedSlots.default ? $scopedSlots.default() : $slots.default),
  211. __propsSymbol__: Symbol(),
  212. switcherIcon: nodeProps => this.renderSwitcherIcon(prefixCls, switcherIcon, nodeProps)
  213. },
  214. on: getListeners(this),
  215. ref: 'tree',
  216. class: {
  217. [`${prefixCls}-icon-hide`]: !showIcon,
  218. [`${prefixCls}-block-node`]: blockNode
  219. }
  220. }
  221. if (treeData) {
  222. vcTreeProps.props.treeData = treeData
  223. }
  224. return <VcTree {...vcTreeProps} />
  225. }
  226. }