首页 > 解决方案 > 在树视图中选择和取消选择节点 - vuejs

问题描述

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

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

有没有一种可行的方法,或者我不理解某些东西?

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

谢谢!

更新:

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

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

标签: javascriptvue.jsvuejs2

解决方案


这和 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>


推荐阅读