You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Mithril.js高效切换组件?避免编辑时重绘Home组件

列表展示与编辑功能的优化实现

问题背景

现有一组数据列表,通过Home组件遍历数据,用Item组件渲染每行及编辑按钮,点击后切换为EditItem组件编辑。功能正常,但编辑操作会导致整个Home组件重绘,希望找到更优实现方式。

优化思路

当前实现依赖父组件维护全局的editingIndex,状态变化时会触发整个列表的重新计算。优化核心是让每行组件独立管理自身的编辑状态,避免父组件状态变化影响所有行:

  • 将展示与编辑逻辑整合到单个Row组件中,由组件自身维护编辑状态和输入值
  • 父组件仅负责传递数据和保存回调,不再管理全局编辑索引
  • 仅触发编辑的行组件会重绘,其他行不受影响

优化后的代码实现

JavaScript 部分

// 整合展示与编辑的Row组件
var Row = {
    oninit: function(vnode) {
        // 组件内部维护状态:是否处于编辑模式、输入框值
        vnode.state.isEditing = false;
        vnode.state.inputValue = vnode.attrs.row.text;
    },
    view: function(vnode) {
        const { row, onSave } = vnode.attrs;
        const { isEditing, inputValue } = vnode.state;

        if (isEditing) {
            // 编辑状态渲染
            return m("tr", [
                m("td", row.id),
                m("td", m("input", {
                    value: inputValue,
                    oninput: e => vnode.state.inputValue = e.target.value
                })),
                m("td", [
                    m("button", {
                        onclick: () => {
                            onSave(row.id, inputValue);
                            vnode.state.isEditing = false;
                        }
                    }, "保存"),
                    m("button", {
                        onclick: () => {
                            vnode.state.isEditing = false;
                            vnode.state.inputValue = row.text;
                        }
                    }, "取消")
                ])
            ]);
        } else {
            // 展示状态渲染
            return m("tr", [
                m("td", row.id),
                m("td", row.text),
                m("td", m("button", {
                    onclick: () => vnode.state.isEditing = true
                }, "编辑"))
            ]);
        }
    }
};

// Home组件
var Home = {
    view: function() {
        return m("div", [
            m("table", { border: 1 }, [
                m("thead", [
                    m("tr", [
                        m("th", "ID"),
                        m("th", "文本"),
                        m("th", "操作")
                    ])
                ]),
                m("tbody", this.data.map(row => 
                    m(Row, {
                        row: row,
                        onSave: (id, newValue) => {
                            // 根据ID找到对应行并更新数据
                            const targetRow = this.data.find(item => item.id === id);
                            if (targetRow) targetRow.text = newValue;
                        }
                    })
                ))
            ])
        ]);
    },
    data: [
        { id: 10, text: "条目1" },
        { id: 20, text: "条目2" },
        { id: 30, text: "条目3" }
    ]
};

// 挂载组件
m.mount(document.body, Home);

HTML 部分

<!DOCTYPE HTML>
<html>
    <head>
        <title>Mithril.js 列表编辑优化</title>
    </head>
    <body>
        <script src="https://unpkg.com/mithril/mithril.min.js"></script>
    </body>
</html>

优化点说明

  1. 状态本地化:每个Row组件独立维护自身的isEditing和inputValue状态,父组件不再需要全局管理编辑索引,状态变化仅影响当前行。
  2. 减少不必要重绘:只有触发编辑的行组件会重新渲染,其他行组件的状态未发生变化,不会参与重绘计算,提升了大数据量场景下的性能。
  3. 职责更清晰:Row组件负责自身的展示、编辑逻辑和状态管理,Home组件仅专注于数据的整体渲染和更新回调,代码结构更易维护。

内容的提问来源于stack exchange,提问作者Shail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 17:19:53