Выбор и отмена выбора узлов в древовидном представлении - vuejs - PullRequest
0 голосов
/ 14 мая 2018

Я новичок в VueJS. Я работал над настройкой примера представления дерева из документации vuejs: Example .

При выборе элемента в древовидном представлении я не могу понять, как отменить выбор, т. Е. Сбросить класс ранее выбранного элемента. Некоторые подходы, которые я пробовал, включают

  • Установка глобальной переменной с помощью Vue.prototype и доступ к ней в вычисляемой функции, в этом случае вычисляемая функция даже не запускается.
  • Я знаю об объекте события, который передан. Используя это и jQuery, удаление класса ранее выбранного div будет работать, но это похоже на хак.
  • Установка массива выбранных элементов в data для события click и доступ к нему в вычисляемой функции. Это тоже не работает.

Есть ли способ, который бы сработал, или я чего-то не понимаю?

Ссылка на кодовую страницу, над которой я работаю: Кодовая ручка . Для выбора узла просто нажмите на узел и попробуйте выбрать другой узел. Предыдущий узел не очищается.

Спасибо!

Обновление:

Ответ ниже работает, но он удалит выбранный класс, если щелкнуть где-нибудь еще. Я хотел решение, где выбранный класс будет удален, только если я нажму на другой узел. Все, что мне нужно было сделать, это создать шину событий и сохранить ранее выбранный объект компонента в родительской переменной. При щелчке по новому узлу генерируется глобальное событие, которое будет прослушиваться методом основного экземпляра. Там он будет устанавливать логическое значение, которое отменяет выбор предыдущего компонента, и другое логическое значение, чтобы установить выбранный класс в новый объект компонента. Я не уверен, что существует лучший способ.

Обновлена ​​кодовая ручка с некоторыми изменениями: Ссылка CodePen

1 Ответ

0 голосов
/ 14 мая 2018

Это не имеет ничего общего с 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...