使用vue自定义了一个递归组件。
不多说,直接上代码。
纯列表展示(icon样式使用的bootstrap的glyphicon):

Vue.component(\'tree-list\', {
    template: `
        <ul class=\"tree-list\">
            <li v-for=\"(item, index) in list\">
                <div @click=\"toggle(item, index)\">
                    <i :class=\"[\'icon\', \'glyphicon\', getIcon(item, index)]\"></i>
                    <span>{{ item.name }}</span>
                </div>
                <tree-list v-if=\"scope[index]\" :list=\"item.children\"></tree-list>
            </li>
        </ul>
    `,
    props: {
        list:  Array
    },
    data () {
        return {
            scope: {}
        }
    },
    methods: {
        getIcon(item, index) {
            const self = this
            if (!item.children || item.children.length==0) {
                return \"glyphicon-file\"
            }
            if (self.scope[index]) {
                return \'glyphicon-folder-open\'
            }
            return \'glyphicon-folder-close\'
        },
        toggle (item, index) {
            const self = this
            if (item.children && item.children.length) {
                self.$set(self.scope, index, !self.scope[index]);
            }
        }
    }
})

可自行扩展增、删、改功能。
遇到的几个问题记录下:
1、单击展开,双击修改,出现点击冲突
拟可用解决方案:单击事件使用setTimeout延时执行,双击事件clearTimeout
2、input输入框自动获取焦点(官方方案

<input v-focus/>
directives: {
    focus : {
        inserted: (el)=> {
            el.focus()
        }
    }
}
钩子函数说明:

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。
componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind:只调用一次,指令与元素解绑时调用。

收藏 打印