精华内容
下载资源
问答
  • Vue树结构操作

    万次阅读 2018-07-09 22:49:21
    要把树结构的每一个节点都渲染成dom,需要对树结构进行递归遍历。Vue组件可以通过name选项的设置来递归的调用自己,因此渲染起来很方便。 本文简单实现了一下树结构的基本增删改等操作,后续还会继续对树结构渲染...

            树形结构是一种常用的数据结构,使用Vue怎么来渲染呢?要把树结构的每一个节点都渲染成dom,需要对树结构进行递归遍历。Vue组件可以通过name选项的设置来递归的调用自己,因此渲染起来很方便。  

            本文简单实现了一下树结构的基本增删改等操作,后续还会继续对树结构渲染(比如拖拽操作、大数据量渲染效率等)进行探索。

    代码比较简单,MyTree组件:

    <template>
      <div class="my-tree">
        <div
          class="brother"
          v-for="(data, idx) of treeData"
          :key="idx">
          <div class="node">
            <span @click="data.expand=!data.expand">
              <Button class="node-expand" type="text" icon="chevron-down" v-if="data.expand"></Button>
              <Button class="node-expand" type="text" icon="chevron-right" v-else></Button>
            </span>
            <input class="node-name" v-model="data.name" />
            <span class="node-menu">
              <span class="menu-item" title="添加同级节点" @click.stop="$emit('addBrother', $event, data)">
                <Icon type="plus-round"></Icon>
              </span>
              <span class="menu-item" title="添加下级节点" @click.stop="$emit('addChild', $event, data)">
                <Icon type="ios-plus-outline"></Icon>
              </span>
              <span class="menu-item" title=“删除” @click.stop="$emit('deleteNode', $event, data)">
                <Icon type="trash-a"></Icon>
              </span>
            </span>
          </div>
          <div
            class="children"
            v-if="data.children && data.children.length"
            v-show="data.expand">
            <my-tree
              @addBrother="addBrother"
              @addChild="addChild"
              @deleteNode="deleteNode"
              :treeData="data.children">
            </my-tree>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      name: 'my-tree',
      props: {
        treeData: {
          type: Array,
          default: () => [{
            id: 1,
            name: '一级节点1',
            expand: true,
            children: [{
              id: 2,
              expand: true,
              name: '二级节点1'
            }]
          },
          {
            id: 3,
            expand: true,
            name: '一级节点2',
            children: [{
              id: 4,
              expand: true,
              name: '二级节点1'
            },
            {
              id: 5,
              expand: true,
              name: '二级节点2',
              children: [{
                id: 6,
                expand: true,
                name: '三级节点'
              }]
            }]
          }]
        }
      },
      methods: {
        addBrother (event, data) {
          this.$emit('addBrother', event, data)
        },
        addChild (event, data) {
          this.$emit('addChild', event, data)
        },
        deleteNode (event, data) {
          this.$emit('deleteNode', event, data)
        }
      }
    }
    </script>
    
    <style lang="stylus" scoped>
    .children
      position relative
      padding-left 20px
    .node-expand
      width 1.5rem
      height 1.5rem
      padding-left 0
      padding-right 0
      padding-bottom 0
      padding-top 0
      &:focus
        box-shadow none
    
    .node-menu
      width 3rem
      display flex
      justify-content space-around
      .menu-item
        &:hover
          cursor pointer
    
    .brother
      display flex
      flex-direction column
      .node
        height 1.5rem
        display flex
        align-items center
        .node-name
          // border none
          // background none
          overflow-x visible
          &:focus
            outline none
    </style>

    组件使用,Tree.vue页面代码:

    <template>
      <div class="tree">
        <div class="tree-title">
          树结构
        </div>
        <my-tree
          @addBrother="addBrother"
          @addChild="addChild"
          @deleteNode="deleteNode">
        </my-tree>
      </div>
    </template>
    
    <script>
    import MyTree from '@/components/MyTree'
    
    export default {
      name: 'tree',
      components: {
        'my-tree': MyTree
      },
      data () {
        return {
          id: 100
        }
      },
      methods: {
        addBrother (event, data) {
          let parentData = this.getParentData(event.target)
          console.log(parentData)
          if (parentData) {
            let index = parentData.indexOf(data)
            if (index !== -1) {
              parentData.splice(index + 1, 0, this.newNode())
            }
          }
        },
        addChild (event, data) {
          if (!data.children) {
            this.$set(data, 'children', [])
          }
          data.children.push(this.newNode())
        },
        deleteNode (event, data) {
          let parentData = this.getParentData(event.target)
          if (parentData) {
            let index = parentData.indexOf(data)
            if (index !== -1) {
              parentData.splice(index, 1)
            }
          }
        },
        newNode () {
          let id = this.id++
          return {
            id,
            name: '新节点' + id,
            expand: true,
            children: []
          }
        },
        getParentData (node) {
          while (node && node.tagName !== 'BODY') {
            if (node.__vue__ && node.__vue__.$options.name === 'my-tree') {
              return node.__vue__.treeData
            }
            node = node.parentNode
          }
          return null
        }
      }
    }
    </script>
    
    <style lang="stylus" scoped>
    .tree
      padding 3rem 2rem
      text-align left
      .tree-title
        border-bottom 1px solid gray
        padding-bottom 0.5rem
        margin-bottom 1rem
    </style>

    这里使用了一些iView的图标标签,可以简单的使用iView来实现漂亮的效果,可以到其iView网了解使用方法。

    学习前端也几个月了,在开始使用Vue的很长一段时间里,对Vue一些选项的作用不甚了解,在Vue网都有比较清楚的介绍,比如递归渲染用到的name属性:

    name

    • 类型string

    • 限制:只有作为组件选项时起作用。

    • 详细

      允许组件模板递归地调用自身。注意,组件在全局用 Vue.component() 注册时,全局 ID 自动作为组件的 name。

    时常翻翻官网总会有意想不到的收获~。~

     

    展开全文
  • 数据结构为数组中包含对象–结构,用Vue组件的写法实现以下的效果: 形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据。本文为用Vue实现方式,另有一篇为用knockout.js的实现方法。 ...
  • vue 根据有多个子节点的数据动态生成树结构


    前言

    技术栈:vue + Quasar Framework
    在开发的时候想要在树结构里面每个节点数据都能实现某种功能(像表格一样有操作的功能),而且不能确定数据有多少层级。基于后续会想要添加节点间互相拖拽的功能,这里使用UI框架提供的树组件不理想,故用vue写一个。
    vue 根据有多个子节点的数据动态生成树结构。


    一、思路

    写一个树结构的封装组件,因为不知道数据的层级,所以在封装的组件里面调用自身,实现一个自身组件的嵌套,我们只需要在嵌套组件的时候做好有子节点才嵌套,无则不嵌套的判断。

    二、封装组件的代码

    1.组件里的template

    class=“row bg_row” 这种样式的写法是Quasar Framework框架里自带的,需要去看文档,如果没有用这个框架的,样式自己写,这里不用理会。

    <template>
      <div id="children_tree">
      	<!-- 将数据正常地循环展示 - 组件传入数据数组 parentTreeData -->
        <div v-for="item in parentTreeData" :key="item.category_id">
          <div class="row bg_row">
            <!-- 数据的左边部分 - showHidden点击方法是控制节点是否展开 -->
            <div class="col" @click="showHidden(item)">
              <i
                v-if="
                  item.son &&
                  item.son instanceof Array && 
                  item.son.length > 0 &&
                  !findTrue(item.category_id)
                "
                class="material-icons draicon"
                >arrow_right</i
              >
              <i
                v-else-if="
                  item.son &&
                  item.son instanceof Array && 
                  item.son.length > 0 &&
                  findTrue(item.category_id)
                "
                class="material-icons draicon"
                >arrow_drop_down</i
              >
              <i
                v-else
                class="material-icons draicon"
                style="padding-left: 38px"
              ></i>
              {{ item.name }}
            </div>
            <!-- 数据的右边放功能按钮的部分 - 接收传入的功能数组 btnOperates -->
            <div :class="`col-${5}`" style="text-align: right">
              <q-btn
                class="on-left"
                v-for="(btn, index) in btnOperates"
                :key="`btn_fun_${index}`"
                :label="btn.label || '按钮'"
                :color="btn.color || 'primary'"
                :outline="btn.outline || false"
                :size="btn.size || 'md'"
                @click="btn.fun(item)"
                unelevated
              />
            </div>
          </div>
          <!-- 调用自己 -->
          <children
            v-if="item.son && findTrue(item.category_id)"
            :key="item.category_id + 10000"
            :parent-tree-data="item.son"
            :tree-data="treeData"
            :btn-operates="btnOperates"
            style="margin-left: 15px"
          ></children>
        </div>
      </div>
    </template>
    

    2.组件里的script

    <script>
    export default {
      name: 'children',
      props: {
        // 传入数据
        parentTreeData: {
          type: Array,
          default: () => {
            return []
          }
        },
        // 功能按钮
        btnOperates: {
          type: Array,
          default: () => {
            return []
          }
        }
      },
      data() {
        return {
          // 用于存储是否展开显示的层级
          showArr: []
        }
      },
      methods: {
        // 展开或者隐藏下级目录
        showHidden(item) {
          if (this.showArr.includes(item.category_id)) {
            // 存在
            this.remove(this.showArr, item.category_id)
          } else {
            // 不存在
            this.showArr.push(item.category_id)
          }
        },
        remove(arr, item) {
          for (let index = 0; index < arr.length; index++) {
            const element = arr[index]
            if (element == item) {
              arr.splice(index, 1)
            }
          }
        },
        // 是否展示
        findTrue(id) {
          return this.showArr.includes(id)
        }
      }
    }
    </script>
    

    3.style

    .bg_row {
      width: 100%;
      height: 50px;
      line-height: 50px;
      background-color: #eeeeee;
      color: #000000;
      margin: 2px 0 2px 0;
    }
    
    .draicon {
      font-size: 32px;
      color: #7e7e7e;
      padding-left: 6px;
    }
    

    三、使用步骤

    1.调用组件

    <cate-tree
       :parentTreeData="list"
       :btnOperates="operates"
    />
    

    2.传入数据

    import cateTree from './components/cate-tree' // 组件名称自定义哈
    export default {
    	components: { cateTree },
    	data() {
    	    return {
    	      list: [
    	        {
    	          category_id: 100,
    	          name: '父级一',
    	          parent_id: 0,
    	          son: [
    	            {
    	              category_id: 103,
    	              name: '子级一',
    	              parent_id: 100,
    	              son: [
    	                {
    	                  category_id: 106,
    	                  name: '孙级一',
    	                  parent_id: 103,
    	                  son: [
    	                    {
    	                      category_id: 107,
    	                      name: '曾孙级一',
    	                      parent_id: 106
    	                    }
    	                  ]
    	                }
    	              ]
    	            }
    	          ]
    	        },
    	        {
    	          category_id: 101,
    	          name: '父级二',
    	          parent_id: 0,
    	          son: [
    	            {
    	              category_id: 104,
    	              name: '子级一',
    	              parent_id: 101
    	            }
    	          ]
    	        },
    	        {
    	          category_id: 102,
    	          name: '父级三',
    	          parent_id: 0,
    	          son: []
    	        }
    	      ],
    	      operates: [
    	        {
    	          label: '當前分類商品',
    	          color: 'primary',
    	          size: 'md',
    	          outline: true,
    	          fun: (row) => {
    	            // 放功能方法
    	          }
    	        },
    	        {
    	          label: '修改',
    	          color: 'primary',
    	          size: 'md',
    	          outline: false,
    	          fun: (row) => {
    	            // 放功能方法
    	          }
    	        },
    	        {
    	          label: '刪除',
    	          color: 'red',
    	          size: 'md',
    	          outline: false,
    	          fun: (row) => {
    	            // 放功能方法
    	          }
    	        }
    	      ]
    	    }
        }
    }
    

    3.实现的效果

    如下图(部分展开)
    vue部分展开的树结构
    (全部展开)
    vue多级全部展开的树结构


    总结

    传入的数据改成是接口获取,因为是组件调用自身,所以不管数据有多少层级,都能渲染。

    展开全文
  • 怎么在vue中利用递归组件实现一个形控件发布时间:2021-06-11 17:26:48来源:亿速云阅读:81作者:Leah本篇文章为大家展示了怎么在vue中利用递归组件实现一个...结构2Vue.component('tree',{name:"tree",templ...

    怎么在vue中利用递归组件实现一个树形控件

    发布时间:2021-06-11 17:26:48

    来源:亿速云

    阅读:81

    作者:Leah

    本篇文章为大家展示了怎么在vue中利用递归组件实现一个树形控件,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

    vue版的树形控件html>

    树形结构2

    Vue.component('tree', {

    name:"tree",

    template:`

    • {{ item.label }}

    `,

    props:["folder","select"],

    })

    // 

    var app = new Vue({

    el:"#app",

    data:{

    msg:"hello world",

    trees: [

    {

    id:1,

    label:"1级目录1",

    show:false,

    children:[

    {

    id:"1-1",

    label:"1.1目录"

    },

    {

    id:"1-2",

    label:"1.2目录"

    },

    {

    id:"1-3",

    label:"1.3目录"

    },

    ]

    },

    {

    id:2,

    label:"1级目录2",

    show:false

    },

    {

    id:3,

    label:"1级目录3",

    show:false,

    children:[

    {

    id:"3-1",

    label:"3.1目录"

    },

    {

    id:"3-2",

    label:"3.2目录",

    show:false,

    children:[

    {

    id:"3-2-1",

    label:"3.2.1目录"

    },

    {

    id:"3-2-2",

    label:"3.2.2目录"

    },

    {

    id:"3-2-3",

    label:"3.2.3目录"

    }

    ]

    }

    ]

    },

    {

    id:4,

    label:"1级目录4",

    show:false,

    children:[

    {

    id:"4-1",

    label:"4.1目录"

    },

    {

    id:"4-2",

    label:"4.2目录",

    show:false,

    children:[

    {

    id:"4-2-1",

    label:"4.2.1目录"

    }

    ]

    }

    ]

    },

    {

    id:5,

    label:"1级目录5",

    show:false,

    children:[

    {

    id:"5-1",

    label:"5.1目录",

    show:false,

    children:[

    {

    id:"5-1-1",

    label:"5.1.1目录"

    },

    {

    id:"5-1-2",

    label:"5.1.2目录",

    show:false,

    children:[

    {

    id:"5-1-2-1",

    label:"5.1.2.1目录"

    },

    ]

    }

    ]

    },

    {

    id:"5-2",

    label:"5.2目录",

    show:false

    }

    ]

    },

    ]

    },

    methods:{

    clickHandler(){

    console.log(23333);

    },

    select(data){

    console.log(data);

    }

    },

    mounted(){

    console.log(this.trees);

    }

    })

    看下结果

    e1f16658abc30390c98dd115b9f89875.png

    当然我用的全局组件,如果用vue-cli搭建的环境是一样的,引入组件就可以了,但是一定要注意,组件内必须要用name属性,而且name的名称要和组件名称(组件标签名称)一致才可以

    贴一个项目中用的模板吧,相当于做笔记了

    • {{ item.label }}

    import { mapGetters , mapActions} from 'vuex';

    export default{

    name:"DatabaseTree",

    props:["folder","select","currentId"],

    data(){

    return{

    addParams:{

    label:"",

    children:[]

    },

    noteData:{

    children:[]

    }

    }

    },

    computed:{

    ...mapGetters(["catalog"])

    },

    methods:{}

    }

    .dataBaseTree{

    padding-left:12%;

    line-height:40px;

    ul{

    padding-left:12%;

    line-height:40px;

    li{

    span{

    display:inline-block;

    padding-left:23%;

    height:100%;

    width:120%;

    color:#ababab;

    font-size:14px;

    position: relative;

    cursor: pointer;

    &:hover{

    background: #EDF0F5;

    }

    .folderIcon{

    color:#BCBCBC;

    position: absolute;

    top:-1px;

    left:22px;

    }

    }

    }

    }

    li{

    position: relative;

    span{

    display:inline-block;

    padding-left:40px;

    font-size:14px;

    height:100%;

    width:120%;

    cursor: pointer;

    position: relative;

    right:25px;

    top:-2px;

    color:#ababab;

    &:hover{

    background: #EDF0F5;

    }

    .titleIcon{

    color:#C3C3C3;

    font-size:16px;

    position: absolute;

    top:12px;

    left:16px;

    }

    .folderIcon{

    color:#BCBCBC;

    position: absolute;

    top:-1px;

    left:22px;

    }

    }

    .active{

    background: #EDF0F5;

    }

    }

    }

    vue版的就到这里了

    下面贴一个原生js版的,感兴趣的小伙伴可以继续往下看html>

    Document

    var tree=[

    {

    id:1,

    label:"1级目录1",

    children:[

    {

    id:"1-1",

    label:"1.1目录"

    },

    {

    id:"1-2",

    label:"1.2目录"

    },

    {

    id:"1-3",

    label:"1.3目录"

    },

    ]

    },

    {

    id:2,

    label:"1级目录2",

    },

    {

    id:3,

    label:"1级目录3",

    children:[

    {

    id:"3-1",

    label:"3.1目录"

    },

    {

    id:"3-2",

    label:"3.2目录",

    children:[

    {

    id:"3-2-1",

    label:"3.2.1目录"

    },

    {

    id:"3-2-2",

    label:"3.2.2目录"

    },

    {

    id:"3-2-3",

    label:"3.2.3目录"

    }

    ]

    }

    ]

    },

    {

    id:4,

    label:"1级目录4",

    children:[

    {

    id:"4-1",

    label:"4.1目录"

    },

    {

    id:"4-2",

    label:"4.2目录",

    children:[

    {

    id:"4-2-1",

    label:"4.2.1目录"

    }

    ]

    }

    ]

    },

    {

    id:5,

    label:"1级目录5",

    children:[

    {

    id:"5-1",

    label:"5.1目录",

    children:[

    {

    id:"5-1-1",

    label:"5.1.1目录"

    },

    {

    id:"5-1-2",

    label:"5.1.2目录",

    children:[

    {

    id:"5-1-2-1",

    label:"5.1.2.1目录"

    },

    ]

    }

    ]

    },

    {

    id:"5-2",

    label:"5.2目录"

    }

    ]

    },

    ];

    var render = function(tree) {

    if (!tree) return null

    var ul = document.createElement('ul');

    for(var i = 0; i 

    var li = document.createElement('li')

    // 创建span标签

    var span = document.createElement('span'); span.innerText = tree[i].label;

    li.appendChild(span);

    if(tree[i].children){

    var sub = render(tree[i].children);

    li.appendChild(sub);

    }

    ul.appendChild(li);

    }

    return ul

    };

    document.body.innerHTML = '';

    document.body.appendChild(render(tree));

    上述内容就是怎么在vue中利用递归组件实现一个树形控件,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注亿速云行业资讯频道。

    展开全文
  • 基于vue结构

    千次阅读 2019-07-12 16:40:04
    基于vue结构封装 主要功能:添加同级、添加子级、拖拽、双击名称进行修改 依赖:vue、element-ui、sass git地址:https://github.com/rongyanping/vue-tree 封装 MyTree.vue <template> <div class=...

    基于vue的树形结构封装

    主要功能:添加同级、添加子级、拖拽、双击名称进行修改
    依赖:vue、element-ui、sass
    git地址:https://github.com/rongyanping/vue-tree

    封装 MyTree.vue

    <template>
      <div class="my_tree">
        <div
          class="brother"
          v-for="(data, idx) of treeData"
          :key="idx">
          <div class="node"
               @drop="drop($event,treeData,idx)"
               @dragover="allowDrop($event,treeData,idx)">
            <span @click="data.expand=!data.expand">
              <i class="el-icon-caret-bottom" v-if="data.expand && data.type==='group'"></i>
              <i class="el-icon-caret-right" v-if="!data.expand && data.type==='group'"></i>
            </span>
            <div :draggable="!data.editable"
                 :class="{'cname_child':true,'cname_child_edit':data.editable}"
                 :contentEditable="data.editable"
                 @dragstart="drag($event,treeData,idx)"
                 @dblclick="dbclickHandle($event,treeData,idx)"
                 @click="data.expand=!data.expand">
                {{data.name}}
            </div>
            <button class="operation_btn" v-if=" data.type==='group'" @click="addBrother($event,data)">添加同级</button>
            <button class="operation_btn" v-if=" data.type==='group'" @click="addChild($event,data)">添加子级</button>
            <button class="operation_btn" v-if=" data.type==='group'"  @click="deleteNode($event, data)">删除</button>
          </div>
          <div
            class="children"
            v-if="data.children && data.children.length" v-show="data.expand">
            <my-tree
              :treeData="data.children"
              @addBrother="addBrother"
              @addChild="addChild"
              @deleteNode="deleteNode"
              @dragBegin="drag"
              @dragStop="drop"
              @dbclickChangeName="dbclickChangeName">
            </my-tree>
          </div>
        </div>
      </div>
    </template>
    <script>
      export default {
        name: 'MyTree',
        props: {
          treeData: {
            type: Array,
            default: () => [{
              id: 1,
              name: '分组1',
              expand: true,
              type:'group',
              children: [{
                id: 2,
                expand: true,
                name: '相机1',
                type:'camera',
              }]
            },
              {
                id: 3,
                expand: true,
                name: '分组2',
                type:'group',
                children: [
                  {
                    id: 5,
                    expand: true,
                    name: '分组2-1',
                    type:'group',
                    children: [{
                      id: 6,
                      expand: true,
                      name: '相机2-1',
                      type:'camera',
                    }]
                  }]
              }]
          },
    
        },
        methods: {
          // 双击
          dbclickHandle(event,data,index){
            const _this = this;
            this.$set(data[index],'editable',true);
            let target = event.target;
            setTimeout(function () {
              target.focus();
              let selection = getSelection();
              // 判断选定对象范围是编辑框还是文本节点
              if(selection.anchorNode.nodeName === '#text'){
                // 如果是文本节点则先获取光标对象
                let range = selection.getRangeAt(0);
                // 获取光标对象的范围界定对象,一般就是textNode对象
                let textNode = range.startContainer;
                // 光标移动到到原来的位置加上新内容的长度 rangeStartOffset +
                range.setStart(textNode, target.innerHTML.length);
                // 光标开始和光标结束重叠
                range.collapse(true);
                // 清除选定对象的所有光标对象
                selection.removeAllRanges();
                // 插入新的光标对象
                selection.addRange(range);
              }
              target.onblur = function () {
                _this.$emit('dbclickChangeName',data,index,target.innerText);
                // console.log('失焦---------',target.innerText)
              }
            },10);
          },
          // 传给父级新名称
          dbclickChangeName(data,index,name){
            this.$emit('dbclickChangeName',data,index,name);
            // console.log('====',name)
          },
          // 开始拖拽
          drag(event,data,index){
            this.$emit('dragBegin',event,data,index);
          },
          // 拖拽结束
          drop(event,data,index){
            event.preventDefault();
            this.$emit('dragStop',event,data,index);
            // console.log('drop>>>>>',event,data,index);
          },
          // 在何处放置被拖动的数据
          allowDrop(event,data,index){
            event.preventDefault();
          },
          // 添加子级
          addChild (event, data) {
            this.$emit('addChild', event, data)
          },
          // 添加同级
          addBrother (event, data) {
            this.$emit('addBrother', event, data);
          },
          // 删除
          deleteNode (event, data) {
            this.$emit('deleteNode', event, data)
          },
        }
      }
    </script>
    <style  scoped lang="scss">
      .my_tree{
        .brother{
          display: flex;
          flex-direction: column;
          padding-top: 20px;
          .node{
            display: flex;
            align-items: center;
            .cname_child{
              border-style: none;
              outline: none;
              width: 100px;
            }
            .cname_child_edit{
              border: 1px solid gray;
            }
            .operation_btn{
              margin-left: 20px
            }
          }
          .children {
            position: relative;
            margin-left: 20px;
          }
        }
      }
    
      input[disabled],input:disabled,input.disabled{
        color: #333;
        -webkit-text-fill-color:#333;
        opacity: 1;
        background-color:white;
      }
    </style>
    
    

    调用MyTree.vue

    <template>
      <div class="tree">
        <my-tree
          @addBrother="addBrother"
          @addChild="addChild"
          @deleteNode="deleteNode"
          :treeData="datas"
          @dragBegin="drag"
          @dragStop="drop"
          @dbclickChangeName="dbclickChangeName">
        </my-tree>
        <div v-show="iptVisible" style="margin-top: 20px">
          <span>分组名:</span>
          <input type="text" v-model="groupName">
          <button @click="submitGroup">提交</button>
        </div>
        <div v-show="iptVisible2" style="margin-top: 20px">
          <span>子级名:</span>
          <input type="text" v-model="groupName2">
          类型:分组/相机
          <input type="text" v-model="addType">
          <button @click="submitChild">提交</button>
        </div>
      </div>
    </template>
    <script>
      import MyTree from './MyTree'
      export default {
        name: 'tree3',
        components: {
          'my-tree': MyTree
        },
        data () {
          return {
            id: 100,
            datas:[{
              id: 1,
              name: '分组1',
              expand: true,
              type:'group',
              editable:false,
              children: [{
                id: 2,
                expand: true,
                name: '相机1',
                type:'camera',
                editable:false,
              }]
            },
              {
                id: 3,
                expand: true,
                name: '分组2',
                type:'group',
                editable:false,
                children: [
                  {
                    id: 5,
                    expand: true,
                    name: '分组2-1',
                    type:'group',
                    editable:false,
                    children: [{
                      id: 6,
                      expand: true,
                      name: '相机2-1',
                      type:'camera',
                      editable:false,
                    },{
                      id: 7,
                      expand: true,
                      name: '相机2-2',
                      type:'camera',
                      editable:false,
                    }]
                  }]
              }],
            dragData:null,
            dragEvent:null,
            dragIndex:null,
    
            cid:10,
            groupName:'',
            iptVisible:false,
            brotherData:null,
            brotherEvent:null,
    
            addChildData:null,
            addChildEvent:null,
            iptVisible2:false,
            groupName2:'',
            addType:'group'
          }
        },
        methods: {
          /* 操作数据全部在本组件内部 */
    
          // 接收新名称
          dbclickChangeName(data,index,changeName){
            // 发送请求:修改名称
            this.$set(data[index],'name',changeName);
            this.$set(data[index],'editable',false);
            console.log('dbclick=====',changeName);
          },
    
          /* 拖拽 */
          drag(event,data,index){
            this.dragData = data;
            this.dragEvent = event;
            this.dragIndex = index;
            // console.log('dragStart=====',this.dragData,index);
          },
          drop(event,data,index){
            /* 拖拽只能是拖到某个分组内 成为该分组的子级 */
            /* 松开鼠标---调取修改接口,成功后添加新数据,删除之前位置*/
            const _this = this;
            data[index].children.push(this.dragData[this.dragIndex]);
            // 删除原有数据
            setTimeout(function () {
              console.log('dragOver=====',_this.dragEvent,_this.dragData);
              _this.deleteNode(_this.dragEvent,_this.dragData[_this.dragIndex])
            },10);
          },
    
          // 添加同级
          addBrother (event,data) {
            this.iptVisible = true;
            this.id++;
            this.brotherData = data;
            this.brotherEvent = event;
            console.log('addBrother>>>>',this.brotherData);
          },
          submitGroup(){
            let parentData = this.getParentData(this.brotherEvent.target);
              // console.log('parentData========',this.brotherEvent.target);
                if (parentData) {
                  let index = parentData.indexOf(this.brotherData);
                  if (index !== -1) {
                    parentData.splice(index + 1, 0, {
                      id: this.id,
                      name: this.groupName,
                      expand: false,
                      type:'group',
                      children: []
                    })
                  }
            }
    
          },
    
          // 添加子级
          addChild (event, data) {
            this.iptVisible2 = true;
            this.cid++;
            this.addChildData = data;
            console.log(this.addChildData)
            // // data 父级数据
            // console.log('addchild===tree3==',data);
            // if (!data.children) {
            //   this.$set(data, 'children', [])
            // }
            //   data.children.push(this.newNode('camera'))
            //   console.log('data====',data)
          },
          submitChild(){
            if(!this.addChildData.children){
              this.$set(this.addChildData, 'children', [])
            }
            if(this.addType==='group'){
              this.addChildData.children.push({
                id: this.cid,
                children:[],
                expand: false,
                name: this.groupName2,
                type:'group',
              })
            }
            else {
              this.addChildData.children.push({
                id: this.cid,
                expand: true,
                name: this.groupName2+this.cid,
                type:'camera',
              })
            }
          },
    
          // 删除组
          deleteNode (event, data) {
            console.log('del====',event,data)
            let parentData = this.getParentData(event.target);
            if (parentData) {
              let index = parentData.indexOf(data);
              if (index !== -1) {
                parentData.splice(index, 1)
              }
            }
          },
    
          newNode (type) {
            let id = this.id++;
            return {
              id,
              name: type==='group'?'新分组' + id:'新相机'+id,
              expand: false,
              children: [],
              type:type
            }
          },
          getParentData (node) {
            while (node && node.tagName !== 'BODY') {
              // console.log('node=====',node,node.__vue__)
              if (node.__vue__ && node.__vue__.$options._componentTag === 'my-tree') {
                return node.__vue__.treeData
              }
              node = node.parentNode
            }
            return null
          }
        }
      }
    </script>
    <style lang="scss" scoped>
      .tree{
        padding: 50px 20px;
        text-align: left;
      }
      .tree-title{
        border-bottom: 1px solid gray;
        padding-bottom: 10px;
        margin-bottom: 10px;
      }
    </style>
    
    
    展开全文
  • Vue 组件

    千次阅读 2018-09-29 22:07:01
    因为项目中使用比较多形组件的原因,尝试使用过iview以及element-ui的组件,两个组件库都非常优秀,但是在用它们的组件来实现需求时都不甚满意。主要体现在样式的难于控制、以及操作的便捷性上。在阅读element...
  • Vue结构简单实现

    千次阅读 2018-04-25 18:12:10
    Vue结构简单实现效果代码&lt;template &gt; &lt;div&gt; &lt;grouplists :datas='datas'&gt;&lt;/grouplists&gt; &lt;/div&gt; &lt;/template&gt; &...
  • Vue 模板

    2019-10-02 23:01:58
    Vue中,Vue模板对应的就是Vue中的View(视图)部分,也是Vue重中之一,而在Vue中要了解Vue模板我们就需要从两个方面来着手,其一是Vue模板语法,其二就是模板渲染。Vue模板语法是Vue中常用的技术之一,除非在...
  • 数据结构为数组中包含对象--结构,用Vue组件的写法实现以下的效果: 形列表,缩进显示层级,第5级数据加底色,数据样式显色,点击展开折叠数据。本文为用Vue实现方式,另有一篇为用knockout.js的实现方法。...
  • vue tree结构仿文件夹目录

    千次阅读 2020-12-24 21:40:10
    vue 结构利用vue组件自己调用自己,循环遍历生成结构。 组件调用自己时应绑定 name属性 拓展:给组件命名的三大作用 1.允许组件模板递归地调用自身; 2.指定 name 选项的另一个好处是便于调试。有名字的组件...
  • 如果在模板中定于了 的数据源如下: 那么在当前Vue组件实例中定义并初始化数据源 export default { name: 'Tree', data(){ return{ nodeData: [ { id:999, labelName:root, children:[] }
  • vue+element 实现树结构

    千次阅读 2019-06-14 17:54:21
    },//这个是我们要展示的模板 defaultcheckedkeys: [],//这个是获取详情或者想要设置的默认值 defaultexpandedkeys: [],//这个是获取详情或者想要设置的默认值 handleCheckChange(data, checked, ...
  • vue 文件的构成熟悉 vue 的同学应该都知道,vue 单文件模板中一般含有三个部分,template,script,style。但是在编译后的 js 文件中,我们却没法在代码中直接找...
  • vue源码结构分析

    2020-03-25 14:07:32
    它包括把模板解析成ast语法优化,代码生成等功能。 编译的工作可以在构建时做(借助webpack、vue-loader等辅助插件);也可以在运行时做,使用包含构建功能的vue.js。显然,编译是一项耗性能的工作...
  • Vue.js的核心是一个允许采用简洁的模板语法来声明式地将数据渲染进DOM的系统。 插值: 文本:数据绑定最常见的形式就是使用双大括号的文本插值。<div id="app"> <p>{{ message }}</p> </div&...
  • vue基于webpack 模板的目录结构以及目录作用的解析

    千次阅读 多人点赞 2017-12-16 09:49:26
    一个vue目录建好如下: 1.build 2.config 3.node_modules 4.src 5.static 6.babelrc babelrc文件是babel的配置文件 主要适用于编译es6转义为es5 一般用2个插件es2015,stage-2,transfer-runtime ...
  • Vue基础之模板语法

    多人点赞 2020-03-17 22:15:21
    Vue 是什么? Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架 vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合 使用Vue将helloworld 渲染到页面上 <div id=...
  • vue 文件的构成熟悉 vue 的同学应该都知道,vue 单文件模板中一般含有三个部分,template,script,style。但是在编译后的 js 文件中,我们却没法在代码中直接找到这三部分,如果我们想从编译后的 js 中获取原始模板...
  • vue树形组件 维树图 (vue-tree-chart) A vue2 component to display tree chart. 显示树形图的vue2组件。 安装 (Install) npm i vue-tree-chart --save 用法 (Usage) in template: 在模板中: <TreeChart :...
  • vue树组件上移下移功能 Vue可拖动的嵌套树 (vue-draggable-nested-tree) This is a draggable tree component. This component does not have css, you need to add your style refer to demo. The demo style is ...
  • 通过查看vue源码,可以知道Vue源码中使用了虚拟DOM(Virtual Dom),虚拟DOM构建经历 template编译成AST语法 -> 再转换为render函数 最终返回一个VNode(VNode就是Vue的虚拟DOM节点) 。本文通过对Vue源码中的AST...
  • Vue模板编译原理

    2020-08-21 16:30:28
    Vue 3 发布在即,本来想着直接看看 Vue 3 的模板编译,但是我打开 Vue 3 源码的时候,发现我好像连 Vue 2 是怎么编译模板的都不知道。从小鲁迅就告诉我们,不能一口吃成一个胖子,那我只能回头看看 Vue 2 的模板编译...
  • Vue.js 模板解析器原理

    千次阅读 2019-04-03 05:18:13
    本文来自《深入浅出Vue.js》模板编译原理篇的第九章,主要讲述了如何将模板解析成AST,这一章的内容是全书最复杂且烧脑的章节。本文排版较为紧凑和图片是未经加工的原稿,真实纸质书的排版和图片会更加精致。 通过...
  • 日前,在工作中有一个类似chrome书签管理器的需求,在调研了iview的Tree组件,Vue-dragging,Vue-...本文着重实现结构的展示,拖拽功能的完善后续会完善。 Vue作为组件化的框架,原则上所有的页面元素都由数据...
  • vue模板编译

    2020-10-31 18:35:58
    弄懂vue模板编译需要弄清 编译的目的 什么时候编译 编译过程 编译的目的 我们知道,html代码可以直接书写template字符串,也可以写render函数,那么template和render有什么关系? new Vue({ el: '#app', ...
  • vue解析模板的解释

    2020-06-04 00:07:30
    VUE的mount过程中,template会被编译成AST语法,AST是指抽象语法,或者语法,是指源代码中的抽象语法结构的树状表现形式 解析实例 实现将模板解析成AST <div> <p>{{name}}</p> </div&...
  • 基于html5 drag api实现的vue树形拖拽组件

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,273
精华内容 3,309
关键字:

vue树结构模板

vue 订阅