nuxtjs 切换由 v-for 循环生成的单个项目
nuxtjs toggle individual items generated by v-for loop
我想创建一个类似手风琴的简单结构,但不知何故我无法切换单个元素:
<div v-for="qa, j in group.questions_answers" :key="j">
<div class="question" @click="toggle()" > <!-- use index here? -->
<span v-if="itemOpen" class="font-iconmoon icon-accordion-up"><span/>
<span v-else class="font-iconmoon icon-accordion-down"><span/>
<span class="q-text" v-html="qa.question"><span/>
</div>
<div v-if="itemOpen" class="answer" v-html="qa.answer"></div>
</div>
我将如何切换单个 question/answer 块?我需要使用 refs 吗?
目前我可以切换所有元素...
export default {
data() {
return {
itemOpen: true
}
},
methods: {
toggle() { // index
this.itemOpen = !this.itemOpen
}
}
}
我可以起草一个 Q/A 组件,然后在每个组件内部进行切换,但我认为这样做有点矫枉过正。
更新我正在处理以下数据结构:
{
"intro_text": "intro text",
"questions_groups": [
{
"group_heading": "heading",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{...}
]
},
{
"group_heading": "heading 1",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{...}
},
{
"group_heading": "heading 2",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
}
{...}
]
}
]
}
这是如何正确地将一个对象的 属性 转变为您正在循环的数组。
<template>
<!-- eslint-disable vue/no-v-html -->
<article>
<div
v-for="todo in todoList"
:key="todo.id"
class="question"
@click="toggleMyTodo(todo)"
>
<span
v-if="isTodoDone(todo)"
class="font-iconmoon icon-accordion-up"
></span>
<span v-else class="font-iconmoon icon-accordion-down"></span>
<span class="q-text" v-html="todo.question"></span>
<div v-if="isTodoDone(todo)" class="answer" v-html="todo.answer"></div>
</div>
</article>
</template>
<script>
export default {
data() {
return {
todoList: [
{
id: 1,
task: 'Cook',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
{
id: 2,
task: 'Hover',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
{
id: 3,
task: 'Washing machine',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
],
}
},
methods: {
toggleMyTodo({ id }) {
const currentTodoIndexToToggle = this.todoList.findIndex(
(todo) => todo.id === id
)
// $set is used because of this https://vuejs.org/v2/guide/reactivity.html#For-Arrays
this.$set(this.todoList, currentTodoIndexToToggle, {
...this.todoList[currentTodoIndexToToggle],
done: !this.todoList[currentTodoIndexToToggle].done,
})
},
isTodoDone({ id }) {
// I'm using `?.` just to be sure https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
return this.todoList.find((todo) => todo.id === id)?.done
},
},
}
</script>
顺便说一下,请 do not use v-html
as is but pass it through 。
因为我在单个 question/answer 对象上没有 id
和 done
字段,所以我需要遍历几个 q/a 组,它是在这种情况下,创建子组件更容易且性能更高,以针对单个 q/a 行进行切换:
<template>
<div>
<slot-main-heading>{{$t('faq.h1')}}</slot-main-heading>
<div v-html="introText"></div>
<div v-for="(group, i) in questionsGroups" :key="i">
<slot-htwo-heading>{{group.group_heading}}</slot-htwo-heading>
<template v-for="(qa, j) in group.questions_answers">
<cms-accordion-row :qaData="qa" :key="j"/>
</template>
</div>
</div>
</template>
cmsAccordionRow.vue
<template>
<div>
<div class="question" @click="toggle()">
<span v-if="itemOpen" class="font-iconmoon icon-accordion-up" ></span>
<span v-else class="font-iconmoon icon-accordion-down" ></span>
<span class="q-text" v-html="qaData.question" ></span>
</div>
<div v-if="itemOpen" class="answer" v-html="qaData.answer"></div>
</div>
</template>
<script>
export default {
props: {
qaData: {
type: Object,
required: true
}
},
data() {
return {
itemOpen: true
}
},
methods: {
toggle() {
this.itemOpen = !this.itemOpen
}
}
}
</script>
我想创建一个类似手风琴的简单结构,但不知何故我无法切换单个元素:
<div v-for="qa, j in group.questions_answers" :key="j">
<div class="question" @click="toggle()" > <!-- use index here? -->
<span v-if="itemOpen" class="font-iconmoon icon-accordion-up"><span/>
<span v-else class="font-iconmoon icon-accordion-down"><span/>
<span class="q-text" v-html="qa.question"><span/>
</div>
<div v-if="itemOpen" class="answer" v-html="qa.answer"></div>
</div>
我将如何切换单个 question/answer 块?我需要使用 refs 吗?
目前我可以切换所有元素...
export default {
data() {
return {
itemOpen: true
}
},
methods: {
toggle() { // index
this.itemOpen = !this.itemOpen
}
}
}
我可以起草一个 Q/A 组件,然后在每个组件内部进行切换,但我认为这样做有点矫枉过正。
更新我正在处理以下数据结构:
{
"intro_text": "intro text",
"questions_groups": [
{
"group_heading": "heading",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{...}
]
},
{
"group_heading": "heading 1",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{...}
},
{
"group_heading": "heading 2",
"questions_answers": [
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
},
{
"question": "Question",
"answer": "Answer"
}
{...}
]
}
]
}
这是如何正确地将一个对象的 属性 转变为您正在循环的数组。
<template>
<!-- eslint-disable vue/no-v-html -->
<article>
<div
v-for="todo in todoList"
:key="todo.id"
class="question"
@click="toggleMyTodo(todo)"
>
<span
v-if="isTodoDone(todo)"
class="font-iconmoon icon-accordion-up"
></span>
<span v-else class="font-iconmoon icon-accordion-down"></span>
<span class="q-text" v-html="todo.question"></span>
<div v-if="isTodoDone(todo)" class="answer" v-html="todo.answer"></div>
</div>
</article>
</template>
<script>
export default {
data() {
return {
todoList: [
{
id: 1,
task: 'Cook',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
{
id: 2,
task: 'Hover',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
{
id: 3,
task: 'Washing machine',
done: false,
question: 'duh?',
answer: 'ahh okay!',
},
],
}
},
methods: {
toggleMyTodo({ id }) {
const currentTodoIndexToToggle = this.todoList.findIndex(
(todo) => todo.id === id
)
// $set is used because of this https://vuejs.org/v2/guide/reactivity.html#For-Arrays
this.$set(this.todoList, currentTodoIndexToToggle, {
...this.todoList[currentTodoIndexToToggle],
done: !this.todoList[currentTodoIndexToToggle].done,
})
},
isTodoDone({ id }) {
// I'm using `?.` just to be sure https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
return this.todoList.find((todo) => todo.id === id)?.done
},
},
}
</script>
顺便说一下,请 do not use v-html
as is but pass it through
因为我在单个 question/answer 对象上没有 id
和 done
字段,所以我需要遍历几个 q/a 组,它是在这种情况下,创建子组件更容易且性能更高,以针对单个 q/a 行进行切换:
<template>
<div>
<slot-main-heading>{{$t('faq.h1')}}</slot-main-heading>
<div v-html="introText"></div>
<div v-for="(group, i) in questionsGroups" :key="i">
<slot-htwo-heading>{{group.group_heading}}</slot-htwo-heading>
<template v-for="(qa, j) in group.questions_answers">
<cms-accordion-row :qaData="qa" :key="j"/>
</template>
</div>
</div>
</template>
cmsAccordionRow.vue
<template>
<div>
<div class="question" @click="toggle()">
<span v-if="itemOpen" class="font-iconmoon icon-accordion-up" ></span>
<span v-else class="font-iconmoon icon-accordion-down" ></span>
<span class="q-text" v-html="qaData.question" ></span>
</div>
<div v-if="itemOpen" class="answer" v-html="qaData.answer"></div>
</div>
</template>
<script>
export default {
props: {
qaData: {
type: Object,
required: true
}
},
data() {
return {
itemOpen: true
}
},
methods: {
toggle() {
this.itemOpen = !this.itemOpen
}
}
}
</script>