首页 > 解决方案 > 如何在 Vue 中显示/隐藏对象的某些部分

问题描述

我正在为产品创建功能页面。当您单击功能名称时,它应该会在下面展开一个框并提供说明。

我截取了一小段数据,其结构基本如下:

{
  "Section": {
    "Page1": {
      "FeatureName": "Feature desc",
      "FeatureName": "Feature desc"
    },
    "Page2": {
      "FeatureName": "Feature desc",
      "FeatureName": "Feature desc"
    }
  }
}

我已经想出了一些方法来做到这一点,但我个人认为它们中的任何一个都不是很好的方法。

  1. 循环遍历 json/object 并为每个特征添加一个 show 属性。然后我可以切换 bool 以显示/隐藏

  2. 从我的后端服务器,实际提供 show 属性开始,以便它可以与 vue 一起使用

两种解决方案都不会使这些组件可重用(即,我将来可以将其用作手风琴,但我必须使用显示属性污染我的源数据,或者进行一些繁重的迭代以添加属性,我并不总是知道深度/级别。)

所以我问,有没有更好的方法或者我列出的唯一方法是什么?

标签: javascriptjsonobjectvuejs2vue-component

解决方案


实现展开/折叠以显示更多细节是一个很常见的问题。这里有几种方法可以做到:

  1. 为集合中的每个对象添加一个布尔属性。这实际上是您的两种方法归结为的原因。我不希望服务器参与进来,这完全是 UI 问题。
  2. 将显示/隐藏值存储在单独的数组/对象中。只是一个大数组或布尔值对象。这很可怕,但它确实避免了改变原始数据。在您的情况下,原始数据位于一个对象中,因此您还可以使用一个对象作为布尔值,由与原始对象相同的键键控。
  3. 避免改变原始数据的另一种方法是包装每个对象。例如{ Page1: { show: false, page: { FeatureName: ... } }。这种结构的缺点是必须编写模板来处理额外的嵌套。
  4. 创建一个组件来保存每个项目的相关状态。这通常是最好的解决方案,但问题是显示/隐藏状态是组件内部的,因此从外部更改它并不容易。这使得实施诸如“显示全部”之类的东西变得很痛苦。只要您不需要从外部访问该状态,它就是一个很好的解决方案。最后举例。

所有这些都假设每个展开框都应该独立运行。如果您希望将它们链接起来,以便一次只能打开一个,那么这一切都会变得更加简单,因为您可以将当前展开的项目的 id 存储为data属性。

现在,正如所承诺的,使用组件来保存每个项目的相关状态的示例:

const expander = {
  props: ['item'],
  
  data () {
    return {
      expanded: false
    }
  },
  
  template: `
    <div>
      <h4>{{ item.title }}</h4>
      <button @click="expanded = !expanded">Toggle</button>
      <p v-if="expanded">{{ item.description }}</p>
    </div>
  `
}

new Vue({
  el: '#app',
  
  components: {
    expander
  },
  
  data () {
    return {
      "Section": {
        "Page1": {
          "title": "Title 1",
          "description": "Blah blah blah blah"
        },
        "Page2": {
          "title": "Title 2",
          "description": "More more more more"
        }
      }
    }
  }
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.js"></script>

<div id="app">
  <expander
    v-for="(item, propertyName) in Section"
    :key="propertyName"
    :item="item"
  ></expander>
</div>


推荐阅读