-
Notifications
You must be signed in to change notification settings - Fork 276
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(tree-select): [tree-select] add data init and optimize demo docs #2538
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ export default { | |
}, | ||
data() { | ||
return { | ||
value: '', | ||
value: 10, | ||
treeOp: { | ||
data: [ | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,7 @@ export default { | |
}, | ||
data() { | ||
return { | ||
value: [], | ||
value: [9, 6], | ||
treeOp: { | ||
data: [ | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,7 +11,7 @@ export default { | |
}, | ||
data() { | ||
return { | ||
value: [], | ||
value: [9, 6], | ||
treeOp: { | ||
data: [ | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,17 @@ | ||
import { find } from '../common/array' | ||
|
||
/** | ||
* 树节点过滤事件 | ||
*/ | ||
export const filter = | ||
({ vm }) => | ||
(value) => { | ||
vm.$refs.treeRef.filter(value) | ||
} | ||
|
||
/** | ||
* 单选,节点选择事件 | ||
*/ | ||
export const nodeClick = | ||
({ props, vm, emit }) => | ||
(data) => { | ||
|
@@ -24,6 +32,9 @@ export const nodeClick = | |
} | ||
} | ||
|
||
/** | ||
* 多选,勾选事件 | ||
*/ | ||
export const check = | ||
({ props, vm, emit }) => | ||
(data, { checkedNodes }) => { | ||
|
@@ -47,3 +58,115 @@ export const check = | |
emit('update:modelValue', currentValue) | ||
} | ||
} | ||
|
||
/** | ||
* 嵌套树结构转成扁平树结构 | ||
* @params data 嵌套树结构 示例:[{ children: [ { label: '二级 1-1', value: 4 }, ... ], label: '一级 1', value: 1 }, ...] | ||
* @return 扁平树结构 示例:[{ label: '一级 1', value: 1, pId: null }, { label: '二级 1-1', value: 4, pId: 1 }, ...] | ||
*/ | ||
export const getTreeData = | ||
({ props, state }) => | ||
(data) => { | ||
const nodes = [] | ||
const getChild = (data, pId) => { | ||
data.forEach((node) => { | ||
node.pId = pId | ||
nodes.push(node) | ||
|
||
if (node[state.childrenName] && node[state.childrenName].length > 0) { | ||
getChild(node[state.childrenName], node[props.valueField]) | ||
} | ||
}) | ||
Comment on lines
+72
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Avoid mutating input data in The Apply this diff to avoid mutating the input data: const getChild = (data, pId) => {
data.forEach((node) => {
+ const newNode = { ...node, pId }
+ nodes.push(newNode)
nodes.push(node)
- node.pId = pId
- nodes.push(node)
- if (node[state.childrenName] && node[state.childrenName].length > 0) {
+ if (newNode[state.childrenName] && newNode[state.childrenName].length > 0) {
getChild(newNode[state.childrenName], newNode[props.valueField])
}
})
}
|
||
} | ||
|
||
getChild(data, null) | ||
|
||
return nodes | ||
} | ||
|
||
/** | ||
* 多选,获取匹配的树节点 | ||
* @params value 树节点 value | ||
* @return 完整的树节点 示例:[{ label: "三级 1-1-2", value: 10, pId: 1, children: [...] }] | ||
*/ | ||
export const getPluginOption = | ||
({ api, props, state }) => | ||
(value) => { | ||
const isRemote = | ||
(props.filterable || props.searchable) && | ||
props.remote && | ||
(typeof props.remoteMethod === 'function' || typeof props.initQuery === 'function') | ||
const { textField, valueField } = props | ||
const sourceData = isRemote ? state.remoteData : api.getTreeData(state.treeData) | ||
const selNode = find(sourceData, (item) => item[valueField] === value) | ||
const items = [] | ||
|
||
if (selNode) { | ||
selNode.currentLabel = selNode[textField] | ||
items.push(selNode) | ||
} | ||
|
||
return items | ||
} | ||
|
||
/** | ||
* 多选,获取选中的树节点 value 数组,用于初始化树节点的勾选状态 | ||
* @return 示例:[9, 6] | ||
*/ | ||
export const getCheckedData = | ||
({ props, state }) => | ||
() => { | ||
const checkedKey = [] | ||
|
||
if (!Array.isArray(state.selected)) { | ||
return props.modelValue ? [props.modelValue] : [state.selected[props.valueField]] | ||
} else { | ||
state.selected.length > 0 && | ||
state.selected.forEach((item) => { | ||
checkedKey.push(item[props.valueField]) | ||
}) | ||
|
||
return checkedKey | ||
} | ||
} | ||
|
||
export const mounted = | ||
({ api, state, props, vm }) => | ||
() => { | ||
if (!state.value || state.value.length === 0) return | ||
|
||
if (props.multiple) { | ||
let initialNodes = [] | ||
if (Array.isArray(state.value)) { | ||
state.value.forEach((value) => { | ||
const option = api.getPluginOption(value) | ||
initialNodes = initialNodes.concat(option) | ||
}) | ||
} | ||
|
||
vm.$refs.baseSelectRef.updateSelectedData( | ||
initialNodes.map((node) => { | ||
return { | ||
...node, | ||
currentLabel: node[props.textField], | ||
value: node[props.valueField], | ||
isTree: true | ||
} | ||
}) | ||
) | ||
|
||
state.defaultCheckedKeys = api.getCheckedData()[0] | ||
} else { | ||
const data = api.getPluginOption(state.value)[0] | ||
vm.$refs.baseSelectRef.updateSelectedData({ | ||
...data, | ||
currentLabel: data[props.textField], | ||
value: data[props.valueField], | ||
state: { | ||
currentLabel: data[props.textField] | ||
} | ||
}) | ||
|
||
state.currentKey = data[props.valueField] | ||
} | ||
Comment on lines
+136
to
+171
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Safely handle undefined data in In the Apply this diff to handle potential undefined const data = api.getPluginOption(state.value)[0]
+ if (data) {
vm.$refs.baseSelectRef.updateSelectedData({
...data,
currentLabel: data[props.textField],
value: data[props.valueField],
state: {
currentLabel: data[props.textField]
}
})
state.currentKey = data[props.valueField]
+ } else {
+ // Handle the case when data is undefined
+ }
|
||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,20 +1,28 @@ | ||||||||||||||||||||||||||
import { filter, nodeClick, check } from './index' | ||||||||||||||||||||||||||
import { check, filter, getCheckedData, getPluginOption, getTreeData, mounted, nodeClick } from './index' | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export const api = ['state', 'filter', 'nodeClick', 'check'] | ||||||||||||||||||||||||||
export const api = ['state', 'check', 'filter', 'nodeClick'] | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
export const renderless = (props, { reactive, computed, watch }, { vm, emit }) => { | ||||||||||||||||||||||||||
export const renderless = (props, { reactive, computed, watch, onMounted }, { vm, emit }) => { | ||||||||||||||||||||||||||
const api = {} | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
const state = reactive({ | ||||||||||||||||||||||||||
value: computed(() => props.modelValue), | ||||||||||||||||||||||||||
treeData: props.treeOp.data | ||||||||||||||||||||||||||
childrenName: computed(() => (props.treeOp.props && props.treeOp.props.children) || 'children'), | ||||||||||||||||||||||||||
currentKey: props.modelValue, | ||||||||||||||||||||||||||
defaultCheckedKeys: [], | ||||||||||||||||||||||||||
remoteData: [], | ||||||||||||||||||||||||||
treeData: props.treeOp.data, | ||||||||||||||||||||||||||
value: computed(() => props.modelValue) | ||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
Comment on lines
+9
to
+14
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Improve props access safety with optional chaining. The - childrenName: computed(() => (props.treeOp.props && props.treeOp.props.children) || 'children'),
+ childrenName: computed(() => props.treeOp.props?.children || 'children'), 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Biome[error] 9-9: Change to an optional chain. Unsafe fix: Change to an optional chain. (lint/complexity/useOptionalChain) |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Object.assign(api, { | ||||||||||||||||||||||||||
state, | ||||||||||||||||||||||||||
check: check({ props, vm, emit }), | ||||||||||||||||||||||||||
filter: filter({ vm }), | ||||||||||||||||||||||||||
nodeClick: nodeClick({ props, vm, emit }), | ||||||||||||||||||||||||||
check: check({ props, vm, emit }) | ||||||||||||||||||||||||||
getCheckedData: getCheckedData({ props, state }), | ||||||||||||||||||||||||||
getPluginOption: getPluginOption({ api, props, state }), | ||||||||||||||||||||||||||
getTreeData: getTreeData({ props, state }), | ||||||||||||||||||||||||||
mounted: mounted({ api, state, props, vm }), | ||||||||||||||||||||||||||
nodeClick: nodeClick({ props, vm, emit }) | ||||||||||||||||||||||||||
}) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
watch( | ||||||||||||||||||||||||||
|
@@ -23,5 +31,7 @@ export const renderless = (props, { reactive, computed, watch }, { vm, emit }) = | |||||||||||||||||||||||||
{ immediate: true, deep: true } | ||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
onMounted(api.mounted) | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
return api | ||||||||||||||||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reorder size variants from largest to smallest
The current order of size variants doesn't follow a logical progression. To improve user comprehension, consider reordering the components from largest to smallest size:
Apply this reordering to match the PR objective of displaying options from large to small:
📝 Committable suggestion