(function () {
    // 插件核心:OOP的模式,可以创建单独的实例,这样实现私有属性和公有方法的有效管理
    class zTree {
        constructor(element, options) {
            // init params
            let self = this,
                len = arguments.length,
                config = {
                    element: null,
                    data: null,
                    callback: function () {}
                };
            if (len === 0) throw new Error(`element or options are required!`);
            if (len === 1) options = element;
            if (!options || typeof options !== "object") throw new TypeError(`options must be an object!`);
            if (len === 2) options.element = element;
            config = Object.assign(config, options);

            // verify the format of the transmitted information
            let {
                element: element2,
                data,
                callback
            } = config;
            if (!element2 || element2.nodeType !== 1) throw new TypeError(`element must be a DOM element object`);
            if (!Array.isArray(data)) throw new TypeError(`data must be an array!`);
            if (typeof callback !== "function") throw new TypeError(`callback must be an function!`);

            // mount to instance
            self.element = element2;
            self.data = data;
            self.callback = callback;
            self.n = 0;

            // init
            self.init();
        }
        init() {
            let self = this;
            self.element.innerHTML = `<ul class="level level0">
                ${self.html(self.data)}
            </ul>`;
            self.handle();
        }
        // dynamic creation of DOM structure
        html(data) {
            let self = this,
                str = ``;
            self.n++;
            data.forEach(item => {
                let {
                    name,
                    children,
                    open
                } = item;
                str += `<li>
                    <a href="#" class="title">${name}</a>
                    ${children && children.length>0?`
                        <em class="icon ${open?'open':''}"></em>
                        <ul class="level level${self.n}" style="display:${open?'block':'none'}">
                            ${self.html(children)}
                        </ul>
                    `:``}
                </li>`;
            });
            self.n--;
            return str;
        }
        // achieve specific functions
        handle() {
            let self = this;
            self.element.addEventListener('click', function (ev) {
                let target = ev.target;
                if (target.tagName === 'EM') {
                    let ulBox = target.nextElementSibling,
                        isOpen = target.classList.contains('open');
                    if (!ulBox) return;
                    if (isOpen) {
                        ulBox.style.display = 'none';
                        target.classList.remove('open');
                        self.callback(self, target, ulBox);
                        return;
                    }
                    ulBox.style.display = 'block';
                    target.classList.add('open');
                    self.callback(self, target, ulBox);
                }
            });
        }
    }

    // 暴露API
    if (typeof window !== "undefined") {
        window.zTree = zTree;
    }
    if (typeof module === "object" && typeof module.exports === "object") {
        module.exports = zTree;
    }
})();
 
 
---------使用方法-----
js-插件封装-树形折叠菜单_ico