添加用于在选定元素中编辑数组对象键的“输入” - Vue.js

Posted

技术标签:

【中文标题】添加用于在选定元素中编辑数组对象键的“输入” - Vue.js【英文标题】:Adding 'input' used to edit array object key in selected elements - Vue.js 【发布时间】:2021-12-26 16:45:02 【问题描述】:

我需要添加一个input 字段,用于在当前选定的元素组件中编辑title(通过单击完成选择)。 问题是每个选定元素都应该有一个输入和工作。我在互联网上找不到类似的任务和解决方案。也许有人会告诉你怎么做?

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>

【问题讨论】:

嗯,在我看来,这是一个非常奇怪和不直观的 UI/UX。在被点击的&lt;li&gt; 中实际呈现一个输入字段是否更有意义,这会更新该特定条目的值? @Terry,我知道这一点,但我从雇主那里收到了这个任务,应该这样做:/有什么想法吗? 【参考方案1】:

您可能需要重新考虑哪个组件应该负责知道哪个项目在任何时间点处于活动状态:提示:它应该是父/消费组件。那是因为你:

    只有一个输入字段,这意味着在任何时间点都只能编辑一个项目 您想让父/消费组件成为哪个项目实际处于活动状态的单一事实来源

因此,您应该做的第一件事是确保isActiveItem 组件上的一个道具,而父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>

【讨论】:

谢谢,它工作正常,但我还有另一个问题。看下一个问题:)【参考方案2】:

如果您想要使用当前组件(不是最干净的)的解决方案,您实际上可以在激活元素时向父组件发出事件,该事件应包含 items 数组中对象的索引

然后你可以使用索引来获取和设置标题变量,这里是一个例子:

项目.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>

ItemList.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 您可以选择多个项目!

【讨论】:

以上是关于添加用于在选定元素中编辑数组对象键的“输入” - Vue.js的主要内容,如果未能解决你的问题,请参考以下文章

如何将对象中特定键的值存储到数组中 - Vue

在 Oracle PL/SQL 中,如何检查 JSON 对象是不是包含特定键的元素

javascript 可以在不指定 PHP 等键的情况下将元素添加到数组吗?

使用拼接反应本机从数组中删除对象元素

数组对象方法

如何使用事件侦听器向对象数组添加新元素并将其显示在 html 页面上(已编辑代码)