如何给一个动态呈现的元素它自己的数据值并在它的父组件中定位它?
How to give a dynamically rendered element it's own data value & target it in it's parent component?
我有一个 BaseMenuItem 组件,它有普通的按钮元素和特殊的 news 元素。
我在 news 类型 els 中添加了自动收报机效果,并希望在单击该元素时停止该元素的自动收报机。目前点击事件停止了整个组的代码效果。
如何定位该组中的单个元素?
有两种方法,openNews
一种显示元素链接到的特定新闻文章。
clearItemType
在从 BaseMenuItem 组件收到发出的事件后清除 itemType
。
我只是不确定要更改哪个元素是 itemType
。
Vuejs 是否有办法为动态生成的元素创建一个唯一的数据值?
如果您需要更多信息,请告诉我!
干杯!
基础菜单项
<template>
<q-btn align="left" dense flat class="main-menu-item" v-on="$listeners">
<div class="flex no-wrap items-center full-width">
<iconz v-if="iconz" :name="iconz" type="pop" color="black" class="mr-md" />
<q-icon v-if="menuIcon" :name="menuIcon" class="text-black mr-md" />
<div @click="$emit('stop-ticker')" v-if="itemType === 'news'" class="ellipsis _ticker">
<div class="ellipsis _ticker-item">{{ title }}</div>
</div>
<div v-else>
<div class="ellipsis">{{ title }}</div>
</div>
<slot>
<div class="ml-auto"></div>
<div class="_subtitle mr-md" v-if="subtitle">{{ subtitle }}</div>
<q-icon name="keyboard_arrow_right" class="_right-side" />
<ComingSoon v-if="comingSoonShow" />
</slot>
</div>
</q-btn>
</template>
<style lang="sass" scoped>
// $
.main-menu-item
display: block
font-size: 15px
position: relative
width: 100%
border-bottom: 1px solid #F5F5F5
+py(10px)
._left-side
color: #000000
._subtitle
margin-left: auto
opacity: 0.7
._ticker
position: absolute
font-weight: bold
margin-left: 2em
width: 82%
&-item
display: inline-block
padding-left: 100%
animation: ticker 8s linear infinite
@keyframes ticker
to
transform: translateX(-100%)
</style>
<script>
import { iconz } from 'vue-iconz'
export default {
name: 'MainMenuItem',
components: { iconz },
props: {
comingSoonShow: { type: Boolean, default: false },
title: { type: String, default: 'menu' },
subtitle: { type: String, default: '' },
menuIcon: { type: String, default: '' },
iconz: { type: String, default: '' },
itemType: { type: String, default: '' },
}
}
</script>
主菜单页面
<template>
<div class="eachMenuGroup" v-if="newsList.length">
<MainMenuItem
v-for="news in newsList"
:key="news.id"
@click="openNews(news)"
:title="news.title"
:itemType="itemType"
:class="{ readLink: readNewsList[news.id] }"
menuIcon="contactless"
@stop-ticker="clearItemType"
></MainMenuItem>
</div>
</template>
<style lang="sass" scoped>
.readLink
font-weight: 500
</style>
<script>
methods: {
openNews(postInfo) {
dbAuthUser().merge({ seenNewsPosts: { [postInfo.id]: true } })
Browser.open({ url: postInfo.url, presentationStyle: 'popover' })
},
clearItemType() {
this.itemType = ''
return
},
</script>
编辑:我根据您的最新评论进行了编辑。见下文
要定位 v-for
中触发事件的确切元素,您可以通过使用索引来使用 $refs
:
<MainMenuItem v-for="(item, index) in items" :ref="`menuItem--${index}`" @stop-ticker="clearItemType(index)" />
在你的方法中:
clearItemType(index){
console.log(this.$refs[`menuItem--${index}`])
// this is the DOM el that fired the event
}
您评论后的编辑版本:
如果您将完全相同的属性传递给 v-for
的每个 el,您将无法仅在 parent 上下文中为一个 child 修改其值。
相反,在您的 parent 中保留一组独特的值。每个 child 将收到一个特定的道具,您可以在 parent 中相应地更改该道具,方法是侦听 child 发出的事件或将索引作为点击事件传递,就像我在下面为简单起见所做的那样.
见下面的片段
Vue.config.productionTip = false;
const Item = {
name: 'Item',
props: ['name', 'isActive'],
template: `<div>I am clicked {{ isActive }}!</div>`,
};
const App = new Vue({
el: '#root',
components: {
Item
},
data: {
items: ["item1", "item2"],
activeItemTypes: []
},
methods: {
toggle(index) {
this.activeItemTypes = this.activeItemTypes.includes(index) ? this.activeItemTypes.filter(i => i !== index) : [...this.activeItemTypes, index]
}
},
template: `
<div>
<Item v-for="(item, i) in items" :name="item" @click.native="toggle(i)" :isActive="activeItemTypes.includes(i)"/>
</div>
`,
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="root"></div>
我有一个 BaseMenuItem 组件,它有普通的按钮元素和特殊的 news 元素。 我在 news 类型 els 中添加了自动收报机效果,并希望在单击该元素时停止该元素的自动收报机。目前点击事件停止了整个组的代码效果。
如何定位该组中的单个元素?
有两种方法,openNews
一种显示元素链接到的特定新闻文章。
clearItemType
在从 BaseMenuItem 组件收到发出的事件后清除 itemType
。
我只是不确定要更改哪个元素是 itemType
。
Vuejs 是否有办法为动态生成的元素创建一个唯一的数据值?
如果您需要更多信息,请告诉我!
干杯!
基础菜单项
<template>
<q-btn align="left" dense flat class="main-menu-item" v-on="$listeners">
<div class="flex no-wrap items-center full-width">
<iconz v-if="iconz" :name="iconz" type="pop" color="black" class="mr-md" />
<q-icon v-if="menuIcon" :name="menuIcon" class="text-black mr-md" />
<div @click="$emit('stop-ticker')" v-if="itemType === 'news'" class="ellipsis _ticker">
<div class="ellipsis _ticker-item">{{ title }}</div>
</div>
<div v-else>
<div class="ellipsis">{{ title }}</div>
</div>
<slot>
<div class="ml-auto"></div>
<div class="_subtitle mr-md" v-if="subtitle">{{ subtitle }}</div>
<q-icon name="keyboard_arrow_right" class="_right-side" />
<ComingSoon v-if="comingSoonShow" />
</slot>
</div>
</q-btn>
</template>
<style lang="sass" scoped>
// $
.main-menu-item
display: block
font-size: 15px
position: relative
width: 100%
border-bottom: 1px solid #F5F5F5
+py(10px)
._left-side
color: #000000
._subtitle
margin-left: auto
opacity: 0.7
._ticker
position: absolute
font-weight: bold
margin-left: 2em
width: 82%
&-item
display: inline-block
padding-left: 100%
animation: ticker 8s linear infinite
@keyframes ticker
to
transform: translateX(-100%)
</style>
<script>
import { iconz } from 'vue-iconz'
export default {
name: 'MainMenuItem',
components: { iconz },
props: {
comingSoonShow: { type: Boolean, default: false },
title: { type: String, default: 'menu' },
subtitle: { type: String, default: '' },
menuIcon: { type: String, default: '' },
iconz: { type: String, default: '' },
itemType: { type: String, default: '' },
}
}
</script>
主菜单页面
<template>
<div class="eachMenuGroup" v-if="newsList.length">
<MainMenuItem
v-for="news in newsList"
:key="news.id"
@click="openNews(news)"
:title="news.title"
:itemType="itemType"
:class="{ readLink: readNewsList[news.id] }"
menuIcon="contactless"
@stop-ticker="clearItemType"
></MainMenuItem>
</div>
</template>
<style lang="sass" scoped>
.readLink
font-weight: 500
</style>
<script>
methods: {
openNews(postInfo) {
dbAuthUser().merge({ seenNewsPosts: { [postInfo.id]: true } })
Browser.open({ url: postInfo.url, presentationStyle: 'popover' })
},
clearItemType() {
this.itemType = ''
return
},
</script>
编辑:我根据您的最新评论进行了编辑。见下文
要定位 v-for
中触发事件的确切元素,您可以通过使用索引来使用 $refs
:
<MainMenuItem v-for="(item, index) in items" :ref="`menuItem--${index}`" @stop-ticker="clearItemType(index)" />
在你的方法中:
clearItemType(index){
console.log(this.$refs[`menuItem--${index}`])
// this is the DOM el that fired the event
}
您评论后的编辑版本:
如果您将完全相同的属性传递给 v-for
的每个 el,您将无法仅在 parent 上下文中为一个 child 修改其值。
相反,在您的 parent 中保留一组独特的值。每个 child 将收到一个特定的道具,您可以在 parent 中相应地更改该道具,方法是侦听 child 发出的事件或将索引作为点击事件传递,就像我在下面为简单起见所做的那样.
见下面的片段
Vue.config.productionTip = false;
const Item = {
name: 'Item',
props: ['name', 'isActive'],
template: `<div>I am clicked {{ isActive }}!</div>`,
};
const App = new Vue({
el: '#root',
components: {
Item
},
data: {
items: ["item1", "item2"],
activeItemTypes: []
},
methods: {
toggle(index) {
this.activeItemTypes = this.activeItemTypes.includes(index) ? this.activeItemTypes.filter(i => i !== index) : [...this.activeItemTypes, index]
}
},
template: `
<div>
<Item v-for="(item, i) in items" :name="item" @click.native="toggle(i)" :isActive="activeItemTypes.includes(i)"/>
</div>
`,
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="root"></div>