javascript - 在 TreeView 中选择和取消选择节点 - vuejs

标签 javascript vue.js vuejs2

我是 VueJS 的新手。我一直致力于从 vuejs 文档自定义 TreeView 示例:Example .

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

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

有没有可行的方法,还是我不明白什么?

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

谢谢!

更新:

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

更新的代码笔有一些变化:CodePen link

最佳答案

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

关于javascript - 在 TreeView 中选择和取消选择节点 - vuejs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50323036/

相关文章:

vue.js - OnChange 传递项目文本和项目值 Vuetify

vue.js - 从 webpack 中的特定 Assets 文件中删除哈希

vue.js - VueJS 自定义指令 + 发出事件

javascript - VueJS - 将插槽传递给子组件的子组件

javascript - 如何在每次点击 jquery 中的链接时添加/追加和切换项目到 div?

javascript - knockout 数据绑定(bind)使表结果消失

javascript - 尝试连接 MongoDB Atlas 时如何修复密码错误?

javascript - 如何使用VueJS突出显示列表中的项目

javascript - 隐藏和显示复选框选项 - 整理 Jquery

javascript - 在 Vuejs 中使用 indexOf 方法