单击使用 v-for 创建的组件时,将 class 添加到特定的父级 div
add class to a specific parent div when click a component created with v-for
我是vuejs的新手,这就是我想做的:
我有一个组件列表,每个组件都在 div 中。现在,如果我对该组件执行某些操作(即单击它)。我想添加一个 class 到父 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);
}
}
这是做什么的:它创建了 3 个 div 和 "toggle-box"-class,其中有一个标签为 "name - index" 的按钮。当我单击一个按钮时,它会发出带有索引的 "someEvent" 事件。父级侦听此事件并将 div 上的 class 'is-active' 切换为 'toggle-box' class。问题是,现在,当我单击一个按钮时,它会将 class 添加到所有 3 个 div。可能是因为vuejs的3个div没有区别。我知道我可以将索引附加到事件并在父级中使用 $event 调用它,但我该如何使用它?还是有更好的方法来实现我想要的?
感谢您的帮助。
有几种不同的方法来解决这个问题,但我认为出发点是考虑您希望如何将其表示为数据,而不是它在 UI 中的显示方式。所以先建模再看。
您可能想在选择这些活动项目后对其进行处理。我会专注于此,而不是突出显示它们的问题。然后突出显示会相对轻松地脱落。
为了便于讨论,我们假设一组活动项是适合您要实现的目标的模型。它可能不是,但它是一个简单的例子。
所以:
data() {
return {
activeNames: [],
names: ['alpha', 'beta', 'gamma']
}
},
此处未提及 classes,因为我们不担心 UI 问题,我们正在尝试对基础数据建模。
对于 toggle
方法,我更倾向于发出 name
而不是 index
,但您可以更好地判断哪个更好地代表数据。对于我的示例,它将是 name
:
methods: {
toggle() {
this.$emit('someEvent', this.myName);
}
}
然后在父组件中,我们将在事件发出时从数组中 add/remove name
。其他数据结构可能对此更好,我会在最后回过头来。
methods: {
doSomething(name) {
if (this.activeNames.includes(name)) {
this.activeNames = this.activeNames.filter(item => item !== name);
} else {
this.activeNames.push(name);
}
}
}
现在我们有一个包含活动名称的数组,我们可以使用它来派生那些包装 div 的 class。
<div
class="toggle-box"
v-for="(name, index) in names"
:class="{'is-active': activeNames.includes(name)}"
:key="index"
>
完成。
正如所承诺的那样,我现在 return 介绍您可以使用的其他数据结构。
我们可以使用具有布尔值的对象来代替数组:
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
将直接创建这个新组件的实例。根据具体情况,这个新组件可能会合并到您的原始组件中。
这里有各种各样的其他考虑因素,因此很难给出明确的答案。如果需要在切换框组件外部知道活动状态,那么它与只是内部状态的情况截然不同。如果一次只能打开一个切换框(如手风琴),那么这同样很棘手,因为内部状态是不够的。
我是vuejs的新手,这就是我想做的: 我有一个组件列表,每个组件都在 div 中。现在,如果我对该组件执行某些操作(即单击它)。我想添加一个 class 到父 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);
}
}
这是做什么的:它创建了 3 个 div 和 "toggle-box"-class,其中有一个标签为 "name - index" 的按钮。当我单击一个按钮时,它会发出带有索引的 "someEvent" 事件。父级侦听此事件并将 div 上的 class 'is-active' 切换为 'toggle-box' class。问题是,现在,当我单击一个按钮时,它会将 class 添加到所有 3 个 div。可能是因为vuejs的3个div没有区别。我知道我可以将索引附加到事件并在父级中使用 $event 调用它,但我该如何使用它?还是有更好的方法来实现我想要的?
感谢您的帮助。
有几种不同的方法来解决这个问题,但我认为出发点是考虑您希望如何将其表示为数据,而不是它在 UI 中的显示方式。所以先建模再看。
您可能想在选择这些活动项目后对其进行处理。我会专注于此,而不是突出显示它们的问题。然后突出显示会相对轻松地脱落。
为了便于讨论,我们假设一组活动项是适合您要实现的目标的模型。它可能不是,但它是一个简单的例子。
所以:
data() {
return {
activeNames: [],
names: ['alpha', 'beta', 'gamma']
}
},
此处未提及 classes,因为我们不担心 UI 问题,我们正在尝试对基础数据建模。
对于 toggle
方法,我更倾向于发出 name
而不是 index
,但您可以更好地判断哪个更好地代表数据。对于我的示例,它将是 name
:
methods: {
toggle() {
this.$emit('someEvent', this.myName);
}
}
然后在父组件中,我们将在事件发出时从数组中 add/remove name
。其他数据结构可能对此更好,我会在最后回过头来。
methods: {
doSomething(name) {
if (this.activeNames.includes(name)) {
this.activeNames = this.activeNames.filter(item => item !== name);
} else {
this.activeNames.push(name);
}
}
}
现在我们有一个包含活动名称的数组,我们可以使用它来派生那些包装 div 的 class。
<div
class="toggle-box"
v-for="(name, index) in names"
:class="{'is-active': activeNames.includes(name)}"
:key="index"
>
完成。
正如所承诺的那样,我现在 return 介绍您可以使用的其他数据结构。
我们可以使用具有布尔值的对象来代替数组:
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
将直接创建这个新组件的实例。根据具体情况,这个新组件可能会合并到您的原始组件中。
这里有各种各样的其他考虑因素,因此很难给出明确的答案。如果需要在切换框组件外部知道活动状态,那么它与只是内部状态的情况截然不同。如果一次只能打开一个切换框(如手风琴),那么这同样很棘手,因为内部状态是不够的。