UNPKG

infogo-tree

Version:

A vue tree component using virtual list.

1,404 lines (1,139 loc) 148 kB
module.exports = /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // create a fake namespace object /******/ // mode & 1: value is a module id, require it /******/ // mode & 2: merge all properties of value into the ns /******/ // mode & 4: return value when already ns object /******/ // mode & 8|1: behave like require /******/ __webpack_require__.t = function(value, mode) { /******/ if(mode & 1) value = __webpack_require__(value); /******/ if(mode & 8) return value; /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; /******/ var ns = Object.create(null); /******/ __webpack_require__.r(ns); /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); /******/ return ns; /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "fb15"); /******/ }) /************************************************************************/ /******/ ({ /***/ "7f4f": /***/ (function(module, exports, __webpack_require__) { // extracted by mini-css-extract-plugin /***/ }), /***/ "8bbf": /***/ (function(module, exports) { module.exports = require("vue"); /***/ }), /***/ "a4b1": /***/ (function(module, exports, __webpack_require__) { // extracted by mini-css-extract-plugin /***/ }), /***/ "eced": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_10_oneOf_1_0_node_modules_css_loader_index_js_ref_10_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_10_oneOf_1_2_node_modules_less_loader_dist_cjs_js_ref_10_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeDrop_vue_vue_type_style_index_0_id_f3a40f9c_lang_less_scoped_true___WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__("7f4f"); /* harmony import */ var _node_modules_mini_css_extract_plugin_dist_loader_js_ref_10_oneOf_1_0_node_modules_css_loader_index_js_ref_10_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_10_oneOf_1_2_node_modules_less_loader_dist_cjs_js_ref_10_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeDrop_vue_vue_type_style_index_0_id_f3a40f9c_lang_less_scoped_true___WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_mini_css_extract_plugin_dist_loader_js_ref_10_oneOf_1_0_node_modules_css_loader_index_js_ref_10_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_10_oneOf_1_2_node_modules_less_loader_dist_cjs_js_ref_10_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeDrop_vue_vue_type_style_index_0_id_f3a40f9c_lang_less_scoped_true___WEBPACK_IMPORTED_MODULE_0__); /* unused harmony reexport * */ /* unused harmony default export */ var _unused_webpack_default_export = (_node_modules_mini_css_extract_plugin_dist_loader_js_ref_10_oneOf_1_0_node_modules_css_loader_index_js_ref_10_oneOf_1_1_node_modules_vue_loader_lib_loaders_stylePostLoader_js_node_modules_postcss_loader_src_index_js_ref_10_oneOf_1_2_node_modules_less_loader_dist_cjs_js_ref_10_oneOf_1_3_node_modules_cache_loader_dist_cjs_js_ref_0_0_node_modules_vue_loader_lib_index_js_vue_loader_options_TreeDrop_vue_vue_type_style_index_0_id_f3a40f9c_lang_less_scoped_true___WEBPACK_IMPORTED_MODULE_0___default.a); /***/ }), /***/ "f6fd": /***/ (function(module, exports) { // document.currentScript polyfill by Adam Miller // MIT license (function(document){ var currentScript = "currentScript", scripts = document.getElementsByTagName('script'); // Live NodeList collection // If browser needs currentScript polyfill, add get currentScript() to the document object if (!(currentScript in document)) { Object.defineProperty(document, currentScript, { get: function(){ // IE 6-10 supports script readyState // IE 10+ support stack trace try { throw new Error(); } catch (err) { // Find the second match for the "at" string to get file src url from stack. // Specifically works with the format of stack traces in IE. var i, res = ((/.*at [^\(]*\((.*):.+:.+\)$/ig).exec(err.stack) || [false])[1]; // For all scripts on the page, if src matches or if ready state is interactive, return the script tag for(i in scripts){ if(scripts[i].src == res || scripts[i].readyState == "interactive"){ return scripts[i]; } } // If no match, return null return null; } } }); } })(document); /***/ }), /***/ "fb15": /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); // CONCATENATED MODULE: ./node_modules/@vue/cli-service/lib/commands/build/setPublicPath.js // This file is imported into lib/wc client bundles. if (typeof window !== 'undefined') { if (true) { __webpack_require__("f6fd") } var setPublicPath_i if ((setPublicPath_i = window.document.currentScript) && (setPublicPath_i = setPublicPath_i.src.match(/(.+\/)[^/]+\.js(\?.*)?$/))) { __webpack_require__.p = setPublicPath_i[1] // eslint-disable-line } } // Indicate to webpack that this file can be concatenated /* harmony default export */ var setPublicPath = (null); // CONCATENATED MODULE: ./node_modules/cache-loader/dist/cjs.js?{"cacheDirectory":"node_modules/.cache/vue-loader","cacheIdentifier":"aa157f90-vue-loader-template"}!./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Tree.vue?vue&type=template&id=b5627bbc& var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{class:_vm.wrapperCls},[_c('div',{ref:"scrollArea",class:_vm.scrollAreaCls,on:{"&scroll":function($event){$event.stopPropagation();return _vm.handleTreeScroll($event)}}},[_c('div',{class:_vm.blockAreaCls},[_c('div',{style:(_vm.topSpaceStyles)}),_vm._l((_vm.renderNodes),function(node){return _c('CTreeNode',_vm._g(_vm._b({key:node[_vm.keyField],class:[typeof _vm.nodeClassName === 'function' ? _vm.nodeClassName(node) : _vm.nodeClassName, typeof _vm.defaultClassName === 'function'? _vm.defaultClassName(node) : ''],style:({ minHeight: (_vm.nodeMinHeight + "px"), marginLeft: _vm.usePadding ? null : ((node._level * _vm.nodeIndent) + "px"), paddingLeft: _vm.usePadding ? ((node._level * _vm.nodeIndent) + "px") : null, width: _vm.usePadding ? null : ("calc(100% - " + (node._level * _vm.nodeIndent) + "px)"), }),attrs:{"data":node,"itemSize":_vm.itemSize},on:{"check":_vm.handleNodeCheck,"select":_vm.handleNodeSelect,"expand":_vm.handleNodeExpand,"node-drop":_vm.handleNodeDrop},scopedSlots:_vm._u([{key:"titleAddition",fn:function(scope){return [_vm._t("titleAddition",null,{"data":scope.data})]}}],null,true)},'CTreeNode',_vm.$props,false),_vm.treeNodeListeners))}),_c('div',{style:(_vm.bottomSpaceStyles)})],2)]),_c('div',{directives:[{name:"show",rawName:"v-show",value:(!_vm.blockLength),expression:"!blockLength"}],class:_vm.emptyCls},[_c('span',{class:_vm.emptyTextDefaultCls},[_vm._t("empty",[_vm._v("\n "+_vm._s(_vm.emptyText)+"\n ")])],2)]),_c('div',{directives:[{name:"show",rawName:"v-show",value:(_vm.loading || _vm.isRootLoading),expression:"loading || isRootLoading"}],class:_vm.loadingCls},[_c('div',{class:_vm.loadingWrapperCls},[_vm._t("loading",[_c('LoadingIcon',{class:_vm.loadingIconCls})])],2)]),_c('iframe',{ref:"iframe",class:_vm.iframeCls})])} var staticRenderFns = [] // CONCATENATED MODULE: ./src/components/Tree.vue?vue&type=template&id=b5627bbc& // EXTERNAL MODULE: external {"commonjs":"vue","commonjs2":"vue","root":"Vue"} var external_commonjs_vue_commonjs2_vue_root_Vue_ = __webpack_require__("8bbf"); var external_commonjs_vue_commonjs2_vue_root_Vue_default = /*#__PURE__*/__webpack_require__.n(external_commonjs_vue_commonjs2_vue_root_Vue_); // CONCATENATED MODULE: ./src/store/tree-node.ts function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } var getPropertyFromData = function getPropertyFromData(node, prop) { // const props = node.store.props; // const data = node.data || {}; var config = node[prop]; if (typeof config === 'function') { return config(node); } else if (typeof config === 'string') { return node[config]; } else if (typeof config === 'undefined') { var dataProp = node[prop]; return dataProp === undefined ? node.disabled : dataProp; } }; var notAllowOverrideList = ['_level', '_filterVisible', '_parent', '_loading', '_loaded', '_remote', '_keyField', 'children', 'setChildren']; var TreeNode = /*#__PURE__*/ function () { //#endregion Properties function TreeNode(options) { var parent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var _keyField = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'id'; var _remote = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; var childStr = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : ''; var disabledFn = arguments.length > 5 ? arguments[5] : undefined; _classCallCheck(this, TreeNode); this._keyField = _keyField; this._remote = _remote; /** 节点层级 */ this._level = 0; /** 多选是否选中 */ this.checked = false; /** 单选是否选中 */ this.selected = false; /** 是否半选状态 */ this.indeterminate = false; /** 是否禁用 */ // disabled: boolean = false /** 是否展开 */ this.expand = false; /** 是否可见 */ this.visible = true; /** 过滤后是否可见,如果为 false 则在其他可见情况下也是不可见的 */ this._filterVisible = true; /** 父节点 */ this._parent = null; /** 子节点 */ this.children = []; /** 是否是子节点 */ this.isLeaf = false; /** 节点是否正在加载 */ this._loading = false; /** 子节点是否已加载 */ this._loaded = false; this.disabledFn = disabledFn; for (var option in options) { if (notAllowOverrideList.indexOf(option) === -1 && option !== childStr) { this[option] = options[option]; } } if (this[_keyField] == null) { // 如果没有 id 字段,随机赋值一个 this[_keyField] = Math.random().toString(36).substring(2); } this._parent = parent; if (this._parent) { this._level = this._parent._level + 1; } this.visible = this._parent === null || this._parent.expand && this._parent.visible; // if (Array.isArray(options.children)) { // this.setChildren(options.children) // } if (Array.isArray(options[childStr])) { this.setChildren(options[childStr], childStr, disabledFn); } if (this.children.length) { this._loaded = true; } if (!this._remote) { this.isLeaf = !this.children.length; } this.disabled = getPropertyFromData(this, 'disabledFn'); } /** * 设置子节点 * @param children 子节点数据数组 */ _createClass(TreeNode, [{ key: "setChildren", value: function setChildren(children, childStr, disabledFn) { var _this = this; this.children = children.map(function (child) { return new TreeNode(Object.assign({}, child), _this, _this._keyField, _this._remote, childStr, disabledFn); }); } }]); return TreeNode; }(); // CONCATENATED MODULE: ./src/const/index.ts //#region ignoreMode var ignoreEnum; (function (ignoreEnum) { ignoreEnum["none"] = "none"; ignoreEnum["parents"] = "parents"; ignoreEnum["children"] = "children"; })(ignoreEnum || (ignoreEnum = {})); var API_METHODS = ['setData', 'setChecked', 'setCheckedKeys', 'checkAll', 'clearChecked', 'setSelected', 'clearSelected', 'setExpand', 'setExpandKeys', 'setExpandAll', 'getCheckedNodes', 'getCheckedKeys', 'getIndeterminateNodes', 'getSelectedNode', 'getSelectedKey', 'getExpandNodes', 'getExpandKeys', 'getCurrentVisibleNodes', 'getNode', 'getTreeData', 'getFlatData', 'getNodesCount', 'insertBefore', 'insertAfter', 'append', 'prepend', 'remove', 'filter', 'showCheckedNodes', 'loadRootNodes', 'scrollTo']; var TREE_SEARCH_API_METHODS = ['clearKeyword', 'getKeyword', 'search']; //#endregion API //#region Placement var placementEnum; (function (placementEnum) { placementEnum["bottom-start"] = "bottom-start"; placementEnum["bottom-end"] = "bottom-end"; placementEnum["bottom"] = "bottom"; placementEnum["top-start"] = "top-start"; placementEnum["top-end"] = "top-end"; placementEnum["top"] = "top"; })(placementEnum || (placementEnum = {})); //#endregion Placement //#region Scroll position var verticalPositionEnum; (function (verticalPositionEnum) { verticalPositionEnum["top"] = "top"; verticalPositionEnum["center"] = "center"; verticalPositionEnum["bottom"] = "bottom"; })(verticalPositionEnum || (verticalPositionEnum = {})); //#endregion Scroll position //#region Drag var dragHoverPartEnum; (function (dragHoverPartEnum) { dragHoverPartEnum["before"] = "before"; dragHoverPartEnum["body"] = "body"; dragHoverPartEnum["after"] = "after"; })(dragHoverPartEnum || (dragHoverPartEnum = {})); // CONCATENATED MODULE: ./src/store/tree-store.ts function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } } function tree_store_classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function tree_store_defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function tree_store_createClass(Constructor, protoProps, staticProps) { if (protoProps) tree_store_defineProperties(Constructor.prototype, protoProps); if (staticProps) tree_store_defineProperties(Constructor, staticProps); return Constructor; } //#endregion Types var tree_store_TreeStore = /*#__PURE__*/ function () { //#endregion Properties function TreeStore(options) { tree_store_classCallCheck(this, TreeStore); this.options = options; //#region Properties /** 树数据 */ this.data = []; this.childStr = ''; /** 扁平化的树数据 */ this.flatData = []; /** 树数据 map */ this.mapData = Object.create(null); /** 未加载但已选中的节点 key ,每次 flattenData 的时候进行检查,将加载的节点从此数组中剔除 */ this.unloadCheckedKeys = []; /** 未加载但选中的单选节点 key */ this.unloadSelectedKey = null; /** 当前单选选中节点 key */ this.currentSelectedKey = null; /** 事件 listeners */ this.listenersMap = {}; } tree_store_createClass(TreeStore, [{ key: "setData", value: function setData(data) { var _this = this; var selectableUnloadKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var checkableUnloadKeys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; var childStr = arguments.length > 3 ? arguments[3] : undefined; var disabledFn = arguments.length > 4 ? arguments[4] : undefined; var replenishSelect = arguments.length > 5 ? arguments[5] : undefined; this.childStr = childStr; this.disabledFn = disabledFn; this.data = data.map(function (nodeData) { return new TreeNode(nodeData, null, _this.options.keyField, !!_this.options.load, childStr, disabledFn); }); // 清空 mapData for (var key in this.mapData) { delete this.mapData[key]; } // 扁平化之前清空单选选中,如果 value 有值,则是 selectableUnloadKey 有值,会重新设置 currentSelectedKey ;多选选中没有存储在 store 中,因此不必事先清空。 this.currentSelectedKey = null; // 扁平化节点数据 this.flatData = this.flattenData(this.data); // 更新未载入多选选中节点 this.setUnloadCheckedKeys(checkableUnloadKeys || [], replenishSelect); if (selectableUnloadKey || selectableUnloadKey === 0) { // 更新未载入单选选中节点 this.currentSelectedKey = null; this.setUnloadSelectedKey(selectableUnloadKey); } this.emit('visible-data-change'); this.emit('set-data'); } //#region Set api /** * 设置单个节点多选选中 * @param key 设置的节点 key * @param value 是否选中 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发 `data-change` 事件以通知外部刷新视图 * @param filtering 是否正在过滤,如果是,则考虑 `filteredNodeCheckable` Prop,用于判断是否是用户点击节点触发的勾选 * @param isCheckAll 是否是全选 */ }, { key: "setChecked", value: function setChecked(key, value) { var triggerEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var triggerDataChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var filtering = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; var isCheckAll = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false; var node = this.mapData[key]; if (!node) return this.setUnloadChecked(key, value, triggerEvent, triggerDataChange); if (node.disabled && isCheckAll) return; // 首先确定没有变化的情况 if (node.checked && value) return; // 已经勾选的再次勾选,直接返回 if (!node.checked && !node.indeterminate && !value) return; // 未勾选且不是半选状态再次设置未勾选,直接返回 if (this.options.cascade) { // 向下勾选,包括自身 this.checkNodeDownward(node, value, filtering, isCheckAll); // 向上勾选父节点直到根节点 this.checkNodeUpward(node); } else { node.checked = value; } if (triggerEvent) { if (node.checked) { this.emit('check', node); } else { this.emit('uncheck', node); } } this.triggerCheckedChange(triggerEvent, triggerDataChange); } /** * 设置单个未加载节点选中,不公开此 API */ }, { key: "setUnloadChecked", value: function setUnloadChecked(key, value) { var triggerEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var triggerDataChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var index = this.findIndex(key, this.unloadCheckedKeys); if (value) { if (index === -1) { this.unloadCheckedKeys.push(key); } } else { if (index !== -1) { this.unloadCheckedKeys.splice(index, 1); } } this.triggerCheckedChange(triggerEvent, triggerDataChange); } /** * 批量选中/取消多选选中节点 * @param keys 选中的节点 key 数组 * @param value 是否选中 * @param triggerEvent 是否触发事件 */ }, { key: "setCheckedKeys", value: function setCheckedKeys(keys, value) { var _this2 = this; var triggerEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var triggerDataChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var isCheckAll = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; keys.forEach(function (key) { _this2.setChecked(key, value, false, false, false, isCheckAll); }); this.triggerCheckedChange(triggerEvent, triggerDataChange); } /** * 多选勾选全部节点 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发视图刷新 */ }, { key: "checkAll", value: function checkAll() { var _this3 = this; var triggerEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (this.options.cascade) { // 级联时,只要勾选第一层节点即可,如果第一层被禁用了,则往下一层勾选 var checkCascade = function checkCascade(nodes) { nodes.forEach(function (node) { if (node.disabled) { checkCascade(node.children); } else { _this3.setChecked(node[_this3.options.keyField], true, false, false); } }); }; checkCascade(this.data); } else { var length = this.flatData.length; for (var i = 0; i < length; i++) { var node = this.flatData[i]; this.setChecked(node[this.options.keyField], true, false, false); } } this.triggerCheckedChange(triggerEvent, triggerDataChange); } /** * 清除所有多选已选 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发视图刷新 */ }, { key: "clearChecked", value: function clearChecked() { var _this4 = this; var triggerEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var currentCheckedNodes = this.getCheckedNodes(); currentCheckedNodes.forEach(function (checkedNode) { _this4.setChecked(checkedNode[_this4.options.keyField], false, false, false); }); // 清空未加载多选选中节点 this.unloadCheckedKeys = []; this.triggerCheckedChange(triggerEvent, triggerDataChange); } /** * 触发 checked-change 的快捷方法 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发视图刷新 */ }, { key: "triggerCheckedChange", value: function triggerCheckedChange() { var triggerEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (triggerEvent) { this.emit('checked-change', this.getCheckedNodes(), this.getCheckedKeys()); } if (triggerDataChange) { this.emit('render-data-change'); } } /** * 设置单选选中 * @param key 选中节点 key * @param value 是否选中 * @param triggerEvent 是否触发事件 */ }, { key: "setSelected", value: function setSelected(key, value) { var triggerEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var triggerDataChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var node = this.mapData[key]; if (!node) return this.setUnloadSelected(key, value, triggerEvent, triggerDataChange); if (node.disabled) return; if (node.selected === value) return; // 当前节点已经是将要设置的状态,直接返回 if (key === this.currentSelectedKey) { // 设置的节点即当前已选中节点 if (!value) { // 取消当前选中节点 node.selected = value; this.currentSelectedKey = null; } } else { // 设置的节点不是当前已选中节点,要么当前没有选中节点,要么当前有选中节点 if (value) { if (this.currentSelectedKey === null) { // 当前没有选中节点 node.selected = value; this.currentSelectedKey = node[this.options.keyField]; } else { // 取消当前已选中,设置新的选中节点 if (this.mapData[this.currentSelectedKey]) { this.mapData[this.currentSelectedKey].selected = false; } node.selected = value; this.currentSelectedKey = node[this.options.keyField]; } } } if (triggerEvent) { if (node.selected) { this.emit('select', node); } else { this.emit('unselect', node); } this.emit('selected-change', this.getSelectedNode(), this.getSelectedKey()); } if (triggerDataChange) { this.emit('render-data-change'); } } /** * 设置未加载单选选中节点,不公开此 API */ }, { key: "setUnloadSelected", value: function setUnloadSelected(key, value) { var triggerEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; var triggerDataChange = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; if (value) { if (this.currentSelectedKey) { this.setSelected(this.currentSelectedKey, false, false, false); } this.unloadSelectedKey = key; } else { if (this.unloadSelectedKey === key) { this.unloadSelectedKey = null; } } if (triggerEvent) { this.emit('selected-change', this.getSelectedNode(), this.getSelectedKey()); } if (triggerDataChange) { this.emit('render-data-change'); } } /** * 清除当前单选选中 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发视图刷新 */ }, { key: "clearSelected", value: function clearSelected() { var triggerEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; if (this.currentSelectedKey && this.mapData[this.currentSelectedKey]) { this.setSelected(this.currentSelectedKey, false, triggerEvent, triggerDataChange); } else if (this.unloadSelectedKey !== null) { this.unloadSelectedKey = null; if (triggerEvent) { this.emit('selected-change', this.getSelectedNode(), this.getSelectedKey()); } if (triggerDataChange) { this.emit('render-data-change'); } } } /** * 设置节点展开 * @param key 节点 key * @param value 是否展开 * @param expandParent 展开节点时是否同时展开父节点 * @param triggerEvent 是否触发事件 * @param triggerDataChange 是否触发 `data-change` 事件以通知外部刷新视图 */ }, { key: "setExpand", value: function setExpand(key, value) { var _this5 = this; var expandParent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var triggerEvent = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true; var triggerDataChange = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true; var node = this.mapData[key]; if (!node || !expandParent && node.isLeaf) return; if (node.expand === value) return; // 当前节点已经是将要设置的状态,直接返回 if (!node.isLeaf) { if (typeof this.options.load === 'function') { // 如果节点未加载过且将要设置为加载,则调用 load 方法 if (!node._loaded && !node._loading && value) { node._loading = true; if (triggerDataChange) { this.emit('visible-data-change'); } new Promise(function (resolve, reject) { var load = _this5.options.load; load(node, resolve, reject); }).then(function (children) { if (Array.isArray(children) && children.length > 0) { var _this5$flatData; var parentIndex = _this5.findIndex(node); if (parentIndex === -1) return; node._loaded = true; node.expand = value; node.setChildren(children, _this5.childStr, _this5.disabledFn); // 如果单选选中的值为空,则允许后续数据覆盖单选 value var currentCheckedKeys = _this5.getCheckedKeys(); var flattenChildren = _this5.flattenData(node.children, _this5.getSelectedKey === null); (_this5$flatData = _this5.flatData).splice.apply(_this5$flatData, [parentIndex + 1, 0].concat(_toConsumableArray(flattenChildren))); // 如果有未加载的选中节点,判断其是否已加载 _this5.setUnloadCheckedKeys(currentCheckedKeys); if (_this5.unloadSelectedKey !== null) { _this5.setUnloadSelectedKey(_this5.unloadSelectedKey); } _this5.emit('set-data'); } else { // 当懒加载的数据为空去掉展开哦节点的箭头 if (node) { node.isLeaf = true; } } }).catch(function (e) { var err = e; if (!(e instanceof Error)) { err = new Error(e); } // tslint:disable-next-line: no-console console.error(err); }).then(function () { node._loading = false; if (triggerEvent) { _this5.emit('expand', node); } if (triggerDataChange) { _this5.emit('visible-data-change'); } }); return; } else if (node._loading) return; // 正在加载的节点,直接返回 } node.expand = value; // Set children visibility var queue = _toConsumableArray(node.children); while (queue.length) { if (queue[0].expand && queue[0].children.length) { queue.push.apply(queue, _toConsumableArray(queue[0].children)); } if (queue[0]._filterVisible === false) { queue[0].visible = false; } else { queue[0].visible = queue[0]._parent === null || queue[0]._parent.expand && queue[0]._parent.visible; } queue.shift(); } if (triggerEvent) { this.emit('expand', node); } if (triggerDataChange) { this.emit('visible-data-change'); } } if (expandParent && node._parent && value) { this.setExpand(node._parent[this.options.keyField], value, expandParent, false, triggerDataChange); } } /** * 批量设置节点展开/折叠 * @param keys 展开的节点 key 数组 * @param value 是否展开 */ }, { key: "setExpandKeys", value: function setExpandKeys(keys, value) { var _this6 = this; var triggerDataChange = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; keys.forEach(function (key) { _this6.setExpand(key, value, true, false, false); }); if (triggerDataChange) { this.emit('visible-data-change'); } } }, { key: "setExpandAll", value: function setExpandAll(value) { var _this7 = this; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; this.flatData.forEach(function (node) { if (!_this7.options.load || node._loaded) { _this7.setExpand(node[_this7.options.keyField], value, false, false, false); } }); if (triggerDataChange) { this.emit('visible-data-change'); } } //#endregion Set api //#region Get api /** * 获取多选选中节点 * @param ignoreMode 忽略模式,可选择忽略父节点或子节点,默认值是 CTree 的 ignoreMode Prop */ }, { key: "getCheckedNodes", value: function getCheckedNodes() { var _this8 = this; var ignoreMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.ignoreMode; if (ignoreMode === ignoreEnum.children) { var result = []; var traversal = function traversal(nodes) { nodes.forEach(function (node) { if (node.checked) { result.push(node); } else if (!node.isLeaf && (node.indeterminate || _this8.options.cascadeLoose && !node.indeterminate)) { traversal(node.children); } }); }; traversal(this.data); return result; } else { return this.flatData.filter(function (node) { if (ignoreMode === ignoreEnum.parents) return node.checked && node.isLeaf; return node.checked; }); } } /** * 获取多选选中的节点 key ,包括未加载的 key * @param ignoreMode 忽略模式,同 `getCheckedNodes` */ }, { key: "getCheckedKeys", value: function getCheckedKeys() { var _this9 = this; var ignoreMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.ignoreMode; return this.getCheckedNodes(ignoreMode).map(function (checkedNodes) { return checkedNodes[_this9.options.keyField]; }).concat(this.unloadCheckedKeys); } /** * 获取多选半选状态节点 */ }, { key: "getIndeterminateNodes", value: function getIndeterminateNodes() { return this.flatData.filter(function (node) { return node.indeterminate; }); } /** * 获取当前单选选中节点 */ }, { key: "getSelectedNode", value: function getSelectedNode() { if (this.currentSelectedKey === null) return null; return this.mapData[this.currentSelectedKey] || null; } /** * 获取当前单选选中节点 key ,有可能是未加载的选中项 */ }, { key: "getSelectedKey", value: function getSelectedKey() { if (this.currentSelectedKey === 0 || this.currentSelectedKey) return this.currentSelectedKey; return this.unloadSelectedKey || null; } /** * 获取未加载但多选选中的节点 */ }, { key: "getUnloadCheckedKeys", value: function getUnloadCheckedKeys() { return this.unloadCheckedKeys; } /** * 获取展开节点 */ }, { key: "getExpandNodes", value: function getExpandNodes() { return this.flatData.filter(function (node) { return !node.isLeaf && node.expand; }); } /** * 获取展开节点 keys */ }, { key: "getExpandKeys", value: function getExpandKeys() { var _this10 = this; return this.getExpandNodes().map(function (node) { return node[_this10.options.keyField]; }); } /** * 根据节点 key 获取节点 * @param key 节点 key */ }, { key: "getNode", value: function getNode(key) { return this.mapData[key] || null; } //#endregion Get api //#region Node transfer api // 这边的 referenceKey 都是被执行的节点,比如 insertBefore ,在这里 referenceKey 就是指要插入到 referenceKey 节点前面 }, { key: "insertBefore", value: function insertBefore(insertedNode, referenceKey) { var node = this.getInsertedNode(insertedNode, referenceKey); if (!node) return null; this.remove(node[this.options.keyField], false); var referenceNode = this.mapData[referenceKey]; var parentNode = referenceNode._parent; var childIndex = this.findIndex(referenceKey, parentNode && parentNode.children); var flatIndex = this.findIndex(referenceKey); var dataIndex = parentNode && -1 || this.findIndex(referenceKey, this.data); this.insertIntoStore(node, parentNode, childIndex, flatIndex, dataIndex); this.emit('visible-data-change'); return node; } }, { key: "insertAfter", value: function insertAfter(insertedNode, referenceKey) { var node = this.getInsertedNode(insertedNode, referenceKey); if (!node) return null; this.remove(node[this.options.keyField], false); var referenceNode = this.mapData[referenceKey]; var parentNode = referenceNode._parent; var childIndex = this.findIndex(referenceKey, parentNode && parentNode.children) + 1; var length = this.flatData.length; var referenceIndex = this.findIndex(referenceKey); // 找到待插入节点应该插入 flatData 的索引 var flatIndex = referenceIndex + 1; for (var i = referenceIndex + 1; i <= length; i++) { if (i === length) { flatIndex = i; break; } if (this.flatData[i]._level <= referenceNode._level) { flatIndex = i; break; } } var dataIndex = parentNode && -1 || this.findIndex(referenceKey, this.data) + 1; this.insertIntoStore(node, parentNode, childIndex, flatIndex, dataIndex); this.emit('visible-data-change'); return node; } }, { key: "append", value: function append(insertedNode, parentKey) { var parentNode = this.mapData[parentKey]; if (!parentNode.isLeaf) { var childrenLength = parentNode.children.length; return this.insertAfter(insertedNode, parentNode.children[childrenLength - 1][this.options.keyField]); } var node = this.getInsertedNode(insertedNode, parentKey, true); if (!node) return null; this.remove(node[this.options.keyField], false); var flatIndex = this.findIndex(parentKey) + 1; this.insertIntoStore(node, parentNode, 0, flatIndex); this.emit('visible-data-change'); return node; } }, { key: "prepend", value: function prepend(insertedNode, parentKey) { var parentNode = this.mapData[parentKey]; if (!parentNode.isLeaf) { return this.insertBefore(insertedNode, parentNode.children[0][this.options.keyField]); } var node = this.getInsertedNode(insertedNode, parentKey, true); if (!node) return null; this.remove(node[this.options.keyField], false); var flatIndex = this.findIndex(parentKey) + 1; this.insertIntoStore(node, parentNode, 0, flatIndex); this.emit('visible-data-change'); return node; } /** * 删除节点 * @param removedKey 要删除的节点 key */ }, { key: "remove", value: function remove(removedKey) { var _this11 = this; var triggerDataChange = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var node = this.mapData[removedKey]; if (!node) return null; // 从 flatData 中移除 var index = this.findIndex(node); if (index === -1) return null; var deleteCount = 1; var length = this.flatData.length; for (var i = index + 1; i < length; i++) { if (this.flatData[i]._level > node._level) { deleteCount++; } else break; } this.flatData.splice(index, deleteCount); // 从 mapData 中移除 var deleteInMap = function deleteInMap(key) { var node = _this11.mapData[key]; delete _this11.mapData[key]; node.children.forEach(function (child) { return deleteInMap(child[_this11.options.keyField]); }); }; deleteInMap(removedKey); // 从 data 中移除 if (!node._parent) { var _index = this.findIndex(node, this.data); if (_index > -1) { this.data.splice(_index, 1); } } // 从父节点 children 中移除 if (node._parent) { var childIndex = this.findIndex(node, node._parent.children); if (childIndex !== -1) { node._parent.children.splice(childIndex, 1); } // 处理父节点 isLeaf node._parent.isLeaf = !node._parent.children.length; // 处理父节点 expand if (node._parent.isLeaf) { node._parent.expand = false; node._parent.indeterminate = false; } // 更新被移除处父节点状态 this.updateMovingNodeStatus(node); } if (triggerDataChange) { this.emit('visible-data-change'); } return node; } }, { key: "getInsertedNode", value: function getInsertedNode(insertedNode, referenceKey) { var isParent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; var referenceNode = this.mapData[referenceKey]; if (!referenceNode) return null; var parentNode = isParent ? referenceNode : referenceNode._parent; if (insertedNode instanceof TreeNode) { // 与参照节点是同一个节点 if (insertedNode[this.options.keyField] === referenceKey) return null; return insertedNode; } else if (_typeof(insertedNode) === 'object') { if (insertedNode[this.options.keyField] === referenceKey) return null; var mapNode = this.mapData[insertedNode[this.options.keyField]]; if (mapNode) return mapNode; return new TreeNode(insertedNode, parentNode, this.options.keyField, !!this.options.load, this.childStr, this.disabledFn); } else { if (!this.mapData[insertedNode] || insertedNode === referenceKey) return null; return this.mapData[insertedNode]; } } /** * 将一个节点插入 store 记录中 * @param node 要插入的节点 * @param parentNode 要插入节点的父节点 * @param childIndex 如果有父节点,则需提供要插入的节点在同级节点中的顺序 * @param flatIndex 在 flatData 中的索引 * @param dataIndex 如果没有父节点,需要提供节点在 data 中的索引 */ }, { key: "insertIntoStore", value: function insertIntoStore(node, parentNode, childIndex, flatIndex, dataIndex) { var _this$flatData; if (flatIndex === -1) return; // 插入父节点 children 中 if (childIndex !== -1 && parentNode) { parentNode.children.splice(childIndex, 0, node); } // 更新 _parent node._parent = parentNode; // 更新父节点 isLeaf, expand if (parentNode) { parentNode.isLeaf = false; this.setExpand(parentNode[this.options.keyField], true, true, false, false); } else if (typeof dataIndex === 'number' && dataIndex > -1) { // 没有父节点,则需要插入到 this.data 中以保证数据正确 this.data.splice(dataIndex, 0, node); } // 插入 flatData 与 mapData var nodes = this.flattenData([node]); // 处理自身及子节点 _level node._level = parentNode ? parentNode._level + 1 : 0; nodes.forEach(function (childNode) { return childNode._level = childNode._parent ? childNode._parent._level + 1 : 0; }); (_this$flatData = this.flatData).splice.apply(_this$flatData, [flatIndex, 0].concat(_toConsumableArray(nodes))); // 更新被移除处父节点状态 this.updateMovingNodeStatus(node); } }, { key: "updateMovingNodeStatus", value: function updateMovingNodeStatus(movingNode) { // 处理多选 this.checkNodeUpward(movingNode); this.triggerCheckedChange(); // 处理单选 if (movingNode.selected) { this.setSelected(movingNode[this.options.keyField], true); } } //#endregion Node transfer api /** * 过滤本地节点数据 * @param keyword 过滤关键词 * @param filterMethod 过滤方法 */ }, { key: "filter", value: function filter(keyword, filterMethod) { var _this12 = this; // 使用树形结构数据进行遍历 var filterVisibleNodes = []; this.flatData.forEach(function (node) { node._filterVisible = node._parent && node._parent._filterVisible || filterMethod(keyword, node); node.visible = node._filterVisible; if (node._filterVisible) { filterVisibleNodes.push(node); } }); // 对于临时列表中的节点,都是可见的,因此将它们的父节点都设为可见并展开 filterVisibleNodes.forEach(function (node) { var stack = []; var parent = node._parent; while (parent) { stack.unshift(parent); parent = parent._parent; } stack.forEach(function (parent) { parent._filterVisible = true; // parent.visible = parent._filterVisible // _filterVisible 且 无父级或者父级展开且可见,则设为可见 parent.visible = (parent._parent === null || parent._parent.expand && parent._parent.visible) && parent._filterVisible; _this12.options.expandOnFilter && _this12.setExpand(parent[_this12.options.keyField], true, true, false, false); }); node.visible = node._parent === null || node._parent.expand && node._parent.visible; }); this.emit('visible-data-change'); } /** * 过滤未加载多选节点,对比最终勾选节点是否有变化并触发 checked-change 事件 * @param keys 全量选中节点 key 数组,包括加载与未加载选中节点 */ }, { key: "setUnloadCheckedKeys", value: function setUnloadCheckedKeys(keys) { var replenishSelect = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; this.unloadCheckedKeys = keys; var checkedKeysCache = keys.concat(); var length = this.unloadCheckedKeys.length; for (var i = length - 1; i >= 0; i--) { var key = this.unloadCheckedKeys[i]; if (this.mapData[key]) { this.setChecked(key, true, false, false); this.unloadCheckedKeys.splice(i, 1); } } var newCheckedKeys = this.getCheckedKeys(); if (newCheckedKeys.length === checkedKeysCache.length && newCheckedKeys.every(function (val) { return checkedKeysCache.some(function (cache) { return cache === val; }); })) return; // 因为多选模式下,value 传过来的数据跟数据上标识 checked: true 的结果可能不一致,因此需要触发一个事件告诉外部最终勾选了哪些节点 if (replenishSelect) { this.emit('checked-change', this.getCheckedNodes(), newCheckedKeys); } } /** * 过滤未加载单选选中节点,对比是否有变化并触发 selected-change 事件 * @param key 节点 key */ }, { key: "setUnloadSelectedKey", value: function setUnloadSelectedKey(key) { var selectedKeyCache = this.getSelectedKey(); if (this.mapData[key]) { // 如果节点已加载 this.setSelected(key, true, false); this.unloadSelectedKey = null; } else { // 节点未加载 this.currentSelectedKey && this.setSelected(this.currentSelectedKey, false, false); this.unloadSelectedKey = key; } var newSelectedKey = this.getSelectedKey(); if (newSelectedKey === selectedKeyCache) return; this.emit('selected-change', this.getSelectedNode(), newSelectedKey); } /** * 保存扁平化的节点数据 `flatData` 与节点数据 Map `mapData` * @param nodes 树状节点数据 * @param overrideSelected 是否根据数据设置 `selected` */ }, { key: "flattenData", value: function flattenData(nodes) { var overrideSelected = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var result = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var length = nodes.length; for (var i = 0; i < length; i++) { var node = nodes[i]; var key = node[this.options.keyField]; result.push(node); if (this.mapData[key]) { throw new Error('[CTree] Duplicate tree node key.'); } this.mapData[key] = node; // 如果数据上就是选中的,则更新节点状态 if (node.checked && this.options.cascade) { // 向下勾选,包括自身 this.checkNodeDownward(node, true); // 向上勾选父节点直到根节点 this.checkNodeUpward(node); } if (node.selected && overrideSelected) { this.clearSelected(false, false); this.currentSelectedKey = node[this.options.keyField]; this.emit('selected-c