Observable 中 HTML 需用 html... 函数注入,依赖响应式变量与 DOM 节点引用;第三方库须选 ESM 版本并避免 window/document 全局依赖;注意异步数据加载、样式隔离及生命周期非线性特性。
HTML 文件怎么在 Observable 运行起来
observable notebook 本身不支持直接拖入或加载本地 index.html 运行——它不是浏览器标签页,也不是本地服务器。你看到的 html 内容,必须“活”在 notebook 的 cell 里,且由 observable 的运行时解析执行。
常见错误现象:document.getElementById 返回 null、canvas 不渲染、第三方库(如 D3、Chart.js)报 self is not defined 或 window is not defined。
- Observable 没有全局
window或document对象,只有每个 cell 独立的DOM上下文 - 不能写
<script src="..."></script>,也不能用fetch('./data.json')加载同目录文件(没同源服务) - 所有 HTML 字符串需通过
html函数注入,否则只是纯文本
用 html 函数嵌入可交互的 HTML 片段
html 是 Observable 提供的核心函数,作用是把字符串安全转成可执行的 DOM 节点,并自动处理事件绑定和响应式更新。它不是模板引擎,不支持插值语法(如 ${x}),但支持内联 JS 表达式(用反引号包裹)。
使用场景:嵌入带 input、button、canvas 或简单 SVG 的可视化片段;复用已有的 HTML/CSS/JS 小模块。
示例(正确写法):
立即学习“前端免费学习笔记(深入)”;
html`<div>
<h3>当前值:</h3>
<p>${value}</p>
<button onclick="viewof value.value++">+1</button>
</div>`
-
value必须是 notebook 中定义的响应式变量(如value = Mutable(0)) - 内联 JS 中不能用
var/let声明变量,会报错;只能调用已有变量或函数 - 避免写
document.querySelector—— 用html创建的节点可通过node引用(见下一条)
如何让第三方 JS 库(如 Plotly、Leaflet)在 Observable 中跑起来
Observable 支持直接 import CDN 模块(ESM 格式),但很多老库(尤其依赖 window 全局对象的)会挂掉。关键不是“能不能引入”,而是“能不能在无 window 环境里初始化”。
常见错误现象:Plotly.newPlot is not a function、Leaflet is not defined、self is not defined(尤其 Webpack 打包库)。
- 优先选 Observable 官方封装过的库,比如
Plot(内置)、Inputs、Generators,它们天然适配 - 若必须用原生库,用
import从 esm.sh 或 skypack 引入 ESM 版本,例如:plotly = await import('https://esm.sh/plotly.js@2.29.0/dist/plotly-basic.min.js') - Canvas/WebGL 类库(如 Three.js)要手动传入
html`<canvas></canvas>`创建的节点,不能靠document.createElement - 避免
eval、Function构造器、with—— Observable 运行时禁用这些
为什么你的 HTML 可视化“动不了”?三个最常漏掉的点
不是代码写错了,而是 Observable 的执行模型和浏览器开发习惯差异太大。最容易卡住的地方就这三个:
-
html返回的是 DOM 节点,不是字符串 —— 如果你把它当字符串拼接(比如html`...` + html`...`),结果是[object HTMLElement][object HTMLElement],页面空白 - 异步初始化失败:比如
d3.json('/data.csv')会跨域失败,必须改用FileAttachment('data.csv').csv()或 Observable 内置数据源 - CSS 不生效:Observable 默认隔离样式,
<style>标签只对当前 cell 生效,且不支持@import;建议用内联style="..."或提前定义好 CSS 变量
复杂点在于:HTML 和 JS 的生命周期不是线性的,而 Observable 是响应式图谱驱动的。一个 canvas 渲染逻辑,可能被多次重入、中断、缓存——别假设“执行一次就完事”。











