在树视图中选择和取消选择节点 - vuejs

时间:2018-05-14 04:20:05

标签: javascript vue.js vuejs2

我是VueJS的新手。我一直在努力从vuejs文档中自定义树视图示例:Example

在树形视图中选择项目时,我无法理解如何取消选择,即取消设置先前所选项目的类别。我尝试过的一些方法包括

  • 使用Vue.prototype设置全局变量并在计算函数中访问它,在这种情况下,计算函数甚至不运行。
  • 我知道传递的事件对象。使用它和jQuery,删除以前选择的div的类将工作,但这似乎是一个黑客。
  • 在点击事件中设置data中所选项目的数组,并在计算函数中访问它。这也行不通。

有没有办法可行或者我不理解某事?

我正在处理的codepen链接:Codepen。要选择节点,只需单击节点并尝试选择其他节点。上一个节点未被清除。

谢谢!

更新

以下答案有效但如果在其他地方点击则会删除所选的课程。我想要一个解决方案,只有在我点击其他节点时才会删除所选类。我所要做的就是创建一个Event Bus并将之前选择的组件对象存储在父变量中。在单击新节点时,将发出一个全局事件,该事件将由主实例方法监听。在那里,它将设置一个布尔值,它将取消设置前一个组件选择,另一个布尔值将所选类设置为新的组件对象。我不确定是否存在更好的方法。

更新了codepen并进行了一些更改:CodePen link

1 个答案:

答案 0 :(得分:1)

这与VueJS无关,我们必须通过在文件夹节点聚焦时设置所需的css属性来使用CSS。

//https://github.com/vuejs/Discussion/issues/356
// demo data
Vue.prototype.$selectedNode = []
var data = {
  name: 'My Tree',
  children: [{
      name: 'hello'
    },
    {
      name: 'wat'
    },
    {
      name: 'child folder',
      children: [{
          name: 'child folder',
          children: [{
              name: 'hello'
            },
            {
              name: 'wat'
            }
          ]
        },
        {
          name: 'hello'
        },
        {
          name: 'wat'
        },
        {
          name: 'child folder',
          children: [{
              name: 'hello'
            },
            {
              name: 'wat'
            }
          ]
        }
      ]
    }
  ]
}

// define the item component
Vue.component('item', {
  template: '#item-template',
  props: {
    model: Object
  },
  data: function() {
    return {
      open: false,
      selectedNode: []
    }
  },
  computed: {
    isFolder: function() {
      return this.model.children &&
        this.model.children.length
    },
    setChevronClass: function() {
      return {
        opened: this.isFolder && this.open,
        closed: this.isFolder && !this.open,
        folderChevronSpan: this.isFolder
      }
    },
    setSelected: function() {
      if (this.selectedNode.length > 0 && this.selectedNode[0].title == this.model.name)
        return true;
      else
        return false;
    }
  },
  methods: {
    toggle: function() {
      if (this.isFolder) {
        this.open = !this.open
        this.$refs.toggler.focus();
      }
    },
    changeType: function() {
      if (!this.isFolder) {
        Vue.set(this.model, 'children', [])
        this.addChild()
        this.open = true
      }
    },
    addChild: function() {
      this.model.children.push({
        name: 'new stuff'
      })
    },
    selectNode: function() {
      this.selectedNode = [];
      this.selectedNode.push({
        'title': this.model.name,
        'isSelected': true
      });
    }
  }
})

// boot up the demo
var demo = new Vue({
  el: '#demo',
  data: {
    treeData: data
  }
})
body {
  font-family: Menlo, Consolas, monospace;
  color: #444;
}

.item {
  cursor: pointer;
}

.folderTitleSpan:hover {
  font-weight: bold;
  border: 1px solid darkblue;
}

.folderTitleSpan:focus,
li span:nth-child(1):focus+.folderTitleSpan {
  background-color: darkblue;
  color: white;
}

.node,
.add {
  list-style-type: none;
  padding-left: 10px !important;
}

.folderChevronSpan::before {
  color: #444;
  content: '\25b6';
  font-size: 10px;
  margin-left: -1em;
  position: absolute;
  transition: -webkit-transform .1s ease;
  transition: transform .1s ease;
  transition: transform .1s ease, -webkit-transform .1s ease;
  -webkit-transition: -webkit-transform .1s ease;
}

.folderChevronSpan.opened::before {
  transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
}

ul {
  padding-left: 1em;
  line-height: 1.5em;
  list-style-type: dot;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17-beta.0/vue.js"></script>
<!-- item template -->
<script type="text/x-template" id="item-template">
  <li>
    <span :class="setChevronClass" tabindex="0" ref="toggler" @click="toggle">  
  </span>
    <span @click="selectNode" tabindex="1" :class="{folderTitleSpan: isFolder}">
      {{ model.name }}
      </span>
    <span v-if="isFolder">[{{ open ? '-' : '+' }}]</span>

    <ul v-show="open" v-if="isFolder">
      <item class="item node" v-for="(model, index) in model.children" :key="index" :model="model">
      </item>
      <li class="add" @click="addChild">+</li>
    </ul>
  </li>
</script>

<p>(You can double click on an item to turn it into a folder.)</p>

<!-- the demo root element -->
<ul id="demo">
  <item class="item node" :model="treeData">
  </item>
</ul>