如何使用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>
优化点说明
- 状态本地化:每个Row组件独立维护自身的
isEditing和inputValue状态,父组件不再需要全局管理编辑索引,状态变化仅影响当前行。 - 减少不必要重绘:只有触发编辑的行组件会重新渲染,其他行组件的状态未发生变化,不会参与重绘计算,提升了大数据量场景下的性能。
- 职责更清晰:Row组件负责自身的展示、编辑逻辑和状态管理,Home组件仅专注于数据的整体渲染和更新回调,代码结构更易维护。
内容的提问来源于stack exchange,提问作者Shail
相关产品推荐
相关产品推荐

