First commit

This commit is contained in:
weibangtuo 2016-10-21 00:55:09 +08:00
parent c84d5603d7
commit 3fb6c43e19
7 changed files with 366 additions and 1 deletions

View File

@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2016 weibt Copyright (c) 2016 weibangtuo
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

69
README.md Normal file
View File

@ -0,0 +1,69 @@
# Vue Tree View Component
Support `Vue.js` 1.0+
## Usage
Add the following required resources.
```html
<link rel="stylesheet" href="[You Path]font-awesome/4.+/css/font-awesome.min.css">
<link rel="stylesheet" href="src/tree.vue.css">
<script src="[You Path]vue.js"></script>
<script src="src/tree.vue.js"></script>
```
Add the component in your vue view.
```html
<div id="app">
<vue-tree :option="option"></vue-tree>
</div>
<script>
new Vue({
el: '#app',
data: {
option: {
root: { //Root Node, see Node Options
name: 'Root Node',
isParent: true,
isOpen: true,
children: []
}
}
}
</script>
```
## Node Options
```javascript
{
name: 'Node Name',
title: 'Node Tag title attr',
isParent: true, //
isOpen: true, // Control node to fold or unfold
icon: 'fa fa-folder', // Or other custom icons call by class name
openedIcon: 'fa fa-folder-open', // [option] For parent. Show when isOpen == true, show icon if it's null or empty
closedIcon: 'fa fa-folder', // [option] For parent. Show when isOpen != true, show icon if it's null or empty
children: [], // for parent node only
buttons: [ // []
{
title: 'icon button tag title attr', //[option]
icon: 'fa fa-edit',
click: function (node) { //[option]
//
}
}
//...
]
}
```
## License
Copyright (c) 2016 weibangtuo. Under MIT License.

19
demo/demo-vue1.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Tree</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="../src/tree.vue.css">
</head>
<body>
<div id="demo">
<h1>{{title}}</h1>
<vue-tree :option="option"></vue-tree>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.21/vue.js"></script>
<script src="../src/tree.vue.js"></script>
<script src="demo.js"></script>
</body>
</html>

19
demo/demo-vue2.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Tree</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css">
<link rel="stylesheet" href="../src/tree.vue.css">
</head>
<body>
<div id="demo">
<h1>{{title}}</h1>
<vue-tree :option="option"></vue-tree>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<script src="../src/tree.vue.js"></script>
<script src="demo.js"></script>
</body>
</html>

125
demo/demo.js Normal file
View File

@ -0,0 +1,125 @@
(function () {
'use strict';
var addNode = function (node) {
node.isOpen = true;
node.children.push({
name: 'child node',
parent: node,
isOpen: true,
isParent: true,
children: [],
buttons: [
{
title: 'Add',
icon: 'fa fa-plus',
click: addNode
}, {
title: 'Delete',
icon: 'fa fa-trash',
click: function (node) {
node.parent && node.parent.children.$remove(node);
}
}
]
});
};
new Vue({
el: '#demo',
data: {
title: 'Vue Tree Demo',
option: {
root: {
name: 'Root Node',
isParent: true,
isOpen: true,
openedIcon: 'fa fa-folder-open-o',
closedIcon: 'fa fa-folder-o',
children: [
{
name: 'Level1'
},
{
name: 'Level1 with icon',
icon: 'fa fa-cube',
title: '192.168.89.0'
},
{
name: 'Edit node',
buttons: [
{
title: 'Edit',
icon: 'fa fa-edit',
click: function (node) {
node.name = prompt('Editing node name, require string', node.name) || node.name;
}
}
]
},
{
name: 'Level1 has children',
icon: 'fa fa-folder',
openedIcon: 'fa fa-folder-open',
isOpen: false,
isParent: true,
children: [
{
name: 'level2 - 1',
icon: 'fa fa-file'
},
{
name: 'level2 - 2',
icon: 'fa fa-file'
},
{
name: 'level2 - 3',
icon: 'fa fa-file'
}
]
},
{
name: 'Level1 add node',
isOpen: true,
isParent: true,
children: [],
buttons: [
{
title: 'Add',
icon: 'fa fa-plus',
click: function (node) {
node.isOpen = true;
node.children.push({
name: 'level2 node',
parent: node,
buttons: [
{
title: 'Delete',
icon: 'fa fa-trash',
click: function (node) {
node.parent.children.$remove(node);
}
}
]
});
}
}
]
},
{
name: 'level1-addNode',
isOpen: true,
isParent: true,
children: [],
buttons: [
{
title: 'Add',
icon: 'fa fa-plus',
click: addNode
}
]
}
]
}
}
}
});
})();

78
src/tree.vue.css Normal file
View File

@ -0,0 +1,78 @@
.vue-tree {
font-size: 14px;
min-height: 20px;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.vue-tree li {
margin: 0;
padding: 5px;
position: relative;
list-style: none;
}
.vue-tree li > span,
.vue-tree li > i,
.vue-tree li > a {
line-height: 20px;
vertical-align: middle;
}
.vue-tree li > a + a {
margin-left: 5px;
}
.vue-tree li i.icon-open-state {
font-size: 16px;
}
.vue-tree ul ul li:hover {
background: rgba(0, 0, 0, .015)
}
.vue-tree li:after, .vue-tree li:before {
content: '';
left: -18px;
position: absolute;
right: auto
}
.vue-tree li:before {
border-left: 1px solid #999;
bottom: 50px;
height: 100%;
top: -16px;
width: 1px;
}
.vue-tree li:after {
border-top: 1px solid #999;
height: 20px;
top: 17px;
width: 22px
}
.vue-tree li span {
display: inline-block;
padding: 3px 5px;
text-decoration: none;
}
.vue-tree > ul > li::after, .vue-tree > ul > li:before {
border: 0
}
.vue-tree li:last-child::before {
height: 34px
}
.vue-tree > ul {
padding-left: 0
}
.vue-tree ul ul {
padding-left: 24px;
padding-top: 10px
}

55
src/tree.vue.js Normal file
View File

@ -0,0 +1,55 @@
(function () {
'use strict';
var VueTreeItem = Vue.extend({
template: '<li :class="{parent_li: node.isParent}">' +
'<i v-if="node.isParent" v-on:click="click(node)" class="fa icon-open-state" :class=\'{"fa-plus-square-o": !node.isOpen, "fa-minus-square-o": node.isOpen}\'></i>' +
'<span :title="node.title">' +
'<i v-if="showIcon(node)" :class="nodeClass(node)"></i> {{node.name}}</span>' +
'<a v-for="btn in node.buttons" class="ml5" href="javascript:" :title="btn.title" v-on:click="btnClick(btn, node)"><i :class="btn.icon"></i></a>' +
'<ul v-if="node.children && node.children.length" v-show="node.isOpen">' +
'<vue-tree-item v-for="item in node.children" :node="item"></vue-tree-item>' +
'</ul>' +
'</li>',
props: {
node: {
type: Object
}
},
methods: {
showIcon: function (node) {
return node.icon || node.openedIcon || node.closedIcon;
},
nodeClass: function (node) {
if (node.isOpen) {
return node.openedIcon || node.icon;
} else {
return node.closedIcon || node.icon;
}
},
click: function (node) {
node.isOpen = !node.isOpen;
},
btnClick: function (btn, node) {
if (typeof btn.click === 'function') {
btn.click(node);
}
}
}
});
Vue.component('vue-tree-item', VueTreeItem);
var VueTree = Vue.extend({
template: '<div class="vue-tree"><ul>' +
'<tree-item :node.sync="option.root"></tree-item>' +
'</ul></div>',
props: {
option: {
type: Object
}
},
components: {
'tree-item': VueTreeItem
}
});
Vue.component('vue-tree', VueTree);
})();