добавить класс к определенному родительскому элементу div, когда щелкните компонент, созданный с помощью v-for - PullRequest
0 голосов
/ 03 мая 2019

Я новичок в vuejs, это то, что я хочу сделать: у меня есть список компонентов, каждый в div.Теперь, если я сделаю что-то с компонентом (т.е. щелкните по нему)Я хочу добавить класс в родительский div.Это то, что я сделал до сих пор, код упрощен, просто чтобы показать, что я хочу сделать с простым делом.

my app.vue:

<div class="toggle-box" v-for="(name, index) in names" :class="classActive" :key="index">
    <app-comp :myName="name" :myIndex="index" @someEvent="doSomething"></app-counter>
</div>
data() {
    classActive: '',
    names: ['alpha', 'beta', 'gamma']
},
methods: {
    doSomething() {
        this.classActive === '' ? this.classActive = 'is-active': this.classActive='';
    }
}

компонент:

<div>
    <button @click="toggle">{{ myName }} - {{ myIndex }}</button>
</div>

props: ['myName', 'myIndex'],
methods: {
    toggle() {
        this.$emit('someEvent', index);
    }
}

что это делает: он создает 3 деления с классом «переключатель» с кнопкой в ​​нем, которая имеет метку «имя - индекс».Когда я нажимаю кнопку, она генерирует событие someEvent с индексом.Родитель слушает это событие и переключает класс is-active на элементе div с классом toggle-box.Дело в том, что прямо сейчас, когда я нажимаю кнопку, он добавляет класс ко всем трем дивам.Вероятно, потому что нет никакой разницы между 3 div для vuejs.Я знаю, что могу добавить индекс к событию и вызвать его с помощью $ event в родительском элементе, но как мне это использовать?Или, может быть, есть лучший способ добиться того, чего я хочу?

спасибо за помощь.

1 Ответ

1 голос
/ 03 мая 2019

Есть несколько разных способов подойти к этому, но я думаю, что отправной точкой является думать о том, как вы хотите представить это как данные, а не как это отображается в пользовательском интерфейсе. Итак, модель перед просмотром.

Предположительно, вы захотите что-то сделать с этими активными элементами после того, как они были выбраны. Я бы сосредоточился на этом, а не на проблеме выделения их. Подсветка тогда выпадет относительно безболезненно.

Ради аргумента давайте предположим, что массив активных элементов является подходящей моделью для того, чего вы пытаетесь достичь. Возможно, это не так, но это простой пример.

Итак:

data() {
    return {
        activeNames: [],
        names: ['alpha', 'beta', 'gamma']
    }
},

Никаких упоминаний о классах здесь нет, поскольку мы не беспокоимся о проблемах пользовательского интерфейса, мы пытаемся смоделировать базовые данные.

Для метода toggle я был бы более склонен испускать name, чем index, но вы лучше можете судить о том, какие данные лучше представлены. Для моего примера это будет name:

methods: {
    toggle() {
        this.$emit('someEvent', this.myName);
    }
}

Затем в родительском компоненте мы добавим / удалим name из массива при отправке события. Другие структуры данных могут быть лучше для этого, я вернусь к этому в конце.

methods: {
    doSomething(name) {
        if (this.activeNames.includes(name)) {
            this.activeNames = this.activeNames.filter(item => item !== name);
        } else {
            this.activeNames.push(name);
        }
    }
}

Теперь у нас есть массив, содержащий активные имена, которые мы можем использовать для получения класса для этих div-оболочек.

<div
    class="toggle-box"
    v-for="(name, index) in names"
    :class="{'is-active': activeNames.includes(name)}"
    :key="index"
>

Готово.

Как и было обещано, я сейчас вернусь к другим структурам данных, которые вы могли бы использовать.

Вместо массива мы можем использовать объект с логическими значениями:

data() {
    return {
        names: ['alpha', 'beta', 'gamma'],
        activeNames: {
            alpha: false,
            beta: false,
            gamma: false
        }
    }
}

Во многих отношениях это более простая структура для работы с этим конкретным примером, но в итоге мы дублируем имена в качестве ключей свойств. Если мы не наполним его таким образом, у нас могут возникнуть проблемы с реактивностью (хотя их можно решить с помощью $set).

Еще одной альтернативой является использование объектов для представления имен в первую очередь:

data() {
    return {
        names: [
            {name: 'alpha', active: false},
            {name: 'beta', active: false},
            {name: 'gamma', active: false}
        ]
    }
}

Имеет ли смысл подобная структура данных для вашего случая использования, я не могу судить.


Обновление:

Исходя из того, что вы сказали в комментариях, я был бы склонен создать еще один компонент для представления переключателя. Каждый из них может хранить свое собственное состояние active, а не пытаться удерживать их все в родительском компоненте. Ваш v-for будет затем напрямую создавать экземпляры этого нового компонента. В зависимости от обстоятельств может случиться так, что этот новый компонент может быть объединен с вашим исходным компонентом.

Здесь есть множество других соображений, которые действительно затрудняют дать окончательный ответ. Если активное состояние необходимо знать за пределами компонента переключателя, тогда это совсем другой сценарий, чем если бы это было только внутреннее состояние. Если только один тумблер может быть открыт одновременно (как гармошка), то это так же сложно, так как внутреннего состояния недостаточно.

...