Edit in JSFiddle

<div id="demo">
    <ul>
        <!--
            wrap the raw data with `model` alias so we
            can manage view state without polluting the
            original data
        -->
        <li v-component="folder" v-with="model: treeData"></li>
    </ul>
</div>

<script type="text/x-template" id="folder-template">
    <div class="item folder" v-on="click: open = !open">
        {{model.name}} [{{open ? '-' : '+'}}]
    </div>
    <ul v-show="open">
        <li v-repeat="model: model.children | orderBy 'type'"
            v-component="{{model.type}}">
        </li>
    </ul>
</script>

<script type="text/x-template" id="file-template">
    <div class="item file">{{model.name}}</div>
</script>
Vue.component('folder', {
    template: '#folder-template',
    data: {
        open: false
    }
})

Vue.component('file', {
    template: '#file-template'
})

var menu = new Vue({
    el: '#demo',
    data: {
        treeData: {
            name: 'My Tree',
            children: [
                { type: 'file', name: 'hello' },
                { type: 'file', name: 'wat' },
                {
                    type: 'folder',
                    name: 'child folder',
                    children: [
                        {
                            type: 'folder',
                            name: 'child folder',
                            children: [
                                { type: 'file', name: 'hello' },
                                { type: 'file', name: 'wat' }
                            ]
                        },
                        { type: 'file', name: 'hello' },
                        { type: 'file', name: 'wat' },
                        {
                            type: 'folder',
                            name: 'child folder',
                            children: [
                                { type: 'file', name: 'hello' },
                                { type: 'file', name: 'wat' }
                            ]
                        }
                    ]
                }
            ]
        }
    }
})
.item {
    cursor: pointer;
    font-family: monospace;
    color: #999;
}
.item.folder {
    color: #333;
}
ul {
    padding-left: 1em;
    list-style-type: circle;
}