web-compiler(mvvm|web-compiler:mvvm 的实现思路)

最近一段时间留意到一个叫Svelte的前端框架,它与Vue 等前端框架的最大不同是采用了编译的方案进行的实现,这是官网的介绍

Svelte 是一种全新的构建用户界面的方法。传统框架如 React 和 Vue 在浏览器中需要做大量的工作,而 Svelte 将这些工作放到构建应用程序的编译阶段来处理。与使用虚拟(virtual)DOM 差异对比不同。Svelte 编写的代码在应用程序的状态更改时就能像做外科手术一样更新 DOM。

code
然后想了一下Svelte 组件 大体思路定义一套dsl,然后通过Svelte编译成js css 代码,html对应的dom通过js生成。
顺着这个思路写了一个最小化的 mvvm 的示例

其对应的编译后代码可以是这个样子
// watcher core function createWatcher(){ let watcher = {}; function watch(key, cb){ if(!watcher[key]){ watcher[key] = []; } watcher[key].push(cb); } function trigger(key){ watcher[key].forEach(cb => cb()); } return { watch, trigger } }

let {watch, trigger} = createWatcher(); let a = 10; function handler(){ a++; // 框架注入trigger trigger('a'); }let btn = document.createElement('button') btn.addEventListener('click', handler) btn.innerHTML = 'Click me'+a; // 框架注入watch watch('a', () => { btn.innerHTML = 'Click me'+a; }) document.body.appendChild(btn)

核心思路是实现一个watcher 观察者,对于script 里被依赖的变量 值发生变更触发trigger, 获取值的地方通过watch注册, 当trigger 'a' 时 获取到观察'a'的callback函数列表 ,依次进行调用。
总结 【web-compiler(mvvm|web-compiler:mvvm 的实现思路)】编译的过程就是植入watch,trigger和转换的过程 如 handler 里对a进行赋值变更 那么有两种方式实现 一种是对 ++ 或者说 = 进行重写 拿到左值 进行 赋值与trigger 操作 , 另一种是分析有无依赖外部的顶层变量 然后进行代码植入, 转换则是把植入完后的代码进行 二次加工 如 button html标签 转换成 js dom的形式。

    推荐阅读