【问题标题】:Delay the rendering of a component in vue在 vue 中延迟组件的渲染
【发布时间】:2019-04-08 20:30:33
【问题描述】:

我在 vue 中创建了一个包含 vue-apexchart 圆环图的组件。一旦页面加载并加载了这个组件,vue-apexchart 就会动画并显示一个小图。 现在我想从一个数据集中并排实例化多个这些组件。而不是所有组件同时加载动画,我想要一个小的渲染延迟来给它一个整体不错的效果。像这样的东西会很好:

  <donut :items="series1"></donut>
  <donut :items="series2" delay=1500></donut>

vue-apexchart 不支持初始化延迟,据我所知,没有任何特定于 vue 的官方解决方案可以延迟组件的渲染。 我试图在任何组件挂钩中放置一个 setTimeout 来停止初始化, 我还尝试在 setTimeout 中的 v-html 标记上的模板元素中注入所有图形 DOM,但是 apexchart 并没有注意到这个新的 dom 内容,vue 也没有注意到 html 绑定。

我创建了这个小提琴,它加载了两个图表实例: https://jsfiddle.net/4f2zkq5c/7/

有什么创意建议吗?

【问题讨论】:

    标签: vuejs2


    【解决方案1】:

    有几种方法可以做到这一点,这取决于你是否真的可以自己修改&lt;animated-component&gt;逻辑:

    1。使用VueJS内置的&lt;transition-group&gt;处理列表渲染

    VueJS 提供了对转换的非常方便的支持,您可以使用它来顺序显示您的&lt;animated-component&gt;。您将需要使用自定义动画库(如 VelocityJS)并将延迟存储在元素的数据集中,例如v-bind:data-delay="500"VueJS docs has a very good example on how to introduce staggered transitions for &lt;transition-group&gt;,下面的例子很大程度上改编自它。

    然后您使用beforeAppear and appear hooks 设置&lt;transition-group&gt; 的各个子项的不透明度。

    Vue.component('animated-component', {
      template: '#animatedComponentTemplate',
      props: {
        data: {
          required: true
        }
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        dataset: {
          first: 'Hello world',
          second: 'Foo bar',
          third: 'Lorem ipsum'
        }
      },
      methods: {
        beforeAppear: function(el) {
          el.style.opacity = 0;
        },
        appear: function(el, done) {
          var delay = +el.dataset.delay;
          setTimeout(function() {
            Velocity(
              el, {
                opacity: 1
              }, {
                complete: done
              }
            )
          }, delay)
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
      <transition-group name="fade" v-on:before-appear="beforeAppear" v-on:appear="appear">
        <animated-component v-bind:data="dataset.first" v-bind:key="0"> </animated-component>
        <animated-component v-bind:data="dataset.second" v-bind:key="1" v-bind:data-delay="500"> </animated-component>
        <animated-component v-bind:data="dataset.third" v-bind:key="2" v-bind:data-delay="1000"> </animated-component>
      </transition-group>
    </div>
    
    <script type="text/x-template" id="animatedComponentTemplate">
      <div>
        <h1>Animated Component</h1>
        {{ data }}
      </div>
    </script>

    2。让&lt;animated-component&gt;处理自己的渲染

    在本例中,您只需将数字传递给delay 属性(请记住使用v-bind:delay="&lt;number&gt;",以便传递数字而不是字符串)。然后,在&lt;animated-component&gt; 的mounted 生命周期挂钩中,您使用计时器来切换组件本身的可见性。

    您希望如何显示最初隐藏的组件的技术取决于您,但这里我只是应用了0 的初始不透明度,然后在 setTimeout 之后对其进行转换。

    Vue.component('animated-component', {
      template: '#animatedComponentTemplate',
      props: {
        data: {
          required: true
        },
        delay: {
          type: Number,
          default: 0
        }
      },
      data: function() {
        return {
          isVisible: false
        };
      },
      computed: {
        styleObject: function() {
          return {
            opacity: this.isVisible ? 1 : 0
          };
        }
      },
      mounted: function() {
        var that = this;
        window.setTimeout(function() {
          that.isVisible = true;
        }, that.delay);
      }
    });
    
    new Vue({
      el: '#app',
      data: {
        dataset: {
          first: 'Hello world',
          second: 'Foo bar',
          third: 'Lorem ipsum'
        }
      }
    });
    .animated-component {
      transition: opacity 0.25s ease-in-out;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="app">
      <animated-component v-bind:data="dataset.first"> </animated-component>
      <animated-component v-bind:data="dataset.second" v-bind:delay="500"> </animated-component>
      <animated-component v-bind:data="dataset.third" v-bind:delay="1000"> </animated-component>
    </div>
    
    <script type="text/x-template" id="animatedComponentTemplate">
      <div class="animated-component" v-bind:style="styleObject">
        <h1>Animated Component, delay: {{ delay }}</h1>
        {{ data }}
      </div>
    </script>

    【讨论】:

    • 非常感谢您的全面回答。我不认为我可以使用您的任何建议,因为我的组件正在包装 Vue 顶点图表库 (apexcharts.com/javascript-chart-demos/pie-charts/update-donut) 顶点图表控制它自己的动画周期,我不能延迟。我延迟它的唯一方法是延迟我认为的组件。您的第一个建议使用已渲染的对象,这些对象首先隐藏然后显示。你的第二个建议有点像同样的问题 - 图表已经渲染并且动画已经完成,当我稍后显示它时。
    • @Farsen 这就是为什么在您的问题中包含 MCVE 很重要的原因:在您的原始问题中,没有说明您面临哪些限制,更不用说您正在使用什么库了。跨度>
    • 你是对的,对此感到抱歉。我现在更新了我的问题。
    【解决方案2】:

    如果您有可能重新格式化您的数据,您可以构建一个系列对象数组,添加一个show: true/false 属性并对其进行迭代:

    //template
    <div v-for="serie in series">
      <donut :items="serie.data" v-if="serie.show"></donut>
    </div>
    
    //script
    data: function() {
      return {
        series: [
          { data: [44, 55, 41, 17, 15], show: false },
          { data: [10, 20, 30], show: false },
        ]
      }
    }
    

    现在您可以创建一个setTimeout 函数,该函数将通过根据意甲索引增加延迟来将serie.show 更改为true
    然后在挂载的钩子上添加函数:

    methods: {
      delayedShow (serie, idx) {
        let delay = 1500 * idx
        setTimeout(() => {
          serie.show = true
        }, delay)
      }
    },
    mounted () {
      this.series.forEach((serie, idx) => {
        this.delayedShow(serie, idx)
      })
    }
    

    Live example

    【讨论】:

      猜你喜欢
      • 2011-07-07
      • 2015-08-28
      • 2019-01-21
      • 2020-11-14
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多