
本文说明 salix 原项目已被正式弃用,推荐迁移至更活跃、维护良好的 `salix-core`;提供迁移要点、基础示例及注意事项,帮助开发者避免因使用过时库导致的渲染失败(如 `cannot read properties of undefined (reading 'edits')`)等问题。
Salix 最初是一个基于 Rascal 的函数式前端框架,用于构建响应式 Web 应用。但自 2021 年起,其核心开发已转向 salix-core —— 一个轻量、模块化、API 更一致且持续更新的替代实现。你遇到的 Uncaught TypeError: Cannot read properties of undefined (reading 'edits') 错误,正是旧版 Salix 在初始化或 DOM 补丁(patching)阶段因模型/视图不匹配或生命周期钩子缺失而崩溃的典型表现,根源在于原 salix 库已停止维护,与现代 Rascal 运行时及前端加载流程存在兼容性断层。
✅ 正确做法:迁移到 salix-core
-
替换依赖
在你的 Rascal 项目中,移除旧 salix 依赖,改用:import salix::core::App; import salix::core::Dom; import salix::core::Html;
-
重构应用入口
salix-core 不再使用 makeApp 和 webApp 模式,而是通过 App::start 启动,并显式声明挂载点与初始化逻辑:module examples::Counter import salix::core::App; import salix::core::Dom; import salix::core::Html; // 模型定义 data Model = model(int count); // 初始化 Model init() = model(0); // 更新逻辑 Model update(str action, Model m) { if (action == "increment") return model(m.count + 1); if (action == "decrement") return model(m.count - 1); return m; } // 视图渲染 Dom view(Model m) = div([ h1("Counter: <" + m.count + ">"), button(onClick("increment"), "++"), button(onClick("decrement"), "--") ]); // 启动应用(关键变更) App[Model] counterApp() = App::start( appId: "counterApp", init: init, update: update, view: view, // 可选:指定 HTML 模板路径(若需服务端注入) template: |file:///path/to/index.html| ); -
HTML 模板精简要求
确保 index.html 中仅保留一个具有匹配 id 的空容器,并引入 salix-core.js(而非旧版 salix.js):Salix-Core Counter
⚠️ 注意事项:
- salix-core 不依赖 jQuery,请彻底移除 jquery-1.11.0.min.js 引用,否则可能引发冲突;
-
appId 必须严格匹配 HTML 中 的 id 值,且全局唯一;
- 所有事件处理器(如 onClick)传递的字符串将直接作为 update 函数的第一个参数,确保 update 能正确识别动作名;
- 若需高级组件(如代码编辑器、图表),可结合 salix-contrib 使用,它为 salix-core 提供了 ACE、Chart.js、Mermaid 等封装。
总结:旧 salix 的 makeApp / webApp 流程已失效,patchDOM 报错本质是框架无法获取有效初始模型或 DOM 树。切换至 salix-core 并遵循其声明式启动模式,即可解决空白页与运行时异常问题,同时获得更好的可维护性与扩展能力。










