前端状态的一个疑问

270 天前
 MinonHeart

想要的效果

调用 add 添加数据 -> 清空渲染器 -> 设置新的渲染器数据 -> 重新渲染

非 add 调用不清空渲染器

传统方式

class Module {
    renderer = null; // 渲染器实例

    // 手动添加数据并渲染
    add(data) {
        this.renderer.clear(); // 清空渲染器(如果是手动添加数据则需要先清空渲染器)
        this.renderer.setData(data); // 更新渲染器数据
        this.renderer.render(); // 重新渲染新数据
    }
}

状态方式

class ModuleState {
    needClear = false; // 标记需要清空渲染器
    @observable data = null; // 新的渲染数据

    // 手动添加数据
    add(data) {
    	this.needClear = true;
        this.data = data;
    }
}

// ModuleView 是异步的,ModuleState 中也拿不到 ModuleView
class ModuleView {
    state = null; // ModuleState
    renderer = null; // 渲染器实例

    constructor() {
        // 当 ModuleState.data 发生变化时,自动渲染数据
        autorun(() => this.render(this.state.data))
    }

    render(data) {
        // 如果是手动添加数据则需要清空渲染器
        if (this.state.needClear) {
            this.renderer.clear();
            this.state.needClear = false;
        }
        this.renderer.setData(data); // 更新渲染数据
        this.renderer.render(); // 重新渲染新的数据
    }
}

问题

在状态方式中,需要额外的一个标记来表示是否需要清空渲染器。

  1. 这个标记是全局可用的,是否合理?
    • 带来了调试上麻烦(实际情况这类标记会更多)
    • 在传统方式中,标记相当于在 add 函数内部,是私有的
  2. 是否有更好的方式来处理这个标记?
547 次点击
所在节点    问与答
2 条回复
george2077
270 天前
全局的话不好管理状态,调试不方便,封装性差
解决方法局部状态管理:
class ModuleView {
state = null; // ModuleState
renderer = null; // 渲染器实例
needClear = false; // 私有标记

constructor() {
autorun(() => this.render(this.state.data))
}

render(data) {
if (this.needClear) {
this.renderer.clear();
this.needClear = false;
}
this.renderer.setData(data);
this.renderer.render();
}

add(data) {
this.needClear = true;
this.state.data = data;
}
}
或者用回调或事件;
class ModuleState {
data = null;

add(data, callback) {
this.data = data;
if (callback) {
callback();
}
}
}

class ModuleView {
state = null;
renderer = null;

constructor() {
autorun(() => this.render(this.state.data))
}

render(data) {
this.renderer.setData(data);
this.renderer.render();
}

clearRenderer() {
this.renderer.clear();
}
}

// 使用
const state = new ModuleState();
const view = new ModuleView();

state.add(someData, () => view.clearRenderer());
MinonHeart
270 天前
@george2077 很合理。

当前架构是 View 初始化后,任何地方都访问不到。按这样改得变更架构了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/970035

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX