Vue 2 按乐器名称列出乐队成员但只显示一次乐器名称
Vue 2 list band members by instrument name but only display the instrument name once
我可以按乐器名称列出乐队成员,但只想显示一次乐器名称,而不是显示巴松管组中每个人的乐器名称。我的想法是提取一组不同的仪器名称,并做一个 v-if 将成员的仪器名称与迭代设置值进行比较,并且仅当成员的数据 属性 instrumentName 与当前值匹配时才显示该成员仪器名称设置。使用下面的代码,我得到一个错误“instNames is not defined”。我仍在学习 Vue 和 Nuxt,并试图摆脱我网站的原始平台 WebMatrix。我需要的另一件事是将一个仪器文件名(图片)附加到每个不同的仪器名称。非常感谢任何帮助!
<template>
<div class="block bg-blue-200 w-96 p-6 m-auto">
<table>
<tr v-for="inst in instNames">
<td>{{ inst.instrumentName }} <img :src="'/images/' + inst.instrumentFilename" >
<td v-for="member in members" :key="member.id">
<div v-if="member.instrumentName == inst.instrumentName"> </div>
<div>{{ member.firstname }} {{ member.lastname }} </div>
<div v-if="$auth.loggedIn" class="block">
<p v-if="!member.email == ' '" class="ml-10"> Email: {{ member.email }} </p>
<p v-if="!member.telephone == ' '" class="ml-10"> Home: {{ member.telephone }} </p>
<p v-if="!member.telephone2 == ' '" class="ml-10">Cell: {{ member.telephone2 }}</p>
<p v-if="!member.street == ' '" class="ml-10">Address: {{ member.street}}</p>
<p v-if="!member.city == ' '" class="ml-28">{{ member.city}}, {{ member.zip}}</p>
</div>
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
async asyncData(context){
const { data } = await context.$axios.get('/api/members')
return {
members : data
}
},
computed: {
instNames: function() {
instNames = [...new Set(this.members.map(x => x.instrumentName))]
return instNames
}
}
}
</script>
您的计算 属性 尝试分配 instNames
,但未在任何地方声明。但是,您实际上并不需要局部变量,因为它未被使用。您可以 return 计算出的集合:
export default {
computed: {
instNames: function() {
//instNames = [...new Set(this.members.map(x => x.instrumentName))]
//^^^^^^^^^ ❌ not declared
// Option 1: Declare it with `let` or `const`
const instNames = [...new Set(this.members.map(x => x.instrumentName))]
return instNames
// Option 2: Just return the calculation
return [...new Set(this.members.map(x => x.instrumentName))]
}
}
}
但是您的模板尝试从计算的 instNames
(字符串数组,而不是对象)渲染 instrumentName
和 instrumentFilename
。假设这些值来自 this.members
,您可以将计算值更新为 return 这些字段:
export default {
computed: {
instNames: function() {
const instName = this.members.map(x => ({
instrumentName: x.instrumentName,
instrumentFilename: x.instrumentFilename,
}))
// remove duplicates here ...
return instName
}
}
}
最后,您的模板 v-if
条件未正确检查非空字符串。对于 !member.email == ' '
,!
运算符具有优先权,它会检查 member.email
是否存在虚假值,即 String
的空字符串。然后它将它与单个 space 进行比较,后者始终是 false
,因为 space 不是假的。您可以用一个简单的真值检查来代替整个比较:
<p v-if="member.email">...</p>
<p v-if="member.telephone">...</p>
<p v-if="member.telephone2">...</p>
<p v-if="member.street">...</p>
<p v-if="member.city">...</p>
以上评论非常宝贵,非常感谢。不过,我的 return 数组的唯一性仍然存在问题;显然,一个 Set 将对一个对象的多次引用视为唯一。所以我最终使用了这段代码:
computed: {
instNames: function() {
const instName = this.members.map
(({ instrumentName, instrumentFilename }) => ({ instrumentName, instrumentFilename}))
const instNameArray = []
const instNameSet = new Set()
for (const object of instName) {
const objectJSON = JSON.stringify(object)
if(!instNameSet.has(objectJSON)) {
instNameArray.push(object)
}
instNameSet.add(objectJSON)
}
console.log(instNameArray)
return instNameArray
}
}
我可以按乐器名称列出乐队成员,但只想显示一次乐器名称,而不是显示巴松管组中每个人的乐器名称。我的想法是提取一组不同的仪器名称,并做一个 v-if 将成员的仪器名称与迭代设置值进行比较,并且仅当成员的数据 属性 instrumentName 与当前值匹配时才显示该成员仪器名称设置。使用下面的代码,我得到一个错误“instNames is not defined”。我仍在学习 Vue 和 Nuxt,并试图摆脱我网站的原始平台 WebMatrix。我需要的另一件事是将一个仪器文件名(图片)附加到每个不同的仪器名称。非常感谢任何帮助!
<template>
<div class="block bg-blue-200 w-96 p-6 m-auto">
<table>
<tr v-for="inst in instNames">
<td>{{ inst.instrumentName }} <img :src="'/images/' + inst.instrumentFilename" >
<td v-for="member in members" :key="member.id">
<div v-if="member.instrumentName == inst.instrumentName"> </div>
<div>{{ member.firstname }} {{ member.lastname }} </div>
<div v-if="$auth.loggedIn" class="block">
<p v-if="!member.email == ' '" class="ml-10"> Email: {{ member.email }} </p>
<p v-if="!member.telephone == ' '" class="ml-10"> Home: {{ member.telephone }} </p>
<p v-if="!member.telephone2 == ' '" class="ml-10">Cell: {{ member.telephone2 }}</p>
<p v-if="!member.street == ' '" class="ml-10">Address: {{ member.street}}</p>
<p v-if="!member.city == ' '" class="ml-28">{{ member.city}}, {{ member.zip}}</p>
</div>
</td>
</tr>
</table>
</div>
</template>
<script>
export default {
async asyncData(context){
const { data } = await context.$axios.get('/api/members')
return {
members : data
}
},
computed: {
instNames: function() {
instNames = [...new Set(this.members.map(x => x.instrumentName))]
return instNames
}
}
}
</script>
您的计算 属性 尝试分配 instNames
,但未在任何地方声明。但是,您实际上并不需要局部变量,因为它未被使用。您可以 return 计算出的集合:
export default {
computed: {
instNames: function() {
//instNames = [...new Set(this.members.map(x => x.instrumentName))]
//^^^^^^^^^ ❌ not declared
// Option 1: Declare it with `let` or `const`
const instNames = [...new Set(this.members.map(x => x.instrumentName))]
return instNames
// Option 2: Just return the calculation
return [...new Set(this.members.map(x => x.instrumentName))]
}
}
}
但是您的模板尝试从计算的 instNames
(字符串数组,而不是对象)渲染 instrumentName
和 instrumentFilename
。假设这些值来自 this.members
,您可以将计算值更新为 return 这些字段:
export default {
computed: {
instNames: function() {
const instName = this.members.map(x => ({
instrumentName: x.instrumentName,
instrumentFilename: x.instrumentFilename,
}))
// remove duplicates here ...
return instName
}
}
}
最后,您的模板 v-if
条件未正确检查非空字符串。对于 !member.email == ' '
,!
运算符具有优先权,它会检查 member.email
是否存在虚假值,即 String
的空字符串。然后它将它与单个 space 进行比较,后者始终是 false
,因为 space 不是假的。您可以用一个简单的真值检查来代替整个比较:
<p v-if="member.email">...</p>
<p v-if="member.telephone">...</p>
<p v-if="member.telephone2">...</p>
<p v-if="member.street">...</p>
<p v-if="member.city">...</p>
以上评论非常宝贵,非常感谢。不过,我的 return 数组的唯一性仍然存在问题;显然,一个 Set 将对一个对象的多次引用视为唯一。所以我最终使用了这段代码:
computed: {
instNames: function() {
const instName = this.members.map
(({ instrumentName, instrumentFilename }) => ({ instrumentName, instrumentFilename}))
const instNameArray = []
const instNameSet = new Set()
for (const object of instName) {
const objectJSON = JSON.stringify(object)
if(!instNameSet.has(objectJSON)) {
instNameArray.push(object)
}
instNameSet.add(objectJSON)
}
console.log(instNameArray)
return instNameArray
}
}