单击用v-for创建的组件时,将类添加到特定的父div

时间:2019-05-03 11:49:39

标签: vue.js v-for

我是vuejs的新手,这是我想要做的: 我有一个组件列表,每个组件在一个div中。现在,如果我对组件做了一些操作(即单击它)。我想向父div添加一个类。到目前为止,这是我所做的,只是简化了代码,只是为了说明我想用一个简单的情况做些什么。

我的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);
    }
}

此操作:创建带有“ toggle-box”类的3个div,其中带有按钮的标签为“名称-索引”。当我单击一个按钮时,它将发出带有索引的“ someEvent”事件。父级侦听此事件,并使用“ toggle-box”类在div上切换类“ is-active”。事情是,现在,当我单击一个按钮时,它将类添加到所有3个div中。可能是因为vuejs的3个div之间没有区别。我知道我可以将索引附加到事件中,并在父级中使用$ event调用它,但是我该如何使用它呢?还是有实现我想要的更好的方法?

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

有几种方法可以解决此问题,但我认为起点是要考虑如何将其表示为数据,而不是如何在UI中显示。因此在查看之前先建模。

大概这些选定的活动项目后,您将要对其进行处理。我将专注于此,而不是突出显示它们的问题。这样,突出显示就会相对轻松地消失。

为了便于讨论,我们假设活动项数组是您要实现的目标的合适模型。可能不是,但这只是一个简单的例子。

所以:

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

这里没有提及类,因为我们不担心UI问题,我们正在尝试对基础数据进行建模。

对于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将直接创建此新组件的实例。视情况而定,此新组件可能会合并到您的原始组件中。

这里还有各种各样的其他考虑因素,因此很难给出明确的答案。如果需要在切换框组件之外知道活动状态,则与仅是内部状态相比,情况就大为不同。如果一次只能打开一个切换框(如手风琴),那么这同样很棘手,因为内部状态不足。