iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 17
0
Modern Web

Vue.js套件介紹及範例系列 第 17

iView - Tree

  • 分享至 

  • xImage
  •  

iView - Tree

一套基於 Vue.js 的高質量UI 組件庫,此篇介紹Tree(樹狀顯示器)

Github

iview/iview

範例

HTML

<tree :data="starwars" @on-select-change="selected"></tree>

JS

以階層的方式定義資料:

  • title: 顯示的值
  • children: 下一階層的資料
  • expand: Boolean,預設是否顯示下一層,預設為false
  • disabled: true: 禁用該筆資料 (Optional)

並可綁定on-select-change事件以取得被選取的節點。

const FOO_DATA = [
    {
        title: 'Bright side',expand: true,
        children: [
            {
                title: 'Male', expand: true,
                children: [
                    { title: 'Luke Skywalker', img: 'https://goo.gl/KEUxHN' }
                ]
            },
            {
                title: 'Female', expand: true,
                children: [
                    { title: 'Leia Skywalker', img: 'https://goo.gl/rNJhLU' }
                ]
            }
        ]
    },
    {
        title: 'Dark side', expand:false,
        children: [
            {
                title: 'Male',
                children: [
                    { title: 'Darth Vader', img: 'https://goo.gl/xcMHqj' }
                ]
            },
            {
                title:'Female', disabled: true,
                children: [
                    { title: 'Asajj Ventress', img: 'https://goo.gl/pr19sJ' }
                ]
            }
        ]
    }

];


var app = new Vue({
    el: "#app",
    data: {
        starwars: [],
        selectedNode: null,
    },
    methods: {
        selected(selectedItem){
            this.selectedNode = selectedItem[0];
            alert(`You select ${this.selectedNode.title}`);
        }
    },
    created() {
        this.starwars = FOO_DATA;
    }
})

加入Checkbox

設定show-checkbox並綁定on-check-change事件:

<tree :data="starwars"  show-checkbox  @on-check-change="checked"></tree>

注意on-check-change對應函式傳入的參數為所有已勾選的節點。
至於父層節點需要所有子節點皆為已勾選後,其'checked'才會為true

var app = new Vue({
    el: "#app",
    data: {
        starwars: [],
        checkedNodes: [] //All checked nodes
    },
    methods: {
        checked(checkedItems) {
            this.checkedNodes = checkedItems;
        }
    },
    created() {
        this.starwars = FOO_DATA;
    }
})

Demo:

也可透過遞迴手動取得所有已勾選的節點:

methods: {
    checked(checkedItems) {
        // Get all checked nodes manually by recursive 
        this.checkedNodes = [];
        this.visit(this.starwars);
    },
    visit(nodes) {
        nodes.forEach(node => {

            if (node.checked === true) {
                this.checkedNodes.push(node);
            }

            if (node.children)
                this.visit(node.children);
            else
                return
        });

    }
}

客製節點內容

利用Prop:render,我們可以在每個節點前加上圖示,及後面加上按鈕。

<tree :data="starwars" :render="renderContent"></tree>

renderContent傳入的第二個參數內含:

Param Type Description
root array 根節點
node object 當前節點
data object 當前節點的資料

而回傳的內容即在組合節點的HTML,其方式為回傳Virtual DOM,方式如下

return h('<current html's tag>', {<current html's props/style/event>}, [<inner html's h(...)> or value])

如果是最內層的方法記得放上data.title

先看個說明的例子:

renderContent(h, { root, node, data }) {
    return h('center', {
        style: { width: '100%',backgroundColor: 'green'}}, 
        [
            h('center', {
                style: { width: '70%', backgroundColor: 'black' }},
                [
                    h('span', { style: {width: '30%', backgroundColor: 'yellow' } }, data.title)
                ] 
            ),
        ]
    );
}

以上將輸出如下:

有了概念後,參考官網的範例可建立如下可新增/移除節點之Tree:


var app = new Vue({
    el: "#app",
    data: {
        starwars: [],
        buttonProps: {
            type: 'default',
            size: 'small',
        }
    },
    methods: {
        renderContent (h, { root, node, data }) {
            return h('span', {
                style: { display: 'inline-block', width: '100%'}
            }, [
                h('span', [ h('Icon', {
                                props: { type: 'ios-paper-outline' },
                                style: { marginRight: '8px' }
                            }), 
                            h('span', data.title)
                          ]),
                h('span', {
                    style: {display: 'inline-block',float: 'right',marginRight: '32px'}
                    }, [
                        h('Button', {
                            props: Object.assign({}, this.buttonProps, {icon: 'ios-add'}),
                            style: {marginRight: '8px'},
                            on: { click: () => { this.append(data) }}
                        }),
                        h('Button', {
                            props: Object.assign({}, this.buttonProps, { icon: 'ios-remove'}),
                            on: { click: () => { this.remove(root, node, data) }}
                        })
                    ])
            ]);
        },
        append(data) {
            const children = data.children || [];
            children.push({
                title: 'New node',
                expand: true
            });
            this.$set(data, 'children', children);
        },
        remove(root, node, data) {
            const parentKey = root.find(el => el === node).parent;
            const parent = root.find(el => el.nodeKey === parentKey).node;
            const index = parent.children.indexOf(data);
            parent.children.splice(index, 1);
        }

    },
    created() {
        this.starwars = FOO_DATA;
    }
})

Demo:

Sample code

更多應用可參考相關API官方文件


上一篇
iView - Cascader
下一篇
vue-sanitize
系列文
Vue.js套件介紹及範例33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
st880221
iT邦新手 5 級 ‧ 2019-05-18 14:11:45

請問樓主知道怎麼解這Tree Component memory leak的問題嗎?
資料量一大,傳入data之後,頁面會瞬間卡死一陣子,才會把樹render出來

我要留言

立即登入留言