UNPKG

zui

Version:

一个基于 Bootstrap 深度定制开源前端实践方案,帮助你快速构建现代跨屏应用。

821 lines (700 loc) 22.8 kB
section: view id: tree description: 体现层级关系的树形菜单 icon: icon-th-list filter: shuxingcaidan sxcd shuxcd --- # 树形菜单 <style> .nav-examples > li > a > code {display: none} .nav-examples > li.active > a > code {display: inline;} </style> 树形菜单提供一种展示层级关系(例如文件系统目录)菜单的视图。 ## 综合示例 下方展示了一个树形菜单,当一个链接包含一个子菜单时,通过点击链接左侧的图标可以展开内部子菜单。子菜单中的链接也可以包含另一个子菜单。 要构建一个树形菜单,只需要按层级嵌套 `<ul>`,并为顶层节点添加 `[data-ride="tree"]` 属性。 <div class="example"> <ul id="treeExample" class="tree" data-ride="tree" data-initial-state="preserve"> <li> <a href="#">水果</a> <ul> <li><a href="#">苹果</a></li> <li> <a href="#">热带水果</a> <ul> <li><a href="#">香蕉</a></li> <li><a href="#">芒果</a></li> <li><a href="#">椰子</a></li> <li><a href="#">菠萝</a></li> </ul> </li> <li><a href="#">梨子</a></li> <li><a href="#">草莓</a></li> <li><a href="#"></a></li> <li><a href="#">桃子</a></li> <li><a href="#">梅子</a></li> </ul> </li> <li> <a href="#">蔬菜</a> <ul> <li> <a href="#">我的菜</a> <ul> <li><a href="#">青菜</a></li> <li><a href="#">娃娃菜</a></li> <li><a href="#">菠菜</a></li> <li><a href="#">甘蓝</a></li> </ul> </li> <li> <a href="#">你的瓜</a> <ul> <li><a href="#">黄瓜</a></li> <li><a href="#">南瓜</a></li> <li><a href="#">丝瓜</a></li> <li><a href="#">苦瓜</a></li> <li><a href="#">木瓜</a></li> </ul> </li> <li><a href="#">白蓝</a></li> <li><a href="#">土豆</a></li> <li><a href="#">茄子</a></li> </ul> </li> <li> <a href="#">甜点</a> <ul> <li><a href="#">蛋糕</a></li> <li><a href="#">冰淇淋</a></li> <li><a href="#">果冻</a></li> </ul> </li> <li class="open"> <a href="#">坚果</a> <ul> <li><a href="#">瓜子</a></li> </ul> </li> <li> <a href="#">饮料</a> <ul> <li><a href="#">咖啡</a></li> <li><a href="#"></a></li> </ul> </li> <li><a href="#">酒水</a></li> <li><a href="#">粥饭</a></li> </ul> </div> ```html <ul class="tree" data-ride="tree"> <li> <a href="#">水果</a> <ul> <li><a href="#">苹果</a></li> <li> <a href="#">热带水果</a> <ul> ... </ul> </li> <li><a href="#">梨子</a></li> ... </ul> </li> <li><a href="#">粥饭</a></li> ... </ul> ``` ## 树形导航菜单 为 `.tree` 元素增加 `.tree-menu` 类可以获得树形导航外观。 <example> <nav class="menu" data-ride="menu" style="width: 200px"> <ul id="treeMenu" class="tree tree-menu" data-ride="tree"> <li><a href="#"><i class="icon icon-th"></i>首页</a></li> <li><a href="#"><i class="icon icon-user"></i>个人资料</a></li> <li> <a href="#"><i class="icon icon-time"></i>更新时间</a> <ul> <li><a href="#">今天</a></li> <li><a href="#">明天</a></li> <li><a href="#">昨天</a></li> <li><a href="#">本周</a></li> </ul> </li> <li><a href="#"><i class="icon icon-trash"></i>垃圾篓</a></li> <li><a href="#"><i class="icon icon-list-ul"></i>全部</a></li> <li class="open"> <a href="#"><i class="icon icon-tasks"></i>状态</a> <ul> <li> <a href="#"><i class="icon icon-circle-blank"></i>已就绪</a> <ul> <li><a href="#">已取消</a></li> <li><a href="#">已关闭</a></li> </ul> </li> <li class="active"><a href="#"><i class="icon icon-play-sign"></i>进行中</a></li> <li><a href="#"><i class="icon icon-ok-sign"></i>已完成</a></li> </ul> </li> </ul> </nav> </example> ```html <nav class="menu" data-ride="menu" style="width: 200px"> <ul id="treeMenu" class="tree tree-menu" data-ride="tree"> <li><a href="#"><i class="icon icon-th"></i>首页</a></li> <li><a href="#"><i class="icon icon-user"></i>个人资料</a></li> <li> <a href="#"><i class="icon icon-time"></i>更新时间</a> <ul> <li><a href="#">今天</a></li> <li><a href="#">明天</a></li> <li><a href="#">昨天</a></li> <li><a href="#">本周</a></li> </ul> </li> <li><a href="#"><i class="icon icon-trash"></i>垃圾篓</a></li> <li><a href="#"><i class="icon icon-list-ul"></i>全部</a></li> <li class="open"> <a href="#"><i class="icon icon-tasks"></i>状态</a> <ul> <li> <a href="#"><i class="icon icon-circle-blank"></i>已就绪</a> <ul> <li><a href="#">已取消</a></li> <li><a href="#">已关闭</a></li> </ul> </li> <li class="active"><a href="#"><i class="icon icon-play-sign"></i>进行中</a></li> <li><a href="#"><i class="icon icon-ok-sign"></i>已完成</a></li> </ul> </li> </ul> </nav> ``` ```js // 手动通过点击模拟高亮菜单项 $('#treeMenu').on('click', 'a', function() { $('#treeMenu li.active').removeClass('active'); $(this).closest('li').addClass('active'); }); ``` <script> $('#treeMenu').on('click', 'a', function() { $('#treeMenu li.active').removeClass('active'); $(this).closest('li').addClass('active'); }); </script> ## 外观选项 ### 在层级菜单之间显示连接线 `.tree-lines` <div class="example"> <ul class="tree tree-lines" data-ride="tree"> <li class="open"> <a href="#">水果</a> <ul> <li><a href="#">苹果</a></li> <li> <a href="#">热带水果</a> <ul> <li><a href="#">香蕉</a></li> <li><a href="#">芒果</a></li> <li><a href="#">椰子</a></li> <li><a href="#">菠萝</a></li> </ul> </li> <li><a href="#">梨子</a></li> <li><a href="#">草莓</a></li> <li><a href="#"></a></li> <li><a href="#">桃子</a></li> <li> <a href="#"></a> <ul> <li><a href="">黑莓</a></li> </ul> </li> </ul> </li> <li> <a href="#">蔬菜</a> <ul> <li> <a href="#">我的菜</a> <ul> <li><a href="#">青菜</a></li> <li><a href="#">娃娃菜</a></li> <li><a href="#">菠菜</a></li> <li><a href="#">甘蓝</a></li> </ul> </li> <li> <a href="#">你的瓜</a> <ul> <li><a href="#">黄瓜</a></li> <li><a href="#">南瓜</a></li> <li><a href="#">丝瓜</a></li> <li><a href="#">苦瓜</a></li> <li><a href="#">木瓜</a></li> </ul> </li> <li><a href="#">白蓝</a></li> <li><a href="#">土豆</a></li> <li><a href="#">茄子</a></li> </ul> </li> </ul> </div> ```html <ul class="tree tree-lines" data-ride="tree"> ... </ul> ``` ### 使用不同的图标 #### 内置图标类型 <div class="example"> <ul class="nav nav-tabs" id="treeIconsExampleNav" style="margin: -21px -21px 10px -21px; background-color: #fafafa"> <li class="active"><a href="###">默认</a></li> <li><a href="folders">文件夹`.tree-folders`</a></li> <li><a href="chevrons">V形`.tree-chevrons`</a></li> <li><a href="angles">直角`.tree-angles`</a></li> </ul> <ul class="tree tree-lines" id="treeIconsExample" data-ride="tree"> <li class="open"> <a href="#">水果</a> <ul> <li><a href="#">苹果</a></li> <li> <a href="#">热带水果</a> <ul> <li><a href="#">香蕉</a></li> <li><a href="#">芒果</a></li> <li><a href="#">椰子</a></li> <li><a href="#">菠萝</a></li> </ul> </li> <li><a href="#">梨子</a></li> <li><a href="#">草莓</a></li> <li><a href="#"></a></li> <li><a href="#">桃子</a></li> <li><a href="#">梅子</a></li> </ul> </li> <li> <a href="#">蔬菜</a> <ul> <li> <a href="#">我的菜</a> <ul> <li><a href="#">青菜</a></li> <li><a href="#">娃娃菜</a></li> <li><a href="#">菠菜</a></li> <li><a href="#">甘蓝</a></li> </ul> </li> <li> <a href="#">你的瓜</a> <ul> <li><a href="#">黄瓜</a></li> <li><a href="#">南瓜</a></li> <li><a href="#">丝瓜</a></li> <li><a href="#">苦瓜</a></li> <li><a href="#">木瓜</a></li> </ul> </li> <li><a href="#">白蓝</a></li> <li><a href="#">土豆</a></li> <li><a href="#">茄子</a></li> </ul> </li> </ul> </div> ```html <ul class="tree tree-lines" data-ride="tree"> ... </ul> ``` #### 使用CSS来自定义图标 ```css tree-custom-icons > li > .list-toggle:before {content: '\e6dd'} .tree-custom-icons > li.open > .list-toggle:before {content: '\e6df'} ``` ### 启用动画效果 `data-animate="true"` <div class="example"> <ul class="tree tree-lines" data-ride="tree" data-animate="true"> <li class="open in"> <a href="#">水果</a> <ul> <li><a href="#">苹果</a></li> <li> <a href="#">热带水果</a> <ul> <li><a href="#">香蕉</a></li> <li><a href="#">芒果</a></li> <li><a href="#">椰子</a></li> <li><a href="#">菠萝</a></li> </ul> </li> <li><a href="#">梨子</a></li> <li><a href="#">草莓</a></li> <li><a href="#"></a></li> <li><a href="#">桃子</a></li> <li><a href="#">梅子</a></li> </ul> </li> <li> <a href="#">蔬菜</a> <ul> <li> <a href="#">我的菜</a> <ul> <li><a href="#">青菜</a></li> <li><a href="#">娃娃菜</a></li> <li><a href="#">菠菜</a></li> <li><a href="#">甘蓝</a></li> </ul> </li> <li> <a href="#">你的瓜</a> <ul> <li><a href="#">黄瓜</a></li> <li><a href="#">南瓜</a></li> <li><a href="#">丝瓜</a></li> <li><a href="#">苦瓜</a></li> <li><a href="#">木瓜</a></li> </ul> </li> <li><a href="#">白蓝</a></li> <li><a href="#">土豆</a></li> <li><a href="#">茄子</a></li> </ul> </li> </ul> </div> ```html <ul class="tree tree-lines" data-animate="true" data-ride="tree"> ... </ul> ``` ## 用法 ### 调用方式 提供两种方式来使用树形菜单。 * 为`ul.tree`结构添加`data-ride="tree"`属性,则会在文档加载完毕之后自动初始化树形菜单; * 使用jQuery方法手动初始化树形菜单。 ```js $('#tree').tree(options); ``` ### 选项 可用选项如下: <table class="table table-bordered"> <thead> <tr> <th>选项</th> <th style="width: 80px">名称</th> <th style="width: 300px">可选值</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>`animate`</td> <td>动画效果</td> <td>* `true` 启用动画 * `false`(默认) 禁用动画</td> <td></td> </tr> <tr> <td>`initialState`</td> <td>初始状态</td> <td>* `'normal'`(默认) 自动根据dom结构决定 * `'expand'` 全部展开 * `'collapse'` 全部折叠 * `'preserve'` 从本地存储还原用户上次操作状态</td> <td>当使用`'normal'`选项时,如果一个`<li>`标签包含class`.open`且包含内部子菜单则子菜单(不包括子菜单的子菜单)在初始化之后会展开显示,其他情况下则折叠显示。</li></td> </tr> <tr> <td>`data`</td> <td>树节点数据</td> <td>数组,包含所有节点对象,可选</td> <td>格式参见本页面 **数据加载与更新** 章节。</td> </tr> <tr> <td>`itemCreator`</td> <td>节点创建函数</td> <td>函数</td> <td>节点创建函数用法参见本页面 **数据加载与更新** 章节。</td> </tr> <tr> <td>`itemWrapper`</td> <td>节点包装器</td> <td>* `false`(默认) 不启用节点包装器 * `true` 启用默认节点包装器 * 例如 `'<div class="my-tree-node/">'`:用来创建节点包装器的 HTML 文本</div></td> <td>用法参见本页面 **数据加载与更新** 章节。</td> </tr> </tbody> </table> 参数可以在手动调用`$().tree(options)`方法时传入,或者以`data-*=""`形式指定。 ### 方法 #### 展开节点 方法可用形式如下: * **expand()** * **expand(params)** * **expand(params, disabledAnimate)** 参数定义如下: * `params`:一个jQuery`<li>`对象,指定需要展开的节点,当不使用此参数时则展开所有节点; * `disabledAnimate`:是否禁用动画,默认 `false`; ```js // 使用 tree 实例 var myTree = $('#tree').data('zui.tree'); myTree.expand(params); // 使用 tree() 方式 $('#tree').tree('expand', params); ``` #### 折叠节点 方法可用形式如下: * **collapse()** * **collapse(params)** * **collapse(params, disabledAnimate)** 参数定义如下: * `params`:一个jQuery`<li>`对象,指定需要折叠的节点,当不使用此参数时则折叠所有节点; * `disabledAnimate`:是否禁用动画,默认 `false`; ```js // 使用 tree 实例 var myTree = $('#tree').data('zui.tree'); myTree.collapse(params); // 使用 tree() 方式 $('#tree').tree('collapse', params); ``` #### 切换节点 使得节点在展开或折叠的状态间切换。 方法可用形式如下: * **toggle()** * **toggle(params)** * **toggle(params, disabledAnimate)** 参数定义如下: * `params`:一个jQuery`<li>`对象,指定需要切换的节点,当不使用此参数时则切换所有节点; * `disabledAnimate`:是否禁用动画,默认 `false`; ```js // 使用 tree 实例 var myTree = $('#tree').data('zui.tree'); myTree.toggle(params); // 使用 tree() 方式 $('#tree').tree('toggle', params); ``` #### 展示节点 展开当前节点及所有子节点。 方法可用形式如下: * **show()** * **show(params)** * **show(params, disabledAnimate)** 参数定义如下: * `params`:一个jQuery`<li>`对象,指定需要展示的节点,当不使用此参数时则展示所有节点; * `disabledAnimate`:是否禁用动画,默认 `false`; ```js // 使用 tree 实例 var myTree = $('#tree').data('zui.tree'); myTree.show(params); // 使用 tree() 方式 $('#tree').tree('show', params); ``` #### 添加节点 向树添加节点有两种方式:一种是通过 jQuery 方式向树中插入符合树所要求的 DOM 节点即可;另一种方式使用树实例方法 `add($element, items)` 添加节点数据,该方法的可选形式为: * **add($element, items)** * **add($element, items, expand)** * **add($element, items, expand, disabledAnimate)** 最后三个参数可以依次省略,参数定义如下: * `$element`:要插入的父节点(jQuery 实例),可以为 `<ul>` 或 `<li>`; * `items`:数组,要插入的节点数据; * `expand`,插入后是否立即展开; * `disabledAnimate`:插入后如果需要立即展开是否禁用动画效果。 ```js // 获取 tree 实例 var myTree = $('#myTree').data('zui.tree'); // 准备插入的数据 var newItems = [{title: '新的节点'}, ...]; // 插入数据到根节点 myTree.add('#myTree', newItems); ``` #### 导出树数据 当添加了新的节点或者移除了节点之后,如果此时需要获取当前树更新后的数据,可以使用 `toData([$ul], [filter])` 方法。该方法拥有如下形式: * **toData()** * **toData($ul)** * **toData(filter)** * **toData($ul, filter)** 参数定义如下: * **$ul**:指定树种需要导出数据的 `<ul>` 节点。默认为树的根节点,及导出整个树的所有节点数据。 * **filter**:指定一个回调函数用于转换数据为合适的格式。该回调函数包括两个参数:`item`,正在导出的节点数据;`$li`,正在导出的 `<li>` 节点对象;必须在此回调函数中返回一个 JavaScript 对象。 ```js // 获取 tree 实例 var myTree = $('#myTree').data('zui.tree'); // 此处可以更新数结构 // 获取更新后的树数据 var myTreeData = myTree.toData(function(item, $li) { item._id = $li.data('id'); return item; }); ``` ### 事件 <table class="table table-bordered"> <thead> <tr> <th>事件</th> <th>jquery事件名称</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>`expand`</td> <td>`expand.zui.tree`</td> <td>当菜单展开之后会触发此事件</td> </tr> <tr> <td>`collapse`</td> <td>`collapse.zui.tree`</td> <td>当菜单被折叠之后会触发此事件</td> </tr> </tbody> </table> #### 监听事件 ```js // 通过jQuery方法绑定事件 $('#tree').on('expand.zui.tree', function(){...}); // 通过参数指定事件回调方法 $('#tree').tree({expand: function(){...}}); ``` <script> function afterPageLoad() { var $nav = $('#treeIconsExampleNav'), $example = $('#treeIconsExample'), $nameInCode = $('#treeIconsNameForExample'); $nav.on('click', 'a', function(e) { var $a = $(this); $nav.find('li.active').removeClass('active'); $a.parent('li').addClass('active'); var name = $a.attr('href').replace(/#/g, ''); if(name) name = ' tree-' + name; $nameInCode.text(name); $example.attr('class', 'tree tree-lines' + name); e.preventDefault(); }); $('[data-ride=tree]').tree(); } </script> ## 数据加载与更新 ### 使用数据初始化 在初始化树形菜单时可以使用 `data` 选项来指定用户构建树的数据。这种方式允许你在恰当时机来展示树(例如从远处服务器获取数据再进行展示)。 用户初始化的数据为一个数组,每个数组中包含若干个对象来用于创建树中的节点(以下简称为节点对象)。 节点对象中可能包含的属性如下: <table class="table table-bordered"> <thead> <tr> <th style="width: 90px">属性</th> <th style="width: 250px">可取的值示例</th> <th>说明</th> </tr> </thead> <tbody> <tr> <td>`title`</td> <td>`'第一个节点'`</td> <td>在节点上展示的文本。</td> </tr> <tr> <td>`url`</td> <td>`'http://zui.sexy'`</td> <td>可选,以链接的形式显示节点,指定链接地址。</td> </tr> <tr> <td>`html`</td> <td>`'<strong>着重强调的节点</strong>'`</td> <td>可选,用于设置为节点 HTML 的内容,如果指定此选项,则 `title` 选项可以省略。</td> </tr> <tr> <td>`children`</td> <td>`[{title: '子节点1'}, {title: '子节点2'}, ...]`</td> <td>可选,以数组的形式设置该节点下的所有子节点,子节点的设置方式与初始化数据一致。这种递归结构与树本身的嵌套结构一致。</td> </tr> <tr> <td>`open`</td> <td>`true`,`false`(默认)</td> <td>可选,如果该节点包含子节点,是否展开当前节点。</td> </tr> <tr> <td>`id`</td> <td>默认不设置</td> <td>用于设置到树节点 `<li>` 上的 `[data-id]` 属性的值,如果设置此属性请确保每一个节点的值在整个树种唯一。</li></td> </tr> </tbody> </table> 除了以上已经定义的命名属性,你仍然可以在节点数据中包含自定义的属性和数据。 以下代码演示了使用数据来初始化一个空的 `<ul class="tree">`: ```html <!-- 创建一个空的树,需要包含 .tree CLASS --> <ul class="tree" id="myTree"></ul> ``` ```js var myTreeData = [{ title: '水果', url: 'http://zui.sexy', open: true, children: [ {title: '橘子'}, { title: '瓜', children: [ {title: '西瓜'}, {title: '黄瓜'} ] } ] }, { title: '坚果', children: [ {title: '向日葵'}, {title: '瓜子'} ] }, { title: '蔬菜' }]; $('#myTree').tree({data: myTreeData}); ``` ### 动态更新数据 当树初始化之后,仍然可以使用 `reload(data)` 方法来动态更新数据。 ```js // 获取 tree 实例 var myTree = $('#myTree').data('zui.tree'); // 准备新的数据 var myNewTreeData = [...]; // 更新数据 myTree.reload(myNewTreeData); ``` ### 使用节点构造器 通过节点构造器可以方便的自定义节点的 DOM 内容。使用初始化选项 `itemCreator` 来定义节点构造器回调函数。节点构造器会在初始化节点数据或更新节点数据时被调用,其形式如下: * **function($li, item)** 参数定义如下: * `$li`:当前正在构造的节点实例; * `item`:当前用于构建的节点数据。 通过在节点构造器回调函数中直接操作节点实例来构造节点: ```js // 初始化选项中定义构造器回调函数 $('#myTree').tree({ data: [...], itemCreator: function($li, item) { $li.append($('<a/>', {href: item.url}).text(item.title)); // return false; // 如果要忽略当前节点,可以通过返回 false 来实现 } }) ``` ### 移除或清空节点 直接使用 jQuery 选择需要移除的节点,调用 jQuery 实例上的 `remove()` 或 `empty()` 方法。 ```js // 移除其中一个节点 $('#myTree li[data-id="myTreeNodeId"]').remove(); // 清空整个树节点 $('#myTree').empty(); ```