Skip to content

Commit aa4f652

Browse files
committed
稳定性优化
1 parent 05ec005 commit aa4f652

File tree

3 files changed

+78
-14
lines changed

3 files changed

+78
-14
lines changed

src/App.vue

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
v-model="graphData[i]"
1414
@delete="graphData.splice(i, 1)"
1515
:key="dataItem.key"
16+
@require-full-update="fullUpdate"
1617
/>
1718
</VueDraggable>
1819
<div class="plot-data add-data">
@@ -25,15 +26,18 @@
2526
<div @click="handleImport()" class="add-data-opt import">↓ 导入</div>
2627
</div>
2728
</div>
28-
<CodeDisplay :dataArr="cloneDeep(graphData)" />
29+
<CodeDisplay :dataArr="cloneArr(graphData)" />
2930
</div>
3031
<div id="divider" @mousedown="handleDrag"></div>
3132
<div id="graph" ref="shellRef">
3233
<Graph
33-
:graphData="cloneDeep(graphData)"
34+
:data="cloneArr(graphData)"
3435
:width="graphWidth"
3536
:height="graphHeight"
3637
:key="key"
38+
@requireFullUpdate="fullUpdate"
39+
@requirePostUpdate="key++"
40+
v-model="fullUpdateState"
3741
/>
3842
</div>
3943
</div>
@@ -46,17 +50,19 @@ import DataBlock from "./components/dataBlock.vue";
4650
import CodeDisplay from "./components/codeDisplay.vue";
4751
import { VueDraggable } from "vue-draggable-plus";
4852
import type { FunctionPlotDatum, FunctionPlotOptions } from "function-plot";
49-
import { onMounted, ref, watch } from "vue";
53+
import { onMounted, ref } from "vue";
5054
import { cloneDeep } from "lodash-es";
5155
import JSON5 from "json5";
5256
import base64 from "base-64";
5357
import utf8 from "utf8";
5458
import { Datum } from "./consts";
5559
5660
const graphData = ref<Datum[]>([{ fn: "x^2", key: 1 }]);
61+
5762
const graphWidth = ref(0),
5863
graphHeight = ref(0);
5964
const key = ref(0);
65+
const fullUpdateState = ref(false);
6066
const sideRatio = ref(33);
6167
const onResize = ref(false);
6268
const shellRef = ref<HTMLDivElement>();
@@ -67,6 +73,24 @@ function handleResize() {
6773
}
6874
}
6975
76+
function cloneArr<T extends Object[]>(obj: T) {
77+
const cloned = cloneDeep(obj);
78+
function removeUndefined(obj: Record<string, any>) {
79+
for (const key in obj) {
80+
console.log(1);
81+
if (obj[key] === undefined) delete obj[key];
82+
if (
83+
typeof obj[key] === "object" &&
84+
obj[key] !== null &&
85+
!Array.isArray(obj[key])
86+
)
87+
removeUndefined(obj[key]);
88+
}
89+
}
90+
cloned.forEach((item) => removeUndefined(item));
91+
return cloned as T;
92+
}
93+
7094
function importMapper(item: FunctionPlotDatum): Datum {
7195
if (item.graphType === "text")
7296
return {
@@ -81,6 +105,11 @@ function importMapper(item: FunctionPlotDatum): Datum {
81105
};
82106
}
83107
108+
function fullUpdate() {
109+
fullUpdateState.value = true;
110+
key.value++;
111+
}
112+
84113
onMounted(() => {
85114
const rawCode = window.location.search.match(/\?code=(.+)$/)?.[1];
86115
if (rawCode)
@@ -96,11 +125,11 @@ onMounted(() => {
96125
97126
window.addEventListener("resize", handleResize);
98127
handleResize();
99-
watch(graphData, () => key.value++, { deep: true });
100128
});
129+
101130
function handleDrag() {
102131
onResize.value = true;
103-
const xfull = outerWidth;
132+
const xfull = window.innerWidth;
104133
const mousemove = (event: MouseEvent) =>
105134
(sideRatio.value = (event.clientX / xfull) * 100);
106135
document.addEventListener("mousemove", mousemove);
@@ -110,6 +139,7 @@ function handleDrag() {
110139
handleResize();
111140
});
112141
}
142+
113143
function handleImport() {
114144
const raw = prompt("源数据:");
115145
if (!raw) return;

src/components/dataBlock.vue

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@
88
{{ type.label }}
99
</option>
1010
</select>
11-
<select v-model="dataItem.graphType" v-if="dataItem.graphType !== 'text'">
11+
<select
12+
v-model="dataItem.graphType"
13+
v-if="dataItem.graphType !== 'text'"
14+
@change="graphTypeChange(dataItem)"
15+
>
1216
<option v-if="!fnType.notAllowedInInterval" :value="undefined">
1317
{{ graphTypeArr[0].label }}
1418
</option>
@@ -26,7 +30,7 @@
2630
:class="{ active: !blockFolded }"
2731
@click="blockFolded = !blockFolded"
2832
>
29-
更多
33+
{{ blockFolded ? "展开" : "收起" }}
3034
</button>
3135
<button class="delete blockBtn" @click="emit('delete')">删除</button>
3236
</div>
@@ -65,15 +69,21 @@
6569
</div>
6670
</template>
6771
<script setup lang="ts">
68-
import { fnTypeArr, graphTypeArr, inputTypeArr, getFnType, Datum } from "../consts";
72+
import {
73+
fnTypeArr,
74+
graphTypeArr,
75+
inputTypeArr,
76+
getFnType,
77+
Datum,
78+
} from "../consts";
6979
import { ref, computed } from "vue";
7080
import StrInputs from "./dataBlockInner/strInputs.vue";
7181
import CoordInputs from "./dataBlockInner/coordInputs.vue";
7282
import SwitchInputs from "./dataBlockInner/switchInputs.vue";
7383
import CoordArrInputs from "./dataBlockInner/coordArrInputs.vue";
7484
import OptInputs from "./dataBlockInner/optInputs.vue";
7585
76-
const emit = defineEmits(["delete"]);
86+
const emit = defineEmits(["delete", "requireFullUpdate"]);
7787
const dataItem = defineModel<Datum>();
7888
const block = ref<HTMLDivElement>();
7989
const blockFolded = ref(true);
@@ -92,6 +102,20 @@ function fnTypeChange(dataItem: Datum) {
92102
block.value.querySelectorAll("input").forEach((ele) => (ele.value = ""));
93103
}
94104
}
105+
const scatteredSet = new WeakSet<Datum>();
106+
function graphTypeChange(dataItem: Datum) {
107+
if (dataItem.graphType === "scatter") {
108+
if (!scatteredSet.has(dataItem)) {
109+
scatteredSet.add(dataItem);
110+
emit("requireFullUpdate");
111+
}
112+
} else {
113+
if (scatteredSet.has(dataItem)) {
114+
scatteredSet.delete(dataItem);
115+
emit("requireFullUpdate");
116+
}
117+
}
118+
}
95119
const fnType = computed(() => getFnType(dataItem.value?.fnType));
96120
</script>
97121

src/components/graph.vue

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,44 @@
44

55
<script setup lang="ts">
66
import { onMounted, ref, watch } from "vue";
7-
import { throttle } from "lodash-es";
7+
import { cloneDeep, throttle } from "lodash-es";
88
import type { FunctionPlotDatum } from "function-plot";
99
import { Datum, findError } from "../consts";
10-
const { graphData, width, height } = defineProps<{
11-
graphData: Datum[];
10+
const { data, width, height } = defineProps<{
11+
data: Datum[];
1212
width: number;
1313
height: number;
1414
}>();
15+
const emit = defineEmits(["requireFullUpdate", "requirePostUpdate"]);
16+
const fullUpdateState = defineModel<boolean>();
1517
1618
const plotRef = ref<HTMLDivElement | null>(null);
1719
onMounted(async () => {
1820
const functionPlot = (await import("function-plot")).default;
1921
watch(
20-
[() => width, () => height],
22+
[() => width, () => height, () => data],
2123
throttle(() => {
24+
const graphData = cloneDeep(data);
2225
const flag = findError(graphData);
26+
if (flag) return;
2327
try {
2428
plotRef.value &&
2529
functionPlot({
2630
target: plotRef.value,
2731
data: <FunctionPlotDatum[]>(
28-
(flag ? graphData.slice(0, flag) : graphData)
32+
// (flag ? graphData.slice(0, flag) : graphData)
33+
graphData
2934
),
3035
width: width - 20,
3136
height: height - 20,
3237
});
38+
if (fullUpdateState.value) {
39+
fullUpdateState.value = false;
40+
emit("requirePostUpdate");
41+
}
3342
} catch (e) {
3443
console.log(e);
44+
if (!fullUpdateState.value) emit("requireFullUpdate");
3545
}
3646
}, 200),
3747
{ immediate: true }

0 commit comments

Comments
 (0)