[英]How to Update the Content of a div in a Separate Function?
我對 JavaScript 很陌生,所以如果這個問題措辭不當或答案很明顯,我深表歉意。 我決定做一個排序可視化項目作為練習。 我目前正在制作的內容是基於 Clément Mihailescu 的這段視頻。
在我的程序中,我有我的渲染 function ,它采用具有隨機值的數組,並使用 array.map() 生成具有根據值高度的條形列,以及條形的顏色:
render() {
const {array} = this.state;
return (
<div className="array-container">
{array.map((value, idx) => (
<div
className="array-bar"
key={idx}
style={{
backgroundColor: PRIMARY_COLOR,
height: `${value}px`,
}}></div>
))}
<button onClick={() => this.resetArray()}>Generate New Array</button>
<button onClick={() => this.mergeSort()}>Merge Sort</button>
<button onClick={() => this.quickSort()}>Quick Sort</button>
<button onClick={() => this.heapSort()}>Heap Sort</button>
<button onClick={() => this.bubbleSort()}>Bubble Sort</button>
</div>
);
}
}
在底部,我有一些在我的數組欄上執行特定排序算法的按鈕和一個“生成新數組”按鈕。 結果最終看起來像這樣
我的問題是我的快速排序算法最終將我的條形圖的 colors 更改為紫色,以指示數組已排序,但我希望能夠在按下“生成新數組”按鈕時將它們更改回原來的顏色. 現在,我的“重置數組” function 生成一個帶有隨機數的新數組,然后將我的主數組的 state 設置為等於:
resetArray() {
const array = [];
for (let i = 0; i < NUMBER_OF_ARRAY_BARS; i++) {
array.push(randomIntFromInterval(5, 400));
}
this.setState({array});
}
所以這成功生成了我的新數組,但顏色沒有被更新
我假設要按照我想要的方式改變數組條的顏色,我應該在這個 resetArray function 中生成我的條,然后在我的原始渲染中簡單地調用它。 問題是我對 JavaScript 的有限理解使得這個看似簡單的修復變得相當困難。 語法明智我只是不知道最好的方法是什么。 如果有人能引導我朝着正確的方向前進,我將不勝感激。 對不起,很長的帖子,我想徹底描述我的問題。
更新描述快速排序算法
這部分代碼不是很好,可能可以更有效地完成。 對於我的 QuickSort 調用,我為條形顏色/值的更改生成了一個單獨的“動畫”數組。 我循環遍歷這個數組,並根據我到達一個字符串(新顏色)還是一個數字(新值)來相應地編輯我的數組索引。
quickSort() {
const animations = getQuickSortAnimations(this.state.array);
for (let i = 0; i < animations.length; i++){
const arrayBars = document.getElementsByClassName('array-bar');
let barIndex;
let barStyle;
// break in the case of array being out of bounds
if (animations[i][0] >= this.state.array.length) { break; }
// switch statement performs either height change or color change
// depending on which is passed through to animations
switch(typeof animations[i][1]){
// color change
case "string":
barIndex = animations[i][0];
barStyle = arrayBars[barIndex].style;
setTimeout(() => {
barStyle.backgroundColor = animations[i][1];
}, i * ANIMATION_SPEED_MS);
break;
//height change
case "number":
barIndex = animations[i][0];
barStyle = arrayBars[barIndex].style;
setTimeout(() => {
barStyle.height = `${animations[i][1]}px`
}, i * ANIMATION_SPEED_MS);
}
}
一開始,我將我的動畫數組設置為“getQuickSortAnimations”,其中我的實際算法發生在一個單獨的文件中。 這是我對動畫數組執行推送的地方,該數組對數組條進行視覺排序:
export function getQuickSortAnimations (array) {
const animations = [];
if (array.length <= 1) { return array; }
quickSort(array, 0, array.length-1, animations)
return animations;
}
function quickSort (array, lowIndex, highIndex, animations){
if (lowIndex >= highIndex) {
animations.push([lowIndex, 'purple']);
return;
}
let pivot = array[highIndex];
let leftPtr = partition(array, lowIndex, highIndex, pivot, animations);
quickSort(array, lowIndex, leftPtr-1, animations);
quickSort (array, leftPtr+1, highIndex, animations);
}
function partition (array, lowIndex, highIndex, pivot, animations){
let leftPtr = lowIndex;
let rightPtr = highIndex-1;
// Coloring our first instance of leftPtr and our Pivot(highIndex)
animations.push([highIndex, 'yellow']);
animations.push([leftPtr, 'red']);
animations.push([rightPtr, 'red']);
while (leftPtr < rightPtr) {
while ((array[leftPtr] <= pivot) && (leftPtr < rightPtr)){
// Send rightPtr to animations once to decolor
animations.push([leftPtr, 'turquoise']);
leftPtr++;
// Send new leftPtr to animations to color new array bar
animations.push([leftPtr, 'red']);
}
while ((array[rightPtr] >= pivot) && (leftPtr < rightPtr)){
// Send rightPtr to animations once to decolor
animations.push([rightPtr, 'turquoise']);
rightPtr--;
// Send new rightPtr to animations to color new array bar
animations.push([rightPtr, 'red']);
}
// temp variable holds the value of our leftPtr index while we perform swap
let temp = array[leftPtr];
// swap our leftPtr with our rightPtr in animations
animations.push([leftPtr, array[rightPtr]]);
// swap our rightPtr with our leftPtr in animations using temp
animations.push([rightPtr, temp]);
// same swap as above but with the our actual array
[array[leftPtr], array[rightPtr]] = [array[rightPtr], array[leftPtr]];
}
animations.push([highIndex, 'turquoise']);
if (array[leftPtr] > array[highIndex]) {
// temp variable holds the value of our leftPtr index while we perform swap
let temp = array[leftPtr];
// swap our leftPtr with our highIndex in animations
animations.push([leftPtr, array[highIndex]]);
// swap our highIndex with our leftPtr in animations using temp
animations.push([highIndex, temp]);
// same swap as above but with the our actual array
[array[leftPtr], array[highIndex]] = [array[highIndex], array[leftPtr]];
animations.push([leftPtr, 'purple']);
}
else {
leftPtr = highIndex;
animations.push([leftPtr, 'purple']);
}
return leftPtr;
}
好的,所以對於反應(或角度)永遠不要嘗試在反應生命周期之外操作 DOM, document.getElementsByClassName
適用於您的情況以更改顏色,但要將其更改回來,您需要使用相同的方法手動執行,這不是什么你必須與反應有關。 你需要做的是:
准備要渲染的數據,完成一個,不僅是數字數組,還有對象數組{value, bgColor (for example}},所以數組中的每個條目都會有它需要渲染的所有數據,假設每個的項目將有不同的顏色。
constructor(props) {
super(props);
const arr = [1, 4, 85, 0, 1, 3, 5, 6, 4, 7, 1, 32, 1, 56, 84];
const arrayToRender = this.getArrayToRender(arr, PRIMARY_COLOR);
this.state = {
array: arr,
arrayToRender: arrayToRender
};
}
getArrayToRender(array, color) {
return array.map((x) => {
return { value: x, bgColor: color };
});
}
並將渲染方法更改為以下內容:
render() {
const { arrayToRender } = this.state;
return (
<div>
<div className="array-container">
{arrayToRender.map((x, idx) => (
<div
className="array-bar"
key={idx}
style={{
backgroundColor: x.bgColor, // <- Here!
height: `${x.value}px`
}}
></div>
))}
</div>
<div>
<button onClick={() => this.resetColor()}>Reset Color</button>
<button onClick={() => this.resetArray()}>Generate New Array</button>
<button onClick={() => this.mergeSort()}>Merge Sort</button>
<button onClick={() => this.quickSort()}>Quick Sort</button>
<button onClick={() => this.heapSort()}>Heap Sort</button>
<button onClick={() => this.bubbleSort()}>Bubble Sort</button>
</div>
</div>
);
}
注意我添加了一個“重置顏色”按鈕
resetColor() {
// You can mutate state objects as is (dangerous)
this.state.arrayToRender.forEach((x) => (x.bgColor = PRIMARY_COLOR));
// But you need to re-set the state to make react reflect the changes
this.setState((prev) => ({ ...prev }));
}
此外, quickSort
方法也需要進行一些更改才能不使用 DOM 函數。
quickSort() {
const animations = getQuickSortAnimations(this.state.array);
for (let i = 0; i < animations.length; i++) {
const curr = this.state.arrayToRender[animations[i][0]];
switch (typeof animations[i][1]) {
case "string":
setTimeout(() => {
curr.bgColor = animations[i][1];
this.setState((prev) => ({ ...prev }));
}, i * ANIMATION_SPEED_MS);
break;
case "number":
setTimeout(() => {
curr.value = animations[i][1];
this.setState((prev) => ({ ...prev }));
}, i * ANIMATION_SPEED_MS);
break;
default:
console.error("Welp");
break;
}
}
// This will reset colors to default one after algo run + 2 sec
const totalDelay = animations.length * ANIMATION_SPEED_MS + 2000; // added 2 seconds
setTimeout(() => {
this.resetColor();
}, totalDelay);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.