123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536 |
- <template>
- <view>
- <view v-if="showLoading" class="ly-tree_loading">
- <image class="ly-tree_loading-icon" src="data:image/gif;base64,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"></image>
- <text class="ly-tree_loading-text">正在加载</text>
- </view>
-
- <template v-else>
- <text v-if="isEmpty" class="ly-tree_empty">{{emptyText}}</text>
- <view class="ly-tree" role="tree" name="LyTreeExpand">
- <ly-tree-node v-for="nodeId in childNodesId"
- :nodeId="nodeId"
- :render-after-expand="renderAfterExpand"
- :show-checkbox="showCheckbox"
- :show-radio="showRadio"
- :check-only-leaf="checkOnlyLeaf"
- :key="getNodeKey(nodeId)"
- :indent="indent"
- :icon-class="iconClass" />
- </view>
- </template>
- </view>
- </template>
- <script>
- import TreeStore from './model/tree-store.js';
- import {getNodeKey} from './tool/util.js';
- import LyTreeNode from './ly-tree-node.vue';
- export default {
- name: 'LyTree',
-
- componentName: 'LyTree',
-
- components: {
- LyTreeNode
- },
-
- data() {
- return {
- elId: `ly_${Math.ceil(Math.random() * 10e5).toString(36)}`,
- store: {
- ready: false
- },
- currentNode: null,
- childNodesId: []
- };
- },
-
- provide() {
- return {
- tree: this
- }
- },
-
- props: {
-
- treeData: Array,
-
-
- ready: {
- type: Boolean,
- default: true
- },
-
-
- emptyText: {
- type: String,
- default: '暂无数据'
- },
-
-
- renderAfterExpand: {
- type: Boolean,
- default: true
- },
-
-
- nodeKey: String,
-
-
- checkStrictly: Boolean,
-
-
- defaultExpandAll: Boolean,
-
-
- toggleExpendAll: Boolean,
-
-
- expandOnClickNode: {
- type: Boolean,
- default: true
- },
-
-
- expandOnCheckNode: {
- type: Boolean,
- default: true
- },
-
-
- checkOnClickNode: Boolean,
- checkDescendants: {
- type: Boolean,
- default: false
- },
-
-
- autoExpandParent: {
- type: Boolean,
- default: true
- },
-
-
- defaultCheckedKeys: Array,
-
-
- defaultExpandedKeys: Array,
-
-
- expandCurrentNodeParent: Boolean,
-
-
- currentNodeKey: [String, Number],
-
-
- checkOnlyLeaf: {
- type: Boolean,
- default: false
- },
-
-
- showCheckbox: {
- type: Boolean,
- default: false
- },
-
-
- showRadio: {
- type: Boolean,
- default: false
- },
-
-
- props: {
- type: [Object, Function],
- default () {
- return {
- children: 'children',
- label: 'label',
- disabled: 'disabled'
- };
- }
- },
-
-
- lazy: {
- type: Boolean,
- default: false
- },
-
-
- highlightCurrent: Boolean,
-
-
- load: Function,
-
-
- filterNodeMethod: Function,
-
-
- childVisibleForFilterNode: {
- type: Boolean,
- default: false
- },
-
-
- accordion: Boolean,
-
-
- indent: {
- type: Number,
- default: 18
- },
-
-
- iconClass: String,
-
-
- showNodeIcon: {
- type: Boolean,
- default: false
- },
-
-
- isInjectParentInNode: {
- type: Boolean,
- default: false
- }
- },
-
- computed: {
- isEmpty() {
- if (this.store.root) {
- const childNodes = this.store.root.getChildNodes(this.childNodesId);
- return !childNodes || childNodes.length === 0 || childNodes.every(({visible}) => !visible);
- }
-
- return true;
- },
- showLoading() {
- return !(this.store.ready && this.ready);
- }
- },
-
- watch: {
- toggleExpendAll(newVal) {
- this.store.toggleExpendAll(newVal);
- },
- defaultCheckedKeys(newVal) {
- this.store.setDefaultCheckedKey(newVal);
- },
- defaultExpandedKeys(newVal) {
- this.store.defaultExpandedKeys = newVal;
- this.store.setDefaultExpandedKeys(newVal);
- },
- treeData(newVal) {
- this.store.setData(newVal);
- },
- checkStrictly(newVal) {
- this.store.checkStrictly = newVal || this.checkOnlyLeaf;
- },
- 'store.root.childNodesId'(newVal) {
- this.childNodesId = newVal;
- },
- childNodesId(){
- this.$nextTick(() => {
- this.$emit('ly-tree-render-completed');
- });
- }
- },
-
- methods: {
-
- filter(value, data) {
- if (!this.filterNodeMethod) throw new Error('[Tree] filterNodeMethod is required when filter');
- this.store.filter(value, data);
- },
-
-
- getNodeKey(nodeId) {
- let node = this.store.root.getChildNodes([nodeId])[0];
- return getNodeKey(this.nodeKey, node.data);
- },
-
-
- getNodePath(data) {
- return this.store.getNodePath(data);
- },
-
-
- getCheckedNodes(leafOnly, includeHalfChecked) {
- return this.store.getCheckedNodes(leafOnly, includeHalfChecked);
- },
-
-
- getCheckedKeys(leafOnly, includeHalfChecked) {
- return this.store.getCheckedKeys(leafOnly, includeHalfChecked);
- },
-
-
- getCurrentNode() {
- const currentNode = this.store.getCurrentNode();
- return currentNode ? currentNode.data : null;
- },
-
-
- getCurrentKey() {
- const currentNode = this.getCurrentNode();
- return currentNode ? currentNode[this.nodeKey] : null;
- },
-
-
- setCheckAll(isCheckAll = true) {
- if (this.showRadio) throw new Error('You set the "show-radio" property, so you cannot select all nodes');
-
- if (!this.showCheckbox) console.warn('You have not set the property "show-checkbox". Please check your settings');
-
- this.store.setCheckAll(isCheckAll);
- },
-
-
- setCheckedNodes(nodes, leafOnly) {
- this.store.setCheckedNodes(nodes, leafOnly);
- },
-
-
- setCheckedKeys(keys, leafOnly) {
- if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCheckedKeys');
- this.store.setCheckedKeys(keys, leafOnly);
- },
-
-
- setChecked(data, checked, deep) {
- this.store.setChecked(data, checked, deep);
- },
-
-
- getHalfCheckedNodes() {
- return this.store.getHalfCheckedNodes();
- },
-
-
- getHalfCheckedKeys() {
- return this.store.getHalfCheckedKeys();
- },
-
-
- setCurrentNode(node) {
- if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentNode');
- this.store.setUserCurrentNode(node);
- },
-
-
- setCurrentKey(key) {
- if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in setCurrentKey');
- this.store.setCurrentNodeKey(key);
- },
-
-
- getNode(data) {
- return this.store.getNode(data);
- },
-
-
- remove(data) {
- this.store.remove(data);
- },
-
-
- append(data, parentNode) {
- this.store.append(data, parentNode);
- },
-
-
- insertBefore(data, refNode) {
- this.store.insertBefore(data, refNode);
- },
-
-
- insertAfter(data, refNode) {
- this.store.insertAfter(data, refNode);
- },
-
-
- updateKeyChildren(key, data) {
- if (!this.nodeKey) throw new Error('[Tree] nodeKey is required in updateKeyChild');
- this.store.updateChildren(key, data);
- }
- },
-
- created() {
- this.isTree = true;
-
- let props = this.props;
- if (typeof this.props === 'function') props = this.props();
- if (typeof props !== 'object') throw new Error('props must be of object type.');
-
- this.store = new TreeStore({
- key: this.nodeKey,
- data: this.treeData,
- lazy: this.lazy,
- props: props,
- load: this.load,
- showCheckbox: this.showCheckbox,
- showRadio: this.showRadio,
- currentNodeKey: this.currentNodeKey,
- checkStrictly: this.checkStrictly || this.checkOnlyLeaf,
- checkDescendants: this.checkDescendants,
- expandOnCheckNode: this.expandOnCheckNode,
- defaultCheckedKeys: this.defaultCheckedKeys,
- defaultExpandedKeys: this.defaultExpandedKeys,
- expandCurrentNodeParent: this.expandCurrentNodeParent,
- autoExpandParent: this.autoExpandParent,
- defaultExpandAll: this.defaultExpandAll,
- filterNodeMethod: this.filterNodeMethod,
- childVisibleForFilterNode: this.childVisibleForFilterNode,
- showNodeIcon: this.showNodeIcon,
- isInjectParentInNode: this.isInjectParentInNode
- });
- this.childNodesId = this.store.root.childNodesId;
- },
-
- beforeDestroy() {
- if (this.accordion) {
- uni.$off(`${this.elId}-tree-node-expand`)
- }
- }
- };
- </script>
- <style>
- .ly-tree {
- position: relative;
- background-color: #FFF;
- padding: 30rpx;
- font-size: 30rpx;
- line-height: 2em;
- }
- .ly-tree_loading {
-
- display: flex;
-
- text-align: center;
- margin-top: 100rpx;
- align-items: center;
- }
-
- .ly-tree_loading-icon {
- width: 50rpx;
- height: 50rpx;
- }
-
- .ly-tree_loading-text {
- font-size: 30rpx;
- color: #606266;
- }
-
- .ly-tree_empty {
- text-align: center;
- margin-top: 100rpx;
- font-size: 30rpx;
- color: #606266;
- }
- </style>
|