Flex中如何通过variableRowHeight和wordWrap属性,创建行高度可变的Tree

本文介绍了一个使用 Flex 和 MXML 编写的简单应用程序实例,该程序通过 XML 格式组织和展示了多段文字内容。利用 Tree 组件实现了有序的文档结构,并配置了多种显示属性以增强用户体验。

main.mxml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <mx:Applicationxmlns:mx="http://www.adobe.com/2006/mxml"
  3. layout="vertical"
  4. verticalAlign="middle"
  5. backgroundColor="white">
  6. <mx:XMLid="xmlDP">
  7. <root>
  8. <paralabel="Paragraph 1">
  9. <nodelabel="Lorem ipsum dolor sit amet, consectetuer adipiscing elit." />
  10. <nodelabel="Cras porttitor nunc a pede." />
  11. <nodelabel="Nulla ac magna non risus accumsan egestas." />
  12. <nodelabel="Aenean pretium porta felis." />
  13. <nodelabel="Sed massa." />
  14. </para>
  15. <paralabel="Paragraph 2">
  16. <nodelabel="Pellentesque pretium eros id odio tincidunt lobortis." />
  17. <nodelabel="Praesent vitae dolor eget nisl adipiscing pretium." />
  18. <nodelabel="Fusce nonummy dignissim risus." />
  19. <nodelabel="Nunc sodales, lectus vitae nonummy cursus, augue lectus auctor orci, vel aliquet enim neque vel eros." />
  20. <nodelabel="Donec laoreet euismod libero." />
  21. <nodelabel="Etiam ut lectus." />
  22. </para>
  23. <paralabel="Paragraph 3">
  24. <nodelabel="Maecenas ut nibh eu diam viverra suscipit." />
  25. <nodelabel="Pellentesque auctor, turpis vel lobortis suscipit, neque tortor tristique nibh, venenatis suscipit nisl nisl eget magna." />
  26. <nodelabel="Donec interdum." />
  27. <nodelabel="Praesent diam." />
  28. </para>
  29. <paralabel="Paragraph 4">
  30. <nodelabel="Proin nulla." />
  31. <nodelabel="Morbi tincidunt, sapien in sollicitudin venenatis, nibh tortor pretium ante, non pharetra urna dolor et libero." />
  32. <nodelabel="In malesuada risus at neque." />
  33. </para>
  34. </root>
  35. </mx:XML>
  36. <mx:Treeid="tree"
  37. dataProvider="{xmlDP}"
  38. labelField="@label"
  39. showRoot="false"
  40. variableRowHeight="true"
  41. wordWrap="true"
  42. alternatingItemColors="[#FFFFFF,#EEEEEE]"
  43. showScrollTips="true"
  44. width="300"
  45. rowCount="6"/>
  46. </mx:Application>
<template> <view class="component-wrap"> <zy-tree containerClass="components-staff-wrap" ref="staffTreeRef" labelKey="name" boxHeight="300px" valueKey="id" :selectParent="false" :multiple="true" :needBtn="true" :toEject="true" :treeData="filterTree" :nextTreeStyle="{ height: '60vh', paddingBottom: 'calc(env(safe-area-inset-bottom) / 2 + 10px )' }" nextTreeMinHeight="400px" @_confirmBtn="onconfirm" @confirm="onClickItem" @cancel="otherClose" :needClickFn="true" :otherCloseFn="otherCloseFn" :defaultValue="currentValue" currentIcon="folder" defaultIcon="zhankai" > <view> <view class="component-header"> <view class="input-box"> <view class="icon-box"> <uni-icons type="search" color="#d6d6d6" size="16" /> </view> <input class="input" v-model="inputStr" :placeholder="placeholder" placeholder-class="inputPlaceholder" @input="(e: any) => userInput(e.detail.value)" /> <view class="icon-box" v-if="inputStr && needCloseIcon" @click="clearableFn"> <uni-icons type="clear" color="#d6d6d6" size="16" /> </view> </view> </view> </view> <!-- 空数据 插槽--> <template #empty v-if="filterTree.length === 0"> <view class="empty-wrap"> <view class="empty-data"> <view class="empty-data-wrap"> <img :src="getCrmUrl('/20251231/crm_market_nosearchdata.png')" alt="" /> </view> </view> <view class="empty-data-text-wrap">未找到相关人员</view> </view> </template> </zy-tree> </view> </template> <script setup lang="ts"> // 原则:传出数据,不传出方法 import { ref } from 'vue' import { deepClone } from '@/utils/crm/index' import { getCrmUrl } from '@/utils/crm/index' import { string } from '@/uni_modules/uview-plus/libs/function/test' const props = defineProps({ treeList: { type: Array, default: () => [] }, placeholder: { type: String, default: () => '搜索同人员姓名' }, needDisabled: { type: Boolean, default: () => true }, needClose: { type: Boolean, default: () => true }, needCloseIcon: { type: Boolean, default: () => false }, otherCloseFn: { type: Boolean, default: () => false } }) // 原始的 const selectValue = defineModel({ required: false, default: [] }) // 当前选中的 const currentValue = ref<any>([]) watch( selectValue, value => { currentValue.value = deepClone(value) }, { deep: true, immediate: true } ) const staffTreeRef = ref<any>(null) const inputStr = ref<string>('') //确认 const clearableFn = (list: any) => { console.log('🚀 ~ clearableFn ~ list:', list) console.log('🚀 ~ clearableFn ~ inputStr.value:', inputStr.value) inputStr.value = '' console.log('🚀 ~ clearableFn ~ inputStr.value:', inputStr.value) } //确认 const onconfirm = (list: any) => { selectValue.value = currentValue.value $emit('confirm', list) if (props.needClose) { close() } } //确认 const otherClose = () => { console.log('🚀 ~ otherClose ~ props.otherCloseFn:', props.otherCloseFn) if (props.otherCloseFn) { console.log('🚀 ~ otherClose ~ props.otherCloseFn:', props.otherCloseFn) $emit('close') } else { close() } } // 点击子节点 const onClickItem = (list: any) => { currentValue.value = list.id $emit('onClickItem', list) } const $emit = defineEmits<{ (e: 'onClickItem', list: any): void (e: 'confirm', list: any): void (e: 'cancel'): void (e: 'opened'): void (e: 'closed'): void (e: 'close'): void }>() const open = () => { staffTreeRef.value._show() $emit('opened') } // 关闭 const close = (val?: any) => { if (val) return staffTreeRef.value._hide() currentValue.value = selectValue.value staffTreeRef.value._hide() $emit('closed') } defineExpose({ open, close }) const filterTree = computed(() => { if (!inputStr.value) { return props.treeList.map((item: any) => { ;(item.children || []).map((e: any) => { e.needShowChild = true return e }) return item }) } let inputValue = inputStr.value const filterChildren = (children: any) => { return children .map((child: any) => { const childMatches = (child.name || '').includes(inputValue) || (child.account || '').includes(inputValue) || (child.workNo || '').includes(inputValue) || (currentValue.value || []).includes(child.id) const filteredChildren = filterChildren(child.children) // 递归查找子节点 if (childMatches || filteredChildren.length > 0) { return { ...child, children: filteredChildren, needOpen: true, disabled: filteredChildren.length == '0' && !child.employeeId && props.needDisabled ? true : false // 如果部门没有员工,则禁用 } // 返回符合条件的子节点 } return null }) .filter(Boolean) } const filteredData = props.treeList .map((item: any) => { const children = filterChildren(item.children) // 过滤当前项的子节点 const itemMatches = (item.name || '').includes(inputValue) || (item.account || '').includes(inputValue) || (item.workNo || '').includes(inputValue) if (children.length > 0 || itemMatches) { return { ...item, children } // 返回符合条件的父节点 } return null }) .filter(Boolean) return filteredData }) const userInput = (val: string) => { inputStr.value = val } </script> <style lang="scss" scoped> .component-wrap { .component-header { background-color: $uni-bg-color-inverse; display: flex; text-align: left; .input-box { width: 100%; display: flex; align-items: center; background-color: #f2f3f5; border-radius: $uni-border-radius-sm; height: 32px; margin: $uni-spacing-row-xs $uni-spacing-row-base; padding: 0 $uni-spacing-row-base; } .icon-box { flex: none; } .input { flex: 1; font-size: $uni-font-size-14; color: $uni-text-color; font-weight: 400; padding-left: 4px; } :deep(.inputPlaceholder) { font-size: $uni-font-size-14; color: rgba(0, 0, 0, 0.16); font-weight: 400; } $search-item-height: 48px; .search { height: $search-item-height * 3; width: 100%; position: absolute; overflow-y: auto; top: 100%; z-index: 6666; background-color: #fff; } .search-item { display: flex; align-items: center; height: $search-item-height; padding-left: $uni-spacing-row-lg; box-sizing: border-box; position: relative; &::after { content: ''; position: absolute; bottom: 0; width: calc(100% - $uni-spacing-row-lg); height: 0.5px; background-color: $uni-divider-color; } &:last-child { &::after { display: none; } } } .search-item-icon-box { flex: none; } .search-item-label { display: block; flex: 1; font-size: $uni-font-size-15; color: $uni-text-color; font-weight: 400; max-width: 100%; padding-left: $uni-spacing-row-xs; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; word-break: break-all; } } } </style> <style lang="scss"> .components-staff-wrap { .next-tree-view { max-height: 60vh !important; padding-bottom: 20px; } .next-tree-cnt { background-color: #fff; } } .component-wrap { .next-tree-view { padding-bottom: 30px; } .empty-wrap { margin-top: 140px; padding-right: 20px; .empty-data { display: flex; justify-content: center; .empty-data-wrap { height: 100px; width: 120px; > image { width: 100%; height: 100%; } } } .empty-data-text-wrap { text-align: center; font-size: $uni-font-size-14; letter-spacing: 0; color: $uni-text-color-secondary; text-align: center; line-height: 26px; font-weight: 400; } } } </style> 监听props.treeList是否变化,打印变化次数
最新发布
11-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值