mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-11-30 11:08:00 +08:00
add vc-tree
This commit is contained in:
parent
388adbac35
commit
8e6dd94107
72
components/vc-tree/demo/animation.vue
Normal file
72
components/vc-tree/demo/animation.vue
Normal file
@ -0,0 +1,72 @@
|
||||
<script>
|
||||
/* eslint no-console:0 */
|
||||
import Tree, { TreeNode } from '../index'
|
||||
import '../assets/index.less'
|
||||
import cssAnimation from 'css-animation'
|
||||
|
||||
function animate (node, show, done) {
|
||||
let height = node.offsetHeight
|
||||
return cssAnimation(node, 'collapse', {
|
||||
start () {
|
||||
if (!show) {
|
||||
node.style.height = `${node.offsetHeight}px`
|
||||
} else {
|
||||
height = node.offsetHeight
|
||||
node.style.height = 0
|
||||
}
|
||||
},
|
||||
active () {
|
||||
node.style.height = `${show ? height : 0}px`
|
||||
},
|
||||
end () {
|
||||
node.style.height = ''
|
||||
done()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const animation = {
|
||||
enter (node, done) {
|
||||
return animate(node, true, done)
|
||||
},
|
||||
leave (node, done) {
|
||||
return animate(node, false, done)
|
||||
},
|
||||
}
|
||||
export default {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<h2>expanded</h2>
|
||||
<Tree
|
||||
defaultExpandAll={false}
|
||||
defaultExpandedKeys={['p1']}
|
||||
openAnimation={{ on: animation, props: { appear: true }}}
|
||||
>
|
||||
<TreeNode title='parent 1' key='p1'>
|
||||
<TreeNode key='p10' title='leaf'/>
|
||||
<TreeNode title='parent 1-1' key='p11'>
|
||||
<TreeNode title='parent 2-1' key='p21'>
|
||||
<TreeNode title='leaf'/>
|
||||
<TreeNode title='leaf'/>
|
||||
</TreeNode>
|
||||
<TreeNode key='p22' title='leaf'/>
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</Tree>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.collapse {
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.collapse-active {
|
||||
transition: height 0.3s ease-out;
|
||||
}
|
||||
</style>
|
173
components/vc-tree/demo/basic-controlled.vue
Normal file
173
components/vc-tree/demo/basic-controlled.vue
Normal file
@ -0,0 +1,173 @@
|
||||
<script>
|
||||
/* eslint no-console:0 */
|
||||
import Tree, { TreeNode } from '../index'
|
||||
import '../assets/index.less'
|
||||
import { gData,
|
||||
/* filterParentPosition, getFilterExpandedKeys,*/ getRadioSelectKeys } from './util'
|
||||
import '../../vc-dialog/assets/index.less'
|
||||
import Modal from '../../vc-dialog'
|
||||
import BaseMixin from '../../_util/BaseMixin'
|
||||
|
||||
export default {
|
||||
mixins: [BaseMixin],
|
||||
data () {
|
||||
return {
|
||||
// expandedKeys: getFilterExpandedKeys(gData, ['0-0-0-key']),
|
||||
expandedKeys: ['0-0-0-key'],
|
||||
autoExpandParent: true,
|
||||
// checkedKeys: ['0-0-0-0-key', '0-0-1-0-key', '0-1-0-0-key'],
|
||||
checkedKeys: ['0-0-0-key'],
|
||||
checkStrictlyKeys: { checked: ['0-0-1-key'], halfChecked: [] },
|
||||
selectedKeys: [],
|
||||
treeData: [],
|
||||
visible: false,
|
||||
multiple: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onExpand (expandedKeys) {
|
||||
console.log('onExpand', arguments)
|
||||
// if not set autoExpandParent to false, if children expanded, parent can not collapse.
|
||||
// or, you can remove all expanded chilren keys.
|
||||
this.setState({
|
||||
expandedKeys,
|
||||
autoExpandParent: false,
|
||||
})
|
||||
},
|
||||
onCheck (checkedKeys) {
|
||||
this.setState({
|
||||
checkedKeys,
|
||||
})
|
||||
},
|
||||
onCheckStrictly (checkedKeys, /* extra*/) {
|
||||
console.log(arguments)
|
||||
// const { checkedNodesPositions } = extra;
|
||||
// const pps = filterParentPosition(checkedNodesPositions.map(i => i.pos));
|
||||
// console.log(checkedNodesPositions.filter(i => pps.indexOf(i.pos) > -1).map(i => i.node.key));
|
||||
const cks = {
|
||||
checked: checkedKeys.checked || checkedKeys,
|
||||
halfChecked: [`0-0-${parseInt(Math.random() * 3, 10)}-key`],
|
||||
}
|
||||
this.setState({
|
||||
// checkedKeys,
|
||||
checkStrictlyKeys: cks,
|
||||
// checkStrictlyKeys: checkedKeys,
|
||||
})
|
||||
},
|
||||
onSelect (selectedKeys, info) {
|
||||
console.log('onSelect', selectedKeys, info)
|
||||
this.setState({
|
||||
selectedKeys,
|
||||
})
|
||||
},
|
||||
onRbSelect (selectedKeys, info) {
|
||||
let _selectedKeys = selectedKeys
|
||||
if (info.selected) {
|
||||
_selectedKeys = getRadioSelectKeys(gData, selectedKeys, info.node.props.eventKey)
|
||||
}
|
||||
this.setState({
|
||||
selectedKeys: _selectedKeys,
|
||||
})
|
||||
},
|
||||
onClose () {
|
||||
this.setState({
|
||||
visible: false,
|
||||
})
|
||||
},
|
||||
handleOk () {
|
||||
this.setState({
|
||||
visible: false,
|
||||
})
|
||||
},
|
||||
showModal () {
|
||||
this.setState({
|
||||
expandedKeys: ['0-0-0-key', '0-0-1-key'],
|
||||
checkedKeys: ['0-0-0-key'],
|
||||
visible: true,
|
||||
})
|
||||
// simulate Ajax
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
treeData: [...gData],
|
||||
})
|
||||
}, 2000)
|
||||
},
|
||||
triggerChecked () {
|
||||
this.setState({
|
||||
checkedKeys: [`0-0-${parseInt(Math.random() * 3, 10)}-key`],
|
||||
})
|
||||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
const loop = data => {
|
||||
return data.map((item) => {
|
||||
if (item.children) {
|
||||
return (
|
||||
<TreeNode
|
||||
key={item.key} title={item.title}
|
||||
disableCheckbox={item.key === '0-0-0-key'}
|
||||
>
|
||||
{loop(item.children)}
|
||||
</TreeNode>
|
||||
)
|
||||
}
|
||||
return <TreeNode key={item.key} title={item.title} />
|
||||
})
|
||||
}
|
||||
// console.log(getRadioSelectKeys(gData, this.selectedKeys));
|
||||
return (<div style={{ padding: '0 20px' }}>
|
||||
<h2>dialog</h2>
|
||||
<button class='btn btn-primary' onClick={this.showModal}>show dialog</button>
|
||||
<Modal
|
||||
title='TestDemo' visible={this.visible}
|
||||
onOk={this.handleOk} onClose={this.onClose}
|
||||
>
|
||||
{this.treeData.length ? (
|
||||
<Tree
|
||||
checkable class='dialog-tree'
|
||||
onExpand={this.onExpand} expandedKeys={this.expandedKeys}
|
||||
autoExpandParent={this.autoExpandParent}
|
||||
onCheck={this.onCheck} checkedKeys={this.checkedKeys}
|
||||
>
|
||||
{loop(this.treeData)}
|
||||
</Tree>
|
||||
) : 'loading...'}
|
||||
</Modal>
|
||||
|
||||
<h2>controlled</h2>
|
||||
<Tree
|
||||
checkable
|
||||
onExpand={this.onExpand} expandedKeys={this.expandedKeys}
|
||||
autoExpandParent={this.autoExpandParent}
|
||||
onCheck={this.onCheck} checkedKeys={this.checkedKeys}
|
||||
onSelect={this.onSelect} selectedKeys={this.selectedKeys}
|
||||
>
|
||||
{loop(gData)}
|
||||
</Tree>
|
||||
<button onClick={this.triggerChecked}>trigger checked</button>
|
||||
|
||||
<h2>checkStrictly</h2>
|
||||
<Tree
|
||||
checkable multiple={this.multiple} defaultExpandAll
|
||||
onExpand={this.onExpand} expandedKeys={this.expandedKeys}
|
||||
onCheck={this.onCheckStrictly}
|
||||
checkedKeys={this.checkStrictlyKeys}
|
||||
|
||||
>
|
||||
{loop(gData)}
|
||||
</Tree>
|
||||
|
||||
<h2>radio's behavior select (in the same level)</h2>
|
||||
<Tree
|
||||
multiple defaultExpandAll
|
||||
onSelect={this.onRbSelect}
|
||||
selectedKeys={getRadioSelectKeys(gData, this.selectedKeys) }
|
||||
>
|
||||
{loop(gData)}
|
||||
</Tree>
|
||||
</div>)
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
@ -16,7 +16,6 @@ export default {
|
||||
defaultSelectedKeys: keys,
|
||||
defaultCheckedKeys: keys,
|
||||
switchIt: true,
|
||||
showMore: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@ -55,7 +54,7 @@ export default {
|
||||
</span>)
|
||||
return (<div style={{ margin: '0 20px' }}>
|
||||
<h2>simple</h2>
|
||||
{/* <Tree
|
||||
<Tree
|
||||
class='myCls' showLine checkable defaultExpandAll
|
||||
defaultExpandedKeys={this.defaultExpandedKeys}
|
||||
onExpand={this.onExpand}
|
||||
@ -77,10 +76,9 @@ export default {
|
||||
<TreeNode title='parent 1-2-1' key='0-0-2-1' />
|
||||
</TreeNode>
|
||||
</TreeNode>
|
||||
</Tree> */}
|
||||
</Tree>
|
||||
|
||||
<h2>Check on Click TreeNode</h2>
|
||||
<button onClick={this.toggleChildren}>toggle children</button>
|
||||
<Tree
|
||||
class='myCls'
|
||||
showLine
|
||||
@ -98,10 +96,6 @@ export default {
|
||||
<TreeNode title='parent 1-1-0' key='0-0-1-0' disableCheckbox />
|
||||
<TreeNode title='parent 1-1-1' key='0-0-1-1' />
|
||||
</TreeNode>
|
||||
{this.showMore ? <TreeNode title='parent 2-1' key='0-0-2'>
|
||||
<TreeNode title='parent 2-1-0' key='0-0-2-0' disableCheckbox />
|
||||
<TreeNode title='parent 2-1-1' key='0-0-2-1' />
|
||||
</TreeNode> : null}
|
||||
</TreeNode>
|
||||
</Tree>
|
||||
</div>)
|
||||
|
176
components/vc-tree/demo/util.js
Normal file
176
components/vc-tree/demo/util.js
Normal file
@ -0,0 +1,176 @@
|
||||
/* eslint no-loop-func: 0*/
|
||||
/* eslint no-console:0 */
|
||||
|
||||
export function generateData (x = 3, y = 2, z = 1, gData = []) {
|
||||
// x:每一级下的节点总数。y:每级节点里有y个节点、存在子节点。z:树的level层级数(0表示一级)
|
||||
function _loop (_level, _preKey, _tns) {
|
||||
const preKey = _preKey || '0'
|
||||
const tns = _tns || gData
|
||||
|
||||
const children = []
|
||||
for (let i = 0; i < x; i++) {
|
||||
const key = `${preKey}-${i}`
|
||||
tns.push({ title: `${key}-label`, key: `${key}-key` })
|
||||
if (i < y) {
|
||||
children.push(key)
|
||||
}
|
||||
}
|
||||
if (_level < 0) {
|
||||
return tns
|
||||
}
|
||||
const __level = _level - 1
|
||||
children.forEach((key, index) => {
|
||||
tns[index].children = []
|
||||
return _loop(__level, key, tns[index].children)
|
||||
})
|
||||
}
|
||||
_loop(z)
|
||||
return gData
|
||||
}
|
||||
export function calcTotal (x = 3, y = 2, z = 1) {
|
||||
/* eslint no-param-reassign:0*/
|
||||
const rec = (n) => n >= 0 ? x * Math.pow(y, n--) + rec(n) : 0
|
||||
return rec(z + 1)
|
||||
}
|
||||
console.log('总节点数(单个tree):', calcTotal())
|
||||
// 性能测试:总节点数超过 2000(z要小)明显感觉慢。z 变大时,递归多,会卡死。
|
||||
|
||||
export const gData = generateData()
|
||||
|
||||
function isPositionPrefix (smallPos, bigPos) {
|
||||
if (bigPos.length < smallPos.length) {
|
||||
return false
|
||||
}
|
||||
// attention: "0-0-1" "0-0-10"
|
||||
if ((bigPos.length > smallPos.length) && (bigPos.charAt(smallPos.length) !== '-')) {
|
||||
return false
|
||||
}
|
||||
return bigPos.substr(0, smallPos.length) === smallPos
|
||||
}
|
||||
// console.log(isPositionPrefix("0-1", "0-10-1"));
|
||||
|
||||
// arr.length === 628, use time: ~20ms
|
||||
export function filterParentPosition (arr) {
|
||||
const levelObj = {}
|
||||
arr.forEach((item) => {
|
||||
const posLen = item.split('-').length
|
||||
if (!levelObj[posLen]) {
|
||||
levelObj[posLen] = []
|
||||
}
|
||||
levelObj[posLen].push(item)
|
||||
})
|
||||
const levelArr = Object.keys(levelObj).sort()
|
||||
for (let i = 0; i < levelArr.length; i++) {
|
||||
if (levelArr[i + 1]) {
|
||||
levelObj[levelArr[i]].forEach(ii => {
|
||||
for (let j = i + 1; j < levelArr.length; j++) {
|
||||
levelObj[levelArr[j]].forEach((_i, index) => {
|
||||
if (isPositionPrefix(ii, _i)) {
|
||||
levelObj[levelArr[j]][index] = null
|
||||
}
|
||||
})
|
||||
levelObj[levelArr[j]] = levelObj[levelArr[j]].filter(p => p)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
let nArr = []
|
||||
levelArr.forEach(i => {
|
||||
nArr = nArr.concat(levelObj[i])
|
||||
})
|
||||
return nArr
|
||||
}
|
||||
// console.log(filterParentPosition(
|
||||
// ['0-2', '0-3-3', '0-10', '0-10-0', '0-0-1', '0-0', '0-1-1', '0-1']
|
||||
// ));
|
||||
|
||||
function loopData (data, callback) {
|
||||
const loop = (d, level = 0) => {
|
||||
d.forEach((item, index) => {
|
||||
const pos = `${level}-${index}`
|
||||
if (item.children) {
|
||||
loop(item.children, pos)
|
||||
}
|
||||
callback(item, index, pos)
|
||||
})
|
||||
}
|
||||
loop(data)
|
||||
}
|
||||
|
||||
function spl (str) {
|
||||
return str.split('-')
|
||||
}
|
||||
function splitLen (str) {
|
||||
return str.split('-').length
|
||||
}
|
||||
|
||||
export function getFilterExpandedKeys (data, expandedKeys) {
|
||||
const expandedPosArr = []
|
||||
loopData(data, (item, index, pos) => {
|
||||
if (expandedKeys.indexOf(item.key) > -1) {
|
||||
expandedPosArr.push(pos)
|
||||
}
|
||||
})
|
||||
const filterExpandedKeys = []
|
||||
loopData(data, (item, index, pos) => {
|
||||
expandedPosArr.forEach(p => {
|
||||
if ((splitLen(pos) < splitLen(p) &&
|
||||
p.indexOf(pos) === 0 || pos === p) &&
|
||||
filterExpandedKeys.indexOf(item.key) === -1) {
|
||||
filterExpandedKeys.push(item.key)
|
||||
}
|
||||
})
|
||||
})
|
||||
return filterExpandedKeys
|
||||
}
|
||||
|
||||
function isSibling (pos, pos1) {
|
||||
pos.pop()
|
||||
pos1.pop()
|
||||
return pos.join(',') === pos1.join(',')
|
||||
}
|
||||
|
||||
export function getRadioSelectKeys (data, selectedKeys, key) {
|
||||
const res = []
|
||||
const pkObjArr = []
|
||||
const selPkObjArr = []
|
||||
loopData(data, (item, index, pos) => {
|
||||
if (selectedKeys.indexOf(item.key) > -1) {
|
||||
pkObjArr.push([pos, item.key])
|
||||
}
|
||||
if (key && key === item.key) {
|
||||
selPkObjArr.push(pos, item.key)
|
||||
}
|
||||
})
|
||||
const lenObj = {}
|
||||
const getPosKey = (pos, k) => {
|
||||
const posLen = splitLen(pos)
|
||||
if (!lenObj[posLen]) {
|
||||
lenObj[posLen] = [[pos, k]]
|
||||
} else {
|
||||
lenObj[posLen].forEach((pkArr, i) => {
|
||||
if (isSibling(spl(pkArr[0]), spl(pos))) {
|
||||
// 后来覆盖前者
|
||||
lenObj[posLen][i] = [pos, k]
|
||||
} else if (spl(pkArr[0]) !== spl(pos)) {
|
||||
lenObj[posLen].push([pos, k])
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
pkObjArr.forEach((pk) => {
|
||||
getPosKey(pk[0], pk[1])
|
||||
})
|
||||
if (key) {
|
||||
getPosKey(selPkObjArr[0], selPkObjArr[1])
|
||||
}
|
||||
|
||||
Object.keys(lenObj).forEach((item) => {
|
||||
lenObj[item].forEach((i) => {
|
||||
if (res.indexOf(i[1]) === -1) {
|
||||
res.push(i[1])
|
||||
}
|
||||
})
|
||||
})
|
||||
return res
|
||||
}
|
@ -23,6 +23,7 @@ export const contextTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
selectable: PropTypes.bool,
|
||||
showIcon: PropTypes.bool,
|
||||
icon: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
draggable: PropTypes.bool,
|
||||
checkable: PropTypes.oneOfType([
|
||||
PropTypes.bool,
|
||||
@ -62,6 +63,7 @@ const Tree = {
|
||||
prefixCls: PropTypes.string,
|
||||
showLine: PropTypes.bool,
|
||||
showIcon: PropTypes.bool,
|
||||
icon: PropTypes.oneOfType([PropTypes.object, PropTypes.func]),
|
||||
focusable: PropTypes.bool,
|
||||
selectable: PropTypes.bool,
|
||||
disabled: PropTypes.bool,
|
||||
@ -72,6 +74,7 @@ const Tree = {
|
||||
]),
|
||||
checkStrictly: PropTypes.bool,
|
||||
draggable: PropTypes.bool,
|
||||
defaultExpandParent: PropTypes.bool,
|
||||
autoExpandParent: PropTypes.bool,
|
||||
defaultExpandAll: PropTypes.bool,
|
||||
defaultExpandedKeys: PropTypes.arrayOf(PropTypes.string),
|
||||
@ -110,6 +113,7 @@ const Tree = {
|
||||
disabled: false,
|
||||
checkStrictly: false,
|
||||
draggable: false,
|
||||
defaultExpandParent: true,
|
||||
autoExpandParent: true,
|
||||
defaultExpandAll: false,
|
||||
defaultExpandedKeys: [],
|
||||
@ -123,15 +127,31 @@ const Tree = {
|
||||
const props = getOptionProps(this)
|
||||
const {
|
||||
defaultExpandAll,
|
||||
defaultExpandParent,
|
||||
defaultExpandedKeys,
|
||||
defaultCheckedKeys,
|
||||
defaultSelectedKeys,
|
||||
expandedKeys,
|
||||
} = props
|
||||
const children = this.$slots.default
|
||||
// Sync state with props
|
||||
const { checkedKeys = [], halfCheckedKeys = [] } =
|
||||
calcCheckedKeys(defaultCheckedKeys, props, children) || {}
|
||||
|
||||
const state = {
|
||||
sSelectedKeys: calcSelectedKeys(defaultSelectedKeys, props),
|
||||
sCheckedKeys: checkedKeys,
|
||||
sHalfCheckedKeys: halfCheckedKeys,
|
||||
}
|
||||
|
||||
if (defaultExpandAll) {
|
||||
state.sExpandedKeys = getFullKeyList(children)
|
||||
} else if (defaultExpandParent) {
|
||||
state.sExpandedKeys = calcExpandedKeys(expandedKeys || defaultExpandedKeys, props, children)
|
||||
} else {
|
||||
state.sExpandedKeys = defaultExpandedKeys
|
||||
}
|
||||
|
||||
// Cache for check status to optimize
|
||||
this.checkedBatch = null
|
||||
this.propsToStateMap = {
|
||||
@ -141,13 +161,7 @@ const Tree = {
|
||||
halfCheckedKeys: 'sHalfCheckedKeys',
|
||||
}
|
||||
return {
|
||||
sExpandedKeys: defaultExpandAll
|
||||
? getFullKeyList(children)
|
||||
: calcExpandedKeys(defaultExpandedKeys, props, children),
|
||||
sSelectedKeys: calcSelectedKeys(defaultSelectedKeys, props, children),
|
||||
sCheckedKeys: checkedKeys,
|
||||
sHalfCheckedKeys: halfCheckedKeys,
|
||||
|
||||
...state,
|
||||
...(this.getSyncProps(props) || {}),
|
||||
dragOverNodeKey: '',
|
||||
dropPosition: null,
|
||||
@ -161,18 +175,21 @@ const Tree = {
|
||||
|
||||
watch: {
|
||||
children (val) {
|
||||
const { checkedKeys = [], halfCheckedKeys = [] } = calcCheckedKeys(this.checkedKeys || this.sCheckedKeys, this.$props, this.$slots.default) || {}
|
||||
const { checkedKeys = [], halfCheckedKeys = [] } = calcCheckedKeys(this.checkedKeys || this.sCheckedKeys, this.$props, val) || {}
|
||||
this.sCheckedKeys = checkedKeys
|
||||
this.sHalfCheckedKeys = halfCheckedKeys
|
||||
},
|
||||
autoExpandParent (val) {
|
||||
this.sExpandedKeys = val ? calcExpandedKeys(this.expandedKeys, this.$props, this.$slots.default) : this.expandedKeys
|
||||
},
|
||||
expandedKeys (val) {
|
||||
this.sExpandedKeys = calcExpandedKeys(this.expandedKeys, this.$props, this.$slots.default)
|
||||
this.sExpandedKeys = this.autoExpandParent ? calcExpandedKeys(val, this.$props, this.$slots.default) : val
|
||||
},
|
||||
selectedKeys (val) {
|
||||
this.sSelectedKeys = calcSelectedKeys(this.selectedKeys, this.$props, this.$slots.default)
|
||||
this.sSelectedKeys = calcSelectedKeys(val, this.$props, this.$slots.default)
|
||||
},
|
||||
checkedKeys (val) {
|
||||
const { checkedKeys = [], halfCheckedKeys = [] } = calcCheckedKeys(this.checkedKeys, this.$props, this.$slots.default) || {}
|
||||
const { checkedKeys = [], halfCheckedKeys = [] } = calcCheckedKeys(val, this.$props, this.$slots.default) || {}
|
||||
this.sCheckedKeys = checkedKeys
|
||||
this.sHalfCheckedKeys = halfCheckedKeys
|
||||
},
|
||||
@ -251,6 +268,18 @@ const Tree = {
|
||||
}, 0)
|
||||
},
|
||||
onNodeDragOver (event, node) {
|
||||
const { eventKey } = node.props
|
||||
|
||||
// Update drag position
|
||||
if (this.dragNode && eventKey === this.dragOverNodeKey) {
|
||||
const dropPosition = calcDropPosition(event, node)
|
||||
|
||||
if (dropPosition === this.dropPosition) return
|
||||
|
||||
this.setState({
|
||||
dropPosition,
|
||||
})
|
||||
}
|
||||
this.__emit('dragover', { event, node })
|
||||
},
|
||||
onNodeDragLeave (event, node) {
|
||||
@ -502,8 +531,10 @@ const Tree = {
|
||||
newState.sHalfCheckedKeys = halfCheckedKeys
|
||||
}
|
||||
|
||||
if (checkSync('expandedKeys')) {
|
||||
newState.sExpandedKeys = calcExpandedKeys(props.expandedKeys, props, children)
|
||||
// Re-calculate when autoExpandParent or expandedKeys changed
|
||||
if (prevProps && (checkSync('autoExpandParent') || checkSync('expandedKeys'))) {
|
||||
newState.sExpandedKeys = props.autoExpandParent
|
||||
? calcExpandedKeys(props.expandedKeys, props, children) : props.expandedKeys
|
||||
}
|
||||
|
||||
if (checkSync('selectedKeys')) {
|
||||
|
@ -65,10 +65,10 @@ const TreeNode = {
|
||||
},
|
||||
inject: {
|
||||
vcTree: { default: {}},
|
||||
vcTreeNode: { default: {}},
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
vcTree: this.vcTree,
|
||||
vcTreeNode: this,
|
||||
}
|
||||
},
|
||||
@ -358,19 +358,37 @@ const TreeNode = {
|
||||
|
||||
// Load data to avoid default expanded tree without data
|
||||
syncLoadData (props) {
|
||||
const { loadStatus } = this
|
||||
const { expanded } = props
|
||||
const { expanded } = this
|
||||
const { vcTree: { loadData }} = this
|
||||
|
||||
if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf2()) {
|
||||
this.setState({ loadStatus: LOAD_STATUS_LOADING })
|
||||
// read from state to avoid loadData at same time
|
||||
this.setState(({ loadStatus }) => {
|
||||
if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf()) {
|
||||
loadData(this).then(() => {
|
||||
this.setState({ loadStatus: LOAD_STATUS_LOADED })
|
||||
}).catch(() => {
|
||||
this.setState({ loadStatus: LOAD_STATUS_FAILED })
|
||||
})
|
||||
|
||||
loadData(this).then(() => {
|
||||
this.setState({ loadStatus: LOAD_STATUS_LOADED })
|
||||
}).catch(() => {
|
||||
this.setState({ loadStatus: LOAD_STATUS_FAILED })
|
||||
})
|
||||
}
|
||||
return { loadStatus: LOAD_STATUS_LOADING }
|
||||
}
|
||||
|
||||
return null
|
||||
})
|
||||
|
||||
// const { loadStatus } = this
|
||||
// const { expanded } = props
|
||||
// const { vcTree: { loadData }} = this
|
||||
|
||||
// if (loadData && loadStatus === LOAD_STATUS_NONE && expanded && !this.isLeaf2()) {
|
||||
// this.setState({ loadStatus: LOAD_STATUS_LOADING })
|
||||
|
||||
// loadData(this).then(() => {
|
||||
// this.setState({ loadStatus: LOAD_STATUS_LOADED })
|
||||
// }).catch(() => {
|
||||
// this.setState({ loadStatus: LOAD_STATUS_FAILED })
|
||||
// })
|
||||
// }
|
||||
},
|
||||
|
||||
// Switcher
|
||||
@ -437,7 +455,7 @@ const TreeNode = {
|
||||
// Icon + Title
|
||||
renderSelector () {
|
||||
const { title, selected, icon, loadStatus, dragNodeHighlight } = this
|
||||
const { vcTree: { prefixCls, showIcon, draggable, loadData }} = this
|
||||
const { vcTree: { prefixCls, showIcon, icon: treeIcon, draggable, loadData }} = this
|
||||
const disabled = this.isDisabled()
|
||||
|
||||
const wrapClass = `${prefixCls}-node-content-wrapper`
|
||||
@ -446,15 +464,18 @@ const TreeNode = {
|
||||
let $icon
|
||||
|
||||
if (showIcon) {
|
||||
$icon = icon ? (
|
||||
const currentIcon = icon || treeIcon
|
||||
$icon = currentIcon ? (
|
||||
<span
|
||||
class={classNames(
|
||||
`${prefixCls}-iconEle`,
|
||||
`${prefixCls}-icon__customize`,
|
||||
)}
|
||||
>
|
||||
{typeof icon === 'function'
|
||||
? icon(this.$props) : icon}
|
||||
{typeof currentIcon === 'function'
|
||||
? currentIcon(
|
||||
{ props: this.$props, on: this.$listeners }
|
||||
) : currentIcon}
|
||||
</span>
|
||||
) : this.renderIcon()
|
||||
} else if (loadData && loadStatus === LOAD_STATUS_LOADING) {
|
||||
@ -510,6 +531,7 @@ const TreeNode = {
|
||||
animProps = getTransitionProps(openTransitionName, { appear: transitionAppear })
|
||||
} else if (typeof openAnimation === 'object') {
|
||||
animProps = { ...openAnimation }
|
||||
animProps.props = { css: false, ...animProps.props }
|
||||
if (!transitionAppear) {
|
||||
delete animProps.props.appear
|
||||
}
|
||||
@ -526,7 +548,6 @@ const TreeNode = {
|
||||
if (expanded) {
|
||||
$children = (
|
||||
<ul
|
||||
v-show={expanded}
|
||||
class={classNames(
|
||||
`${prefixCls}-child-tree`,
|
||||
expanded && `${prefixCls}-child-tree-open`,
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* eslint no-loop-func: 0*/
|
||||
import warning from 'warning'
|
||||
import { getSlotOptions, getOptionProps } from '../../_util/props-util'
|
||||
const DRAG_SIDE_RANGE = 0.25
|
||||
const DRAG_MIN_GAP = 2
|
||||
|
||||
export function arrDel (list, value) {
|
||||
const clone = list.slice()
|
||||
@ -23,27 +25,6 @@ export function posToArr (pos) {
|
||||
return pos.split('-')
|
||||
}
|
||||
|
||||
// Only used when drag, not affect SSR.
|
||||
export function getOffset (ele) {
|
||||
if (!ele.getClientRects().length) {
|
||||
return { top: 0, left: 0 }
|
||||
}
|
||||
|
||||
const rect = ele.getBoundingClientRect()
|
||||
if (rect.width || rect.height) {
|
||||
const doc = ele.ownerDocument
|
||||
const win = doc.defaultView
|
||||
const docElem = doc.documentElement
|
||||
|
||||
return {
|
||||
top: rect.top + win.pageYOffset - docElem.clientTop,
|
||||
left: rect.left + win.pageXOffset - docElem.clientLeft,
|
||||
}
|
||||
}
|
||||
|
||||
return rect
|
||||
}
|
||||
|
||||
export function getPosition (level, index) {
|
||||
return `${level}-${index}`
|
||||
}
|
||||
@ -194,15 +175,14 @@ export function getDragNodesKeys (treeNodes, node) {
|
||||
}
|
||||
|
||||
export function calcDropPosition (event, treeNode) {
|
||||
const offsetTop = getOffset(treeNode.selectHandle).top
|
||||
const offsetHeight = treeNode.selectHandle.offsetHeight
|
||||
const pageY = event.pageY
|
||||
const gapHeight = 2 // [Legacy] TODO: remove hard code
|
||||
if (pageY > offsetTop + offsetHeight - gapHeight) {
|
||||
return 1
|
||||
}
|
||||
if (pageY < offsetTop + gapHeight) {
|
||||
const { clientY } = event
|
||||
const { top, bottom, height } = treeNode.selectHandle.getBoundingClientRect()
|
||||
const des = Math.max(height * DRAG_SIDE_RANGE, DRAG_MIN_GAP)
|
||||
|
||||
if (clientY <= top + des) {
|
||||
return -1
|
||||
} else if (clientY >= bottom - des) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@ -218,13 +198,6 @@ export function calcExpandedKeys (keyList, props, children = []) {
|
||||
return []
|
||||
}
|
||||
|
||||
const { autoExpandParent } = props
|
||||
|
||||
// Do nothing if not auto expand parent
|
||||
if (!autoExpandParent) {
|
||||
return keyList
|
||||
}
|
||||
|
||||
// Fill parent expanded keys
|
||||
const { keyNodes, nodeList } = getNodesStatistic(children)
|
||||
const needExpandKeys = {}
|
||||
@ -330,10 +303,11 @@ export function calcCheckStateConduct (treeNodes, checkedKeys) {
|
||||
}
|
||||
|
||||
const { subNodes = [], parentPos, node } = keyNodes[key]
|
||||
if (isCheckDisabled(node)) return
|
||||
|
||||
tgtCheckedKeys[key] = true
|
||||
|
||||
if (isCheckDisabled(node)) return
|
||||
|
||||
// Conduct down
|
||||
subNodes
|
||||
.filter(sub => !isCheckDisabled(sub.node))
|
||||
|
@ -3,7 +3,7 @@ import Layout from './components/layout.vue'
|
||||
const AsyncTestComp = () => {
|
||||
const d = window.location.hash.replace('#', '')
|
||||
return {
|
||||
component: import(`../components/transfer/demo/${d}`),
|
||||
component: import(`../components/vc-tree/demo/${d}`),
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user