我在vue中创建了一个包含vue-apexchart甜甜圈图的组件。加载页面并加载此组件后,vue-apexchart将动画并显示一个小图表。现在我想并排数据集中的多个这些组件。而不是所有组件同时加载动画,我想要一个小的渲染延迟,以给它一个整体很好的效果。像这样的东西会很好:
<donut :items="series1"></donut>
<donut :items="series2" delay=1500></donut>
vue-apexchart会支持初始化延迟,据我所知,没有任何特定于vue的官方解决方案来延迟组件的渲染。我试图在任何组件钩子中放置一个setTimeout来停止初始化,我也尝试在setTimeout中的v-html标签上的模板元素中注入所有图形DOM,但是apexchart doesent注意到这一点新的dom内容,vue doesent也注意到html绑定。
我创建了这个小提琴,它加载了两个图形实例:https://jsfiddle.net/4f2zkq5c/7/
任何创意建议?
如果您可以重新格式化数据,则可以构建一个系列对象数组,添加一个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索引递增延迟来将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)
})
}
有几种方法可以做到这一点,这取决于你是否可以自己实际修改<animated-component>
逻辑:
<transition-group>
来处理列表渲染VueJS为转换提供了非常方便的支持,您可以使用它来顺序显示您的<animated-component>
。您将需要使用自定义动画库(如VelocityJS)并简单地将延迟存储在元素的数据集中,例如v-bind:data-delay="500"
。 VueJS docs has a very good example on how to introduce staggered transitions for <transition-group>
,下面的例子很大程度上改编自它。
然后使用beforeAppear
and appear
hooks设置<transition-group>
的各个孩子的不透明度。
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>
<animated-component>
处理自己的渲染在这个例子中,你只需将一个数字传递给delay
属性(记得使用v-bind:delay="<number>"
以便传递数字而不是字符串)。然后,在<animated-component>
的已安装生命周期钩子中,您使用计时器来切换组件本身的可见性。
关于如何显示最初隐藏的组件的技术取决于您,但在这里我只是应用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>