【问题标题】:Avoid repeating pattern in vue template避免在Vue模板中重复模式
【发布时间】:2019-11-27 09:16:42
【问题描述】:

我有一个巨大的烦人组件,需要在父模板中重复多次,因为父模板使用的是 v-if。下面是组件代码:

<SelectCard
  v-for="(channel, index) in category.visibleChannels"
  :key="index + '-' + channel.id"
  :channel="channel"
  :channel-selected="isSelected(channel.id)"
  :read-more-details="channelInfoDetails"
  @select="onAddChannel"
  @deselect="onRemoveChannel"
  @read-more-changed="setChannelInfoDetails"
/>

每次渲染模板时唯一改变的是我循环的数组.... 这是问题的简化版本:

<template>
<div
    ref="channels"
    class="channels"
  >
    <div v-if="showCategories">
      <div
        v-for="category in sliderCategories"
        :key="category.name"
      >
        <h3 v-text="category.name" />
        <div
          v-if="category.showAll"
          class="channel-list show-all"
          :class="channelListSize"
        >
          <ul>
            <SelectCard looping over category.contents  />
          </ul>
        </div>
        <ChannelSlider
          v-else
          :category="category"
          @visible-updated="setVisibleChannels"
        >
          <SelectCard looping over category.visibleChannels  />
        </ChannelSlider>
        <div class="show-all-link">
          <a
            :class="category.showAll?'arrow-up':'arrow-down'"
            class="link"
            @keyup.enter="toggleShowAll(category.name, !category.showAll)"
            @click="toggleShowAll(category.name, !category.showAll)"
            v-text="showAllText(category.showAll)"
          />
        </div>
      </div>
    </div>
    <div v-else>
      <div v-if="showNoSearchResult">
        <SomeComponent with some props/>
      </div>
      <div :class="channelListSize" class="channel-list">
        <ul>
          <SelectCard looping over updatedChannels  />
        </ul>
      </div>
    </div>
    <div
      ref="someref"
      class="someClass"
      :style="{top: channelInfoDetails.top + 'px', position: 'absolute'}"
    >
      <AnotherComponent with some props/>
    </div>
  </div>
</template>

所以我的模板变得巨大,因为 SelectCard 代码有很多道具。

有没有办法可以将 SelectCard 放在父代码中的方法中,以便我可以使用数组调用函数或其他什么?还是有其他我不知道的解决方案?

【问题讨论】:

  • 每个分支的标记真的只是一对包含SelectCard&lt;div&gt; 元素吗?或者这是为了提出问题而进行的简化?
  • @skirtle ,它是为了简化......每个 v-if/v-else 里面都有更多的模板。除了 SelectCard 之外,它们都没有相同的内容。
  • 我已更新示例模板以使其更清晰

标签: javascript vue.js vue-component


【解决方案1】:

我认为这里没有您想的那么简单的解决方案。但也有一些可能性。

您可以使用v-bindv-on 的对象形式将其略微减小。对于v-bind,您需要引入一个方法来返回对象,因为您的道具依赖于channelindex,因此它们需要传递给该方法。这会减少一点,但它不是很好。 is 属性的对象形式也可能是一个选项。这可能会进一步压缩它,但会以清晰度为代价。

另一种方法是引入另一个组件,然后将插槽用于SelectCard。例如:

<div>
  <div v-if="conditionA">
    <div v-if="conditionA-A">
      <slot />
    </div>
    <div v-else>
      <slot />
    </div>  
  </div>
  <div v-else>
    <div v-if="conditionB-A">
      <slot />
    </div>
    <div v-else>
      <slot />
    </div>  
  </div>
</div>

然后您将 SelectCard 作为插槽内容传递,并使用计算属性使数组动态化。

这种方法的一个问题是,您可能会发现自己必须在各个组件层之间传递大量内容才能使其正常工作。

另一种选择是将所有内容转换为render 函数。你绝对可以使用render 函数来做你想做的事情,但这会以不得不放弃使用模板为代价。这是否真的是一个问题将取决于模板其余部分的复杂性。

【讨论】:

  • 感谢您的回答!这是我的恐惧。我更新了示例模板以显示它的复杂程度。有很多不同的变化。而且该模板完全无法阅读完整版(正如您在看到新示例后可能已经猜到的那样)。我希望使 SelectCard 部分更小,以至少帮助它变得更小......与例如 React 相比,Vue 在模板渲染方面似乎缺乏灵活性。而且我担心我们为这项工作选择了错误的框架。
【解决方案2】:

v-if's 的所有逻辑放入一个计算属性中,该属性返回您想要传递为的正确数组。 SelectCard 的道具 类似:

<SelectCard :arr="arrayToRender"/>
...
computed: {
       arrayToRender(){
           if (ConditionA){ return Array_A}
           if ....
    }

【讨论】:

  • 不幸的是,这是不可能的,因为每个 v-if div 中的代码比您在我的示例中看到的要多...我只是想简化我的示例...没有 v-if/v -else 除了这个巨大的 SelectCard 之外,里面的内容是一样的......
  • 即使您需要将其分解为几个计算属性,但它仍然比污染模板 imo 更好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 2023-03-22
  • 1970-01-01
  • 2017-08-05
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多