在 Mobx 中监听 Window Resize 事件不更新 React Konva 中 Stage 组件的宽度和高度
Listening to Window Resize event in Mobx not updating Stage component's width & height in React Konva
我在 Mobx 中有一个可观察的 win
,它会在 window 调整大小时更新。 updateWin
函数更新 win
observable。
FrameItStore.tsx
import { makeObservable, observable, action, computed } from "mobx";
import { Point, TrafficSignalPosition, IFrameItStore } from "@/types/index";
export class FrameItStore implements IFrameItStore {
id = 0;
win = {
width: window.innerWidth,
height: window.innerHeight
};
box = {
width: 1024,
height: 600
};
trafficSignalColors = [
{
close: "#EF4444",
minimize: "#FBBE25",
maximize: "#49DE80"
},
{
close: "black",
minimize: "blue",
maximize: "orange"
}
];
constructor() {
makeObservable(this, {
win: observable,
updateWin: action.bound,
box: observable,
boxCenter: computed,
trafficSignalPosition: computed,
trafficSignalColors: observable,
id: observable
});
window.addEventListener("resize", this.updateWin);
}
updateWin() {
this.win.width = window.innerWidth;
this.win.height = window.innerHeight;
}
destroyWin() {
window.removeEventListener("resize", this.updateWin);
}
get boxCenter(): Point {
return {
x: (this.win.width - this.box.width) / 2,
y: (this.win.height - this.box.height) / 2
};
}
get trafficSignalPosition(): TrafficSignalPosition {
return {
close: { x: this.boxCenter.x + 20, y: this.boxCenter.y + 20 },
minimize: { x: this.boxCenter.x + 2 * 20, y: this.boxCenter.y + 20 },
maximize: { x: this.boxCenter.x + 3 * 20, y: this.boxCenter.y + 20 }
};
}
}
width
& height
在商店中更新,但我在组件中看不到效果。
如果我将 console.log(this.win)
放在 updateWin
函数中,它会显示更新后的值。但是我在组件中看不到更新的值。
我已经添加了另外 2 个 console.log
语句。
URLBar.tsx
import * as React from "react";
import { Rect } from "react-konva";
import { useFrameItStore } from "../store/index";
import { TrafficSignalPosition, Window } from "../types/index";
export const URLBar = () => {
const frameItStore = useFrameItStore();
console.log("URLBar.tsx =►", frameItStore.win.width);
const box: Window = frameItStore.box;
const trafficSignalPosition: TrafficSignalPosition =
frameItStore.trafficSignalPosition;
return (
<Rect
x={trafficSignalPosition.maximize.x + 20}
y={trafficSignalPosition.maximize.y}
width={box.width - 3 * 20}
height={20}
fill="white"
/>
);
};
Konva.tsx
import * as React from "react";
import { Stage, Layer } from "react-konva";
import { FrameItContext } from "../store/index";
import { BrowserWindow, SiteImage, TrafficSignal, URLBar } from "./index";
import { Stage as StageType } from "konva/types/Stage";
export class Konva extends React.Component {
static contextType = FrameItContext;
context!: React.ContextType<typeof FrameItContext>;
stageRef = React.createRef<StageType>();
handleExportClick = () => {
console.log(
this.stageRef
.current!.getStage()
.toDataURL({ mimeType: "image/jpeg", quality: 1 })
);
};
render() {
const { win } = this.context;
console.log("Konva.tsx -►", win.width);
return (
<>
<Stage width={win.width} height={win.height} ref={this.stageRef}>
<Layer>
<BrowserWindow />
<URLBar />
<TrafficSignal />
<SiteImage />
</Layer>
</Stage>
<button
style={{ position: "absolute", top: "0" }}
onClick={this.handleExportClick}
>
Download Image
</button>
</>
);
}
}
但是 console.log
的 none 再次打印。它也不会更新我的 Konva Stage
的 width
和 height
,因此 Stage
变得有响应。
我错过了什么吗?制作了一个 Minimal CodeSandBox here。请注意控制台,它不会更改值。
您需要将您的组件包装到 observer
装饰器中以使其与 MobX 一起工作
import { observer } from "mobx-react";
class KonvaComponent extends React.Component {
// ..
}
export const Konva = observer(KonvaComponent)
或者如果你使用装饰器建议:
import { observer } from "mobx-react";
@observer
export class Konva extends React.Component {
// ..
}
我在 Mobx 中有一个可观察的 win
,它会在 window 调整大小时更新。 updateWin
函数更新 win
observable。
FrameItStore.tsx
import { makeObservable, observable, action, computed } from "mobx";
import { Point, TrafficSignalPosition, IFrameItStore } from "@/types/index";
export class FrameItStore implements IFrameItStore {
id = 0;
win = {
width: window.innerWidth,
height: window.innerHeight
};
box = {
width: 1024,
height: 600
};
trafficSignalColors = [
{
close: "#EF4444",
minimize: "#FBBE25",
maximize: "#49DE80"
},
{
close: "black",
minimize: "blue",
maximize: "orange"
}
];
constructor() {
makeObservable(this, {
win: observable,
updateWin: action.bound,
box: observable,
boxCenter: computed,
trafficSignalPosition: computed,
trafficSignalColors: observable,
id: observable
});
window.addEventListener("resize", this.updateWin);
}
updateWin() {
this.win.width = window.innerWidth;
this.win.height = window.innerHeight;
}
destroyWin() {
window.removeEventListener("resize", this.updateWin);
}
get boxCenter(): Point {
return {
x: (this.win.width - this.box.width) / 2,
y: (this.win.height - this.box.height) / 2
};
}
get trafficSignalPosition(): TrafficSignalPosition {
return {
close: { x: this.boxCenter.x + 20, y: this.boxCenter.y + 20 },
minimize: { x: this.boxCenter.x + 2 * 20, y: this.boxCenter.y + 20 },
maximize: { x: this.boxCenter.x + 3 * 20, y: this.boxCenter.y + 20 }
};
}
}
width
& height
在商店中更新,但我在组件中看不到效果。
如果我将 console.log(this.win)
放在 updateWin
函数中,它会显示更新后的值。但是我在组件中看不到更新的值。
我已经添加了另外 2 个 console.log
语句。
URLBar.tsx
import * as React from "react";
import { Rect } from "react-konva";
import { useFrameItStore } from "../store/index";
import { TrafficSignalPosition, Window } from "../types/index";
export const URLBar = () => {
const frameItStore = useFrameItStore();
console.log("URLBar.tsx =►", frameItStore.win.width);
const box: Window = frameItStore.box;
const trafficSignalPosition: TrafficSignalPosition =
frameItStore.trafficSignalPosition;
return (
<Rect
x={trafficSignalPosition.maximize.x + 20}
y={trafficSignalPosition.maximize.y}
width={box.width - 3 * 20}
height={20}
fill="white"
/>
);
};
Konva.tsx
import * as React from "react";
import { Stage, Layer } from "react-konva";
import { FrameItContext } from "../store/index";
import { BrowserWindow, SiteImage, TrafficSignal, URLBar } from "./index";
import { Stage as StageType } from "konva/types/Stage";
export class Konva extends React.Component {
static contextType = FrameItContext;
context!: React.ContextType<typeof FrameItContext>;
stageRef = React.createRef<StageType>();
handleExportClick = () => {
console.log(
this.stageRef
.current!.getStage()
.toDataURL({ mimeType: "image/jpeg", quality: 1 })
);
};
render() {
const { win } = this.context;
console.log("Konva.tsx -►", win.width);
return (
<>
<Stage width={win.width} height={win.height} ref={this.stageRef}>
<Layer>
<BrowserWindow />
<URLBar />
<TrafficSignal />
<SiteImage />
</Layer>
</Stage>
<button
style={{ position: "absolute", top: "0" }}
onClick={this.handleExportClick}
>
Download Image
</button>
</>
);
}
}
但是 console.log
的 none 再次打印。它也不会更新我的 Konva Stage
的 width
和 height
,因此 Stage
变得有响应。
我错过了什么吗?制作了一个 Minimal CodeSandBox here。请注意控制台,它不会更改值。
您需要将您的组件包装到 observer
装饰器中以使其与 MobX 一起工作
import { observer } from "mobx-react";
class KonvaComponent extends React.Component {
// ..
}
export const Konva = observer(KonvaComponent)
或者如果你使用装饰器建议:
import { observer } from "mobx-react";
@observer
export class Konva extends React.Component {
// ..
}