vue.js - 如何为动态呈现的元素赋予它自己的数据值并在它的父组件中定位它?
问题描述
我有一个BaseMenuItem组件,它具有普通的按钮元素和特殊的新闻元素。我在新闻类型 els 中添加了一个代码效果,并希望在单击该元素时停止该元素的代码。当前,单击事件会停止对整个组的报价器效果。
如何定位该组中的单个元素?
有两种方法,openNews
一种显示元素链接到的特定新闻文章。从BaseMenuItem组件接收到发出的事件后,这clearItemType
将清除。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
}
评论后的编辑版本:
如果您将完全相同的道具传递给您的每个 el,您v-for
将无法仅针对父上下文中的一个孩子修改其值。
相反,在您的父母中保留一系列独特的价值观。每个孩子都会收到一个特定的道具,您可以通过收听孩子发出的事件或通过将索引作为点击事件传递,您可以在父级中相应地更改它,就像我在下面为简单起见所做的那样。
请参阅下面的片段
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>
推荐阅读
- python - python 代码覆盖错误 cat: /ade_info.vmd: No such file or directory
- c - 关于 nftw() 和 ftw() 线程安全的问题
- javascript - Javascript - 不加载
- visual-studio-code - VSCode 扩展。将类型注入无标题文件
- php - 从 php 到 mysql 的时间格式
- angular - 带有 Angular Service Worker 的 Angular Universal
- salesforce - 我们如何在 Salesforce 的 IF 语句中覆盖多个条件的代码覆盖率
- c# - 以当前登录以外的其他用户身份使用 WPF WebBrowser 运行应用程序 - 某些网页无法正常工作
- visual-studio - 将 Visual Studio 2017 错误消息设置为英文
- php - HTTPS 上的套接字错误但 HTTP 上没有 | PHP