我在一個 Vue 應用程式中有一個 UI 更新,我一次更新了 10 個頂點圖表條形圖。完全加載大約需要一秒鐘,在此期間我想展示一個svg spinner。但是,在 av-if="showSpinner"上div包含該微調器并設定showSpinner.value = true;a的正常模式const showSpinner = ref(false);不起作用。例如:
<template>
<div v-if="showSpinner">
[svg spinner]
</div>
<div>
[10 apexcharts I'm updating at once with already existing local data]
</div>
</template>
<script setup lang="ts">
import { ref, nextTick } from 'vue';
const showSpinner = ref(false);
const state = reactive({
dataForCharts: {},
});
const someFuncThatGetsCalledMuchLater = () => {
showSpinner.value = true;
// I've also tried await nextTick(); (after making this
// function itself async) but that didn't make any difference.
nextTick(() => {
// some code that modifies state.dataForCharts, causing the charts to redraw
});
}
</script>
甚至忽略必須存在以便showSpinner.value = false;稍后設定的代碼,這是我尚未解決的另一個問題,上面的代碼直到所有圖表都更新后才顯示微調器(這基本上凍結了網頁 1s ,因為我的理解是 Javascript 是單執行緒的)。
所以我的兩個問題是:
- 如何在圖表開始更新和凍結網頁之前讓這個 svg 微調器出現?
- 因為我還沒有解決(1),所以還沒到這里,但是當圖表完成更新時,我怎樣才能收聽回呼呢?我不認為指令對我有用,因為它們似乎應該只作用于它們所附加的元素,而且我認為
showSpinner.value = false;內部設定onUpdated(...)也不起作用,因為在每次反應更新后都會呼叫它,包括 , 的更改showSpinner.value = true;,因此將其設定為 false 將立即撤消我們剛剛將其設定為 true 的事實。
uj5u.com熱心網友回復:
1. 在圖表前顯示微調器
基本上你只想先更新showSpinner,然后觸發重繪,然后渲染圖表。最簡單的方法是使用nextTick
import { ref, nextTick } from 'vue';
const someFuncThatGetsCalled = async () => {
showSpinner.value = true;
await nextTick(); // could also pass a callback
state.dataForCharts = someDataAndNotNullAnyMore;
}
nextTick,根據檔案,應該可以作業:
等待下一次 DOM 更新重繪 的實用程式。
細節
當你在 Vue 中改變回應狀態時,生成的 DOM 更新不會同步應用。相反,Vue 會緩沖它們直到“下一個滴答”,以確保每個組件只更新一次,無論您進行了多少狀態更改。
nextTick()可以在狀態更改后立即使用以等待 DOM 更新完成。您可以將回呼作為引數傳遞,也可以等待回傳的 Promise。
但是,即使更新了 DOM,瀏覽器也可能不會重新渲染它。后面的js可能會阻塞渲染,本質上渲染nextTick()無用。要處理這個問題,您需要手動推遲啟動 js-heavy 部分,直到 dom 呈現初始更改。你可以使用setTimeoutorrequestAnimationFrame來完成它。使用setTimeout在某些情況下可能有效,但據報道在瀏覽器之間的行為不一致。它也可以解決類似的問題nextTick,您可能需要使用比 0 更高的超時來適應。使用嵌套requestAnimationFrame呼叫將等待瀏覽器在繼續之前進行兩次渲染,因此理論上更可靠。
async function nextTwik(){
return new Promise((resolve)=>{
requestAnimationFrame(()=>{
requestAnimationFrame(()=>{
resolve()
})
})
})
}
那么您可以用作:
const someFuncThatGetsCalled = async () => {
showSpinner.value = true;
await nextTwik();
state.dataForCharts = someDataAndNotNullAnyMore;
};
2. 如何判斷圖表是否已掛載
apexcharts 允許傳遞一個配置選項,您可以在其中定義事件
檔案
const chartsMounted = ref(0);
const chartOptions = {
chart: {
id: "bar-shart",
events: {
mounted(){
chartsMounted.value ;
}
},
// animations, etc...
},
// dataLabels, plotOptions, xaxis, etc...
}
const someFuncThatGetsCalled = async () => {
showSpinner.value = true;
await nextTwik(); // defined above
// kick off chart rendering
state.dataForCharts = someData;
}
watch(chartsMounted, (num) => {
if (num === 10) {
// all 10 charts loaded
console.log("??great success??");
showSpinner.value = false
}
})
只要所有圖表都安裝了更新的事件偵聽器,chartsMounted它就會在加載所有圖表時通知您。
更新
圖表事件功能是使用 Vue2 而不是 Vue3 測驗的。ATTOW, vue3 版本中有一個錯誤,這不起作用。根據回復,apexcharts 支持將事件偵聽器添加到組件中@,例如@mounted。我也離開了options.events基于解決方案,因為它反映在檔案中。
const chartsMounted = ref(0);
function onChartMounted(){
chartsMounted.value ;
}
const someFuncThatGetsCalled = async () => {
showSpinner.value = true;
await nextTwik();
// kick off chart rendering
state.dataForCharts = someData;
}
watch(chartsMounted, (num) => {
if (num === 10) {
// all 10 charts loaded
console.log("??great success??");
showSpinner.value = false
}
})
模板:
<apex-chart :options="options" :series="series" @mounted="onChartMounted" />
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/516157.html
標籤:javascriptcssVue.jssvgVuejs3
