使用v-show

时间:2017-11-03 23:57:44

标签: vue.js vuejs2

我一直在解决一个问题,在嵌套的v-for循环内部,一个简单的v-show指令正朝着 4秒实际应用DOM中的display: none;属性。

基本布局是这样的。我已将实际命名改为汽车;因为为什么不呢!

我为代码墙道歉,但我觉得包含组件结构的基本要点是相关的。

    <div class="vehicle-history" v-if="fetchComplete && !fetchError">
            <h3 class="header-bold">History</h3>
            <div class="history-container" v-for="car in vehicles.cars" :key="car.id">
                    <div class="vehicle-header">
                            <div class="toyota" v-if="car.model == 'toyota'">
                                    <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
                            </div>
                            <div class="audi" v-if="car.model == 'audi'">
                                    <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
                            </div>
                            <div class="benz" v-if="car.model == 'benz'">
                                    <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
                            </div>
                            <div class="rolls" v-if="car.model == 'rolls'">
                                    <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
                            </div><br />
                            <small v-for="color in car.colors">@{{ color.name }}&nbsp;</small>
                    </div>

                    <div class="vehicle-body">
                            <div class="description">@{{ car.description }}</div>

                            <div class="review-container" v-if="car.reviews.length > 5">
                                    <div class="review" v-for="n in (0, 4)" :key="car.reviews[n].id">
                                            <strong>@{{ car.reviews[n].rating }}</strong> - @{{ car.reviews[n].content }}<br />
                                            <small>@{{ car.reviews[n].created_at.date }} @{{ car.reviews[n].created_at.timezone }}</small>

                                            <span v-show="n == 4 && !car.displayFull"><br />
                                                    <button type="button"
                                                                    class="btn btn-link"
                                                                    data-toggle="collapse"
                                                                    v-on:click="car.displayFull = true"
                                                                    v-bind:data-target="'#expanded-reviews-' + car.id">More details
                                                    </button>
                                            </span>
                                    </div>

                                    <div class="collapse" v-bind:id="'expanded-reviews-' + car.id">
                                            <div class="review" v-for="n in (4, car.reviews.length-1)" :key="car.reviews[n].id">
                                                    <strong>@{{ car.reviews[n].rating }}</strong> - @{{ car.reviews[n].content }}<br />
                                                    <small>@{{ car.reviews[n].created_at.date }} @{{ car.reviews[n].created_at.timezone }}</small>

                                                    <span v-if="n == car.reviews.length-1"><br />
                                                            <button type="button"
                                                                            class="btn btn-link"
                                                                            data-toggle="collapse"
                                                                            v-on:click="car.displayFull = false"
                                                                            v-bind:data-target="'#expanded-reviews-' + car.id">Less details
                                                            </button>
                                                    </span>
                                            </div>
                                    </div>
                            </div>
                    </div>
            </div>
    </div>

我尝试了什么

  • :key添加到相关循环
  • v-show属性从按钮(原来位于此处)移动到父级别。
  • 将其包裹在<keep-alive>(根本不起作用,整体上打破了知名度)
  • v-show交换v-if,反之亦然

预期输出

我想要完成的是确保按钮为&#34;更多细节&#34;在手风琴扩展时隐藏起来(也就是说,当最初点击&#34;更多细节&#34;按钮时),并且如果&#34; Less details&#34;单击按钮。

实际输出

虽然它完成了上述操作,但是从单击按钮到在DOM中应用display: none;属性的延迟时间为2-5秒。然而,对Vue变量的更改似乎是即时的。

您是否知道为什么会这样,如果有一个好的解决方法呢?谢谢你,一如既往!

更新

根据一些建议修改了以下代码示例。这是现有代码的扁平副本,因此这次没有更改命名。

<div class="incident-history text-center col-xs-12 padding-bottom" v-if="fetchComplete && !fetchError">
        <h3 class="heading3 black-text">Incident History</h3>
        <div class="incident-container" v-for="incident in responseData.incident.resolved" :key="incident.id">
                <div class="incident-header">
                        <div :class="'title-' + incident.classification">
                                <span class="incident-id">@{{ incident.type }}_@{{ incident.id }}</span> - @{{ incident.title }}
                        </div><br />
                        <small v-for="monitor in incident.monitors">@{{ monitor.name }}&nbsp;</small>
                </div>

                <div class="incident-body">
                        <div class="description">@{{ incident.content }}</div>
                        <div class="update" v-for="(comment, index) in incident.comments.slice(0,5)">
                                <strong>@{{ comment.type }}</strong> - @{{ comment.content }}<br />
                                <small>@{{ comment.created_at.date }} @{{ comment.created_at.timezone }}</small>
                        </div>

                        <div class="collapse"
                                 v-bind:id="'expanded-update-' + incident.id"
                                 v-if="incident.comments.length > 4">

                                <div class="update" v-for="(comment, index) in incident.comments.slice(5)">
                                        <strong>@{{ comment.type }}</strong> - @{{ comment.content }}<br />
                                        <small>@{{ comment.created_at.date }} @{{ comment.created_at.timezone }}</small>
                                </div>
                        </div>

                        <button type="button"
                                        class="btn btn-link"
                                        data-toggle="collapse"
                                        v-show="incident.comments.length > 4 && !incident.displayFull"
                                        v-on:click="incident.displayFull = !incident.displayFull"
                                        v-bind:data-target="'#expanded-update-' + incident.id">Show more
                        </button>

                        <button type="button"
                                        class="btn btn-link"
                                        data-toggle="collapse"
                                        v-show="incident.comments.length > 4 && incident.displayFull"
                                        v-on:click="incident.displayFull = !incident.displayFull"
                                        v-bind:data-target="'#expanded-update-' + incident.id">Show less
                        </button>
                </div>
        </div>
</div>

我会注意到上面的代码块是在另一个for循环中运行的。基本拓扑结构是这样的(长度可能会有所不同)

responseData: Object
    incident: Object
        active: Array[4]
            0: Object
            1: Object
                Property: SomeValue
                Property: SomeValue
                Property: SomeValue
                Property: SomeValue
                Property: SomeValue
                Comments: Array[3]
                    0: Object
                    1: Object
                        Property: SomeValue
                        Property: SomeValue
                    2: Object
            2: Object
            3: Object

替代解决方案

我已经想出了一个可行的,可能更好的替代方案来改变&#34;阅读更多&#34;到&#34;阅读更少&#34;反之亦然。

button.full-details[aria-expanded="true"]:after {
        content: 'Show less';
}
button.full-details[aria-expanded="false"]:after {
        content: 'Show more';
}

这很好用,只需要在按钮上添加几行CSS和一个类(或者以Bootstrap按钮类为目标,但由于很多原因,这并不是很好)。

那就是说,我打算稍微打开这个,希望能够理解为什么问题首先出现在Vue上。

1 个答案:

答案 0 :(得分:1)

在显示屏上听到2-5秒滞后是令人惊讶的,但在那个模板中有相当多的进展。如果没有测试系统,很难判断建议的更改是否会影响页面视觉效果。

按钮似乎最成问题,每次评论创建一个,但每辆车只需要一个,必须评估v-show或v-if所有这些。

在评论圈外面有一个按钮,

 <button class="btn btn-link" type="button" 
  data-toggle="collapse" :data-target="'#expanded-reviews-' + car.id"
  @click="car.displayFull = !car.displayFull">
    {{ buttonPrompt(car.displayFull) }}
 </button>

我还考虑创建汽车子组件,甚至是评论孙子组件,因为当布局变得困难时,布局变得困难忙。

最后一件事是如此明显,我认为它必须是域重命名的工件。

这个

    <div class="toyota" v-if="car.model == 'toyota'">
      <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
    </div>
    <div class="audi" v-if="car.model == 'audi'">
      <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
    </div>
    <div class="benz" v-if="car.model == 'benz'">
      <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
    </div>
    <div class="rolls" v-if="car.model == 'rolls'">
      <span class="model-id">@{{ car.type }}_@{{ car.id }}</span> - @{{ car.title }}
    </div>

可能会成为这个

    <div :class="car.model">
      <span class="model-id">{{ car.type }}_{{ car.id }}</span> - {{ car.title }}
    </div>

另外,这是什么? @{{

评论后编辑 - 关于创建了多少按钮的问题

听起来你只想要渲染一两个按钮?这是一个测试。

使用模板创建的Cars.vue规范

测试数据有6条评论,

<script>
  export default {
    data () {
      return {
        fetchComplete: true,
        fetchError: false,
        cars: [
          {
            model: 'toyota',
            type: 'hatch',
            id: 1,
            title: 'corolla',
            description: 'grey corolla',
            colors: [{name: 'grey'}, {name: 'grey'}, {name: 'grey'}],
            reviews: [
              {rating: 2, content: 'its grey', created_at: {date: ''}},
              {rating: 2, content: 'its grey', created_at: {date: ''}},
              {rating: 2, content: 'its grey', created_at: {date: ''}},
              {rating: 2, content: 'its grey', created_at: {date: ''}},
              {rating: 2, content: 'its grey', created_at: {date: ''}},
              {rating: 2, content: 'its grey', created_at: {date: ''}},
            ]
          }
        ]
      }
    },

测试,

it('count the buttons', () => {
  const buttons = wrapper.element.querySelectorAll('button');
  console.log(buttons)
})

结果,

LOG LOG: Object{
  0: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>, 
  1: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>, 
  2: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>, 
  3: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">More details</button>, 
  4: <button type="button" data-toggle="collapse" data-target="#expanded-reviews-1" class="btn btn-link">Less details</button>, 
length: 5}

然后,问题是变更检测周期是否足够智能 ,以便在每个周期重新评估按钮创建。我会看看我们是否也可以测试一下。

放置v-if

我刚刚想到这个,

<button class="btn btn-link" ... >
  <span v-if="n === car.reviews.length-1">Less details</span>
</button>

可能 会更好

<button class="btn btn-link" ... v-if="n === car.reviews.length-1">
  Less details
</button>

缺少第一次审核

v-for="n in (0, 4)"循环似乎错过了第一次审核。如果我将评级设置为顺序号,则不会显示第一个。

<div class="review" v-for="n in (0, 4)">
  <strong>@{{ car.reviews[n].rating }}</strong> - @{{ car.reviews[n].content }}

尝试

<div class="review" v-for="(review,n) of car.reviews.slice(0,5)" :key="review.id">
  <strong>@{{ review.rating }}</strong> - @{{ review.content }}

...

<div class="review" v-for="(review,n) of car.reviews.slice(5)">

(保持n为按钮v-if表达式。)