首页 > 解决方案 > 如何为动态呈现的元素赋予它自己的数据值并在它的父组件中定位它?

问题描述

我有一个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>

标签: vue.jsvuejs2vue-component

解决方案


编辑:我编辑了你的最新评论。见下文

要定位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>


推荐阅读