npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

vue-draggable-tree

v1.1.6

Published

draggable tree

Readme

vue-draggable-tree

最容易使用的 vue 可拖拽树。

效果图

参考~~抄袭~~rc-tree实现的一个可拖拽树,样式参考ant-design

Example

online example: https://ltaoo.github.io/vue-draggable-tree/examples/index.html

Install

yarn add vue-draggable-tree

Usage

<template>
    <Tree
        draggable
        v-model="data"
        :afterInsert="afterInsert"
    ></Tree>
</template>

<script>
import Tree from '../tree';

const EXAMPLE_DATA = [
    {
        key: '0',
        title: '女装',
        children: [
            {
                key: '0-1',
                title: '风衣',
            },
            {
                key: '0-2',
                title: '外套',
            },
        ],
    },
    {
        key: '1',
        title: '男装',
    },
    {
        key: '2',
        title: '图书',
        children: [
            {
                key: '2-0',
                title: '小说',
                children: [
                    {
                        key: '2-0-0',
                        title: '九州牧云录',
                    },
                    {
                        key: '2-0-1',
                        title: '天空的城',
                    },
                    {
                        key: '2-0-2',
                        title: '三体',
                    },
                ],
            },
            {
                key: '2-1',
                title: '经管',
                children: [
                    {
                        key: '2-1-0',
                        title: '创京东',
                    },
                ],
            },
            {
                key: '2-2',
                title: '科技',
                children: [
                    {
                        key: '2-2-0',
                        title: 'JavaScript权威指南',
                    },
                    {
                        key: '2-2-1',
                        title: 'JavaScript高级程序设计',
                    },
                ],
            },
        ],
    },
];

export default {
    name: 'vue-draggable-tree-demo',
    components: {
        Tree,
    },
    data() {
        return {
            data: EXAMPLE_DATA,
        };
    },
    methods: {
        afterInsert() {
            console.log(this.data);
        },
    },
};
</script>

<style>

</style>

API

属性 | 说明 | 类型 | 默认值 | ---|---|---|---| data | 要渲染的数据 | Array | 空 draggable | 设置节点可拖拽(IE>8)| Boolean | false dragEnd | 拖拽结束后调用的事件 | function(ary, node, e) | - onDragEnter | dragenter 触发时调用 | function({event, node}) | - onDragLeave | dragleave 触发时调用 | function({event, node}) | - onDragOver | dragover 触发时调用 | function({event, node}) | - onDragStart | dragstart 触发时调用 | function({event, node}) | - onDrop | drop 触发时调用 | function({event, node}) | - onExpand | 展开/收起节点时触发 | function({event, node}) | - afterInsert | 在节点插入到指定位置后调用 | function() | - template | 自定义节点内容 | VueComponent | -

说明

树组件,分为两部分吧,首先是渲染,其次是渲染后处理拖动。

render

渲染其实比较简单,首先我们有「元数据」,我们定义下接口

interface SourceNode {
    key: string;
    title: string;
    children?: Array<SourceNode>;
    [propName: string]: any;
}

key 需要是唯一值。然后根据这个元数据生成 vnodeTree 组件要求 data 是数组,所以是生成了 vnode 组成的数组。 再使用 this.renderTreeNode 真正地去渲染。

// vChildren Array<VNode>,h createElement
const vChildren = loop(this.data, h, TreeNode);
<ul
    class="ant-tree tree"
    role="tree-node"
    unselectable="on"
>
    {vChildren.map((child, i) => this.renderTreeNode(child, i))}
</ul>

VNode 的接口长什么样呢?

interface VNode {
    tag: string;
    data: Object;
    children: Array<VNode>;
    // ...
}

React 中,JSX 其实是创建 React Element 的语法糖,这里也是类似,

参考 渲染函数 & JSX

drop

该组件核心概念在于,所有 TreeNode,无论层级多深,都是由 Tree 这个根组件去管理。每个节点有「位置」属性,类似 0、0-0 这样,个数表示层级,第二位数字表示在该层级的位置,如 '0-1' 表示第一层级的第二个节点。

- 图书
    - 经管
        - 创京东
        - 参与感
- 服装 <----- 这个节点就是 0-1

当拖动 Node 时,会触发相关事件

  • dragstart
  • dragenter
  • dragover
  • drop
  • dragend

dragstart,当拖动节点时调用;dragenter,当拖动时「被进入」节点触发,举例,拖动「三体」到「经管」这个 node 时,触发 dragenter 的是「经管」节点,而不是「三体」节点;

并且,当 enter 时,这里有一个黑科技,node 的实际大小要大于我们所看到的大小。当我们移动到「下边缘」时,实际上是已经移到了内部,只是我们看起来还没有到内部,通过鼠标位置与节点位置的计算,我们人为地划分了「上边缘」、「内部」和「下边缘」。

计算方式是先获取到目标节点距离屏幕顶部的距离(top)、目标节点高度(height)、当前鼠标距屏幕顶部距离(y),如果

  • 1、y < top 说明鼠标在节点上方
  • 2、y > top + height 说明鼠标在节点下方
  • 3、其他情况说明在节点内部

进阶

定制渲染内容

需要注意的问题

当在同组间移动时,先移除原先的,再插入,位置计算会有问题。

发布流程

如果对组件本身有修改,修改完成后更新 package.json 中的 version 字段,并且需要打包exampledist,分别运行

yarn build
yarn dist

然后可以先将新的包发布到 npm 上,运行:

npm publish

然后将源代码 pushgithub

如果只修改了 example,只需要 buildpush 源码即可。

todo

  • []优化发布流程
  • [x]代码整理
  • []examples 展示页用例完善
  • []增加 theme 以方便直接在 iview 或者 element 项目中使用
  • []增加 checkbox
  • []选中状态
  • []增加连接线
  • []增加禁用状态
  • []是否展开控制