首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >缓慢的DOM变化与v-显示

缓慢的DOM变化与v-显示
EN

Stack Overflow用户
提问于 2017-11-03 23:57:44
回答 1查看 2.2K关注 0票数 2

我一直在排除一个问题,在嵌套的v-for循环中,一个简单的v-show指令占用了大约4秒的时间在DOM中实际应用display: none;属性。

基本的布局是这样的。我已经把真正的名字改成了汽车,因为为什么不呢?

我对代码墙表示歉意,但我认为包含组件结构的基本jist是相关的。

代码语言:javascript
复制
    <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属性从按钮(它最初位于的位置)移到父span。
  • 将它封装在<keep-alive>中(根本不起作用,它破坏了整个可见性)
  • v-show替换为v-if,反之亦然

预期输出

我想要完成的是,当手风琴展开时,确保“更多细节”的按钮隐藏起来(也就是说,当“更多细节”按钮最初被单击时),如果单击“较少的细节”按钮,则重新出现。

实际输出

虽然这样做,但从单击按钮到获取DOM中应用的display: none;属性有2-5秒的延迟。然而,对Vue变量的更改立即出现。

你知道为什么会这样吗?如果有一个很好的解决办法的话?谢谢,一如既往!

更新

下面根据一些建议修订了代码示例。这是一个现有代码的平面副本,所以这一次不会更改命名。

代码语言:javascript
复制
<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-循环内部运行。基本的拓扑是这样的(长度可能会变化)

代码语言:javascript
复制
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

替代解决方案

我想出了一个可行的方法,可以更好地替代“多读”改为“少读”,反之亦然。

代码语言:javascript
复制
button.full-details[aria-expanded="true"]:after {
        content: 'Show less';
}
button.full-details[aria-expanded="false"]:after {
        content: 'Show more';
}

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

话虽如此,我还是要把这个问题放在一边,希望能理解为什么Vue会在一开始就出现这个问题。

EN

回答 1

Stack Overflow用户

发布于 2017-11-04 10:32:56

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

按钮似乎是最有问题的,创建一个每个评论,但只需要一个每辆车,必须评估v-显示或v-如果所有的。

在评论循环外有一个按钮,

代码语言:javascript
复制
 <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>

我还会考虑创建一个car子组件,甚至是一个review外孙组件,因为在如此繁忙的情况下,对布局的推理变得很困难。

最后一件事很明显,我想这一定是域名重命名的产物。

代码语言:javascript
复制
    <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>

可能会变成这样

代码语言:javascript
复制
    <div :class="car.model">
      <span class="model-id">{{ car.type }}_{{ car.id }}</span> - {{ car.title }}
    </div>

还有,这是什么?@{{

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

听起来好像你只期待一个或两个按钮被渲染?这是个测试。

根据您的模板创建的Cars.vue规范,

测试数据有6个评论,

代码语言:javascript
复制
<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: ''}},
            ]
          }
        ]
      }
    },

这次测试,

代码语言:javascript
复制
it('count the buttons', () => {
  const buttons = wrapper.element.querySelectorAll('button');
  console.log(buttons)
})

结果,

代码语言:javascript
复制
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布局

我刚想到,这个

代码语言:javascript
复制
<button class="btn btn-link" ... >
  <span v-if="n === car.reviews.length-1">Less details</span>
</button>

可能会这样更好

代码语言:javascript
复制
<button class="btn btn-link" ... v-if="n === car.reviews.length-1">
  Less details
</button>

缺失第一次审查

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

代码语言:javascript
复制
<div class="review" v-for="n in (0, 4)">
  <strong>@{{ car.reviews[n].rating }}</strong> - @{{ car.reviews[n].content }}

试一试

代码语言:javascript
复制
<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)">

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47105944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档