簡體   English   中英

添加用於編輯所選元素中的數組對象鍵的“輸入” - Vue.js

[英]Adding 'input' used to edit array object key in selected elements - Vue.js

我需要在當前選定的元素組件中添加一個用於編輯titleinput字段(選擇是通過單擊完成的)。 問題是每個選定的元素都應該有一個輸入和工作 我在互聯網上找不到類似的任務和解決方案。 也許有人會告訴你怎么做?

ItemsList.vue組件:

<template>
    <input type="text" placeholder="Edit selected items"/>
    <div class="items-col">
        <ul class="items-list">
            <Item v-for="item in items" :key="item" :title="item.title"/>
        </ul>
    </div>
</template>

<script>
import Item from '@/components/Item.vue'
export default {
    data() {
        return {
            items: [
                { title: 'item 1' },
                { title: 'item 2' },
                { title: 'item 3' },
                { title: 'item 4' },
                { title: 'item 5' },
                { title: 'item 6' }
            ]
        }
    },
    components: {
        Item
    }
}
</script>

Item.vue組件:

<template>
    <li class="item" @click="isActive = !isActive" :class="{ active: isActive }">{{ title }}</li>
</template>

<script>

export default {
    name: 'ItemsList',
    data() {
        return {
            isActive: false
        }
    },
    props: {
        title: String
    }
}
</script>

<style>
    .item.active {
        color: red;
    }
</style>

您可能需要重新考慮哪個組件應該負責知道哪個項目在任何時間點處於活動狀態:提示:它應該是父/消費組件。 那是因為你:

  1. 只有一個輸入字段,這意味着在任何時間點只能編輯一個項目
  2. 您想讓父/消費組件成為哪個項目實際處於活動狀態的唯一真實來源

因此,您應該做的第一件事是確保isActiveItem組件上的一個 prop,而父ItemList組件會隨時跟蹤哪個處於活動狀態。

那么,這只是一個問題:

  • isActive標志實現切換邏輯。 當從Item組件觸發本機單擊事件時,會更新該標志。 對於切換邏輯,我們可以簡單地在點擊項的從零開始的索引或-1之間切換,我們用它來表示沒有任何活動。
  • 使用v-bind:value和一個計算屬性來反映當前活動項的值。 我們可以簡單地在父組件上使用this.items[this.activeIndex]來檢索它
  • 監聽onInput事件,然后更新正確的項目

請參閱下面的概念驗證:

 Vue.component('item-list', { template: '#item-list-template', data() { return { items: [{ title: 'item 1' }, { title: 'item 2' }, { title: 'item 3' }, { title: 'item 4' }, { title: 'item 5' }, { title: 'item 6' } ], activeIndex: -1, } }, methods: { onItemClick(index) { this.activeIndex = this.activeIndex === index ? -1 : index; }, setActiveItemValue(event) { const foundItem = this.items[this.activeIndex]; if (!foundItem) return; return this.items[this.activeIndex].title = event.currentTarget.value; } }, computed: { activeItemValue() { return this.items[this.activeIndex]?.title ?? ''; } } }); Vue.component('item', { template: '#item-template', props: { isActive: Boolean, title: String } }); new Vue({ el: '#app' });
 li.active { background-color: yellow; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <div id="app"> <item-list></item-list> </div> <script type="text/x-template" id="item-list-template"> <div> <input type="text" placeholder="Edit selected items" :value="activeItemValue" @input="setActiveItemValue" /> <div class="items-col"> <ul class="items-list"> <item v-for="(item, i) in items" :key="i" :title="item.title" :isActive="activeIndex === i" @click.native="onItemClick(i)" /> </ul> </div> </div> </script> <script type="text/x-template" id="item-template"> <li class="item" :class="{ active: isActive }">{{ title }}</li> </script>

如果您想要使用當前組件(不是最干凈的)的解決方案,當您激活一個元素時,您實際上可以向父組件發出一個事件,該事件應包含項目數組中對象的索引

然后你可以使用索引來獲取和設置標題變量,這是一個例子:

項目.vue

<template>
  <li class="item" @click="activateItem" :class="{ active: isActive }">{{ title }}</li>
</template>

<script>

export default {
  name: 'ItemsList',
  data() {
    return {
      isActive: false
    }
  },
  methods:{
    activateItem() {
      this.isActive = !this.isActive
      this.$emit('activatedItem', this.isActive ? this.index : null)
    }
  },
  props: {
    title: String,
    index: Number
  }
}
</script>

<style>
.item.active {
  color: red;
}
</style>

項目列表.vue

<template>
  <div>
    <input type="text" placeholder="Edit selected items" @input="inputChange" :value="inputValue"/>
    <div class="items-col">
      <ul class="items-list">
        <Item v-for="(item, index) in items" :key="index" :title="item.title" :index="index" @activatedItem="itemSelected"/>
      </ul>
    </div>
  </div>
</template>

<script>
import Item from '@/components/Item.vue'
export default {
  data() {
    return {
      items: [
        { title: 'item 1' },
        { title: 'item 2' },
        { title: 'item 3' },
        { title: 'item 4' },
        { title: 'item 5' },
        { title: 'item 6' }
      ],
      selectedIndex: null,
      inputValue: ''
    }
  },
  methods:{
    itemSelected(index){
        this.selectedIndex = index;
        if(this.selectedIndex != null) {
          this.inputValue = this.items[this.selectedIndex].title;
        }
    },
    inputChange(event){
      this.inputValue = event.target.value;
      if(this.selectedIndex != null){
        this.items[this.selectedIndex].title = this.inputValue
      }
    }
  },
  components: {
    Item
  }
}
</script>

您還應該知道,使用您提供的組件 Item,您可以選擇多個項目!

對於您的第二個問題,您應該只更改索引以匹配數組中的索引,例如,如果 rowIndex 以 1 開頭:

onItemClick(index, rowIndex) {
    let correctIndex = (index + (this.itemsPerRow * (rowIndex - 1));
    this.activeIndex = this.activeIndex === correctIndex ? -1 : correctIndex);
},

謝謝各位,運行正常。

此任務的另一個問題:

如何使其在元素位於 3 個項目的行中的條件下工作?

例如我需要得到這個最終效果:


<ul class="items-list">
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 1</li>
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 2</li>
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 3</li>
</ul>
<ul class="items-list">
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 4</li>
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 5</li>
    //my Item.vue component
    <li class="item" :class="{ active: isActive }">item 6</li>
</ul>

我寫了一個方法,將項目連續 3 分隔,在您的解決方案之后,我有以下內容:

ItemsList.vue組件:

<template>
    <div class="items-col">
        <input type="text" placeholder="Edit selected items" :value="activeItemValue" @input="setActiveItemValue" />
        <ul class="items-list" v-for="index in rowCount" :key="index">
            <Item v-for="(item, i) in itemCountInRow(index)" :key="i" :title="item.title"  :isActive="activeIndex === i" @click="onItemClick(i)"/>
        </ul>
    </div>
</template>

<script>

import Item from '@/components/Item.vue'

export default {
    name: 'ItemsList',
    data() {
        return {
            items: [
                { title: 'item 1' },
                { title: 'item 2' },
                { title: 'item 3' },
                { title: 'item 4' },
                { title: 'item 5' },
                { title: 'item 6' },
            ],
            activeIndex: -1,
            itemsPerRow: 3
        }
    },
    components: {
        Item
    },
    computed: {
        rowCount(){
            return Math.ceil(this.items.length / this.itemsPerRow);
        },
        activeItemValue() {
            return this.items[this.activeIndex]?.title ?? '';
        }
    },
    methods: {
        onItemClick(index) {
            this.activeIndex = this.activeIndex === index ? -1 : index;
        },
        setActiveItemValue(event) {
            const foundItem = this.items[this.activeIndex];
            if (!foundItem) return;
            
            return this.items[this.activeIndex].title = event.currentTarget.value;
        },
        itemCountInRow(index){
            return this.items.slice((index - 1) * this.itemsPerRow, index * this.itemsPerRow)
        }
    }
}
</script>

現在,當我單擊該項目時,您的方法僅適用於第一個列表。

是否可以使其與每行 3 個項目的划分一起工作?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM