乐趣区

关于compiler:webcompilermvvm-的实现思路

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

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

code

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

<script>
    let a = 10;
    function handler(){a++;}
    let str = "hello";
</script>
<button @click="handler()">
    click me {{a}}
</button>

其对应的编译后代码能够是这个样子

// 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 函数列表,顺次进行调用。

总结

编译的过程就是植入 watch,trigger 和转换的过程 如 handler 里对 a 进行赋值变更 那么有两种形式实现 一种是对 ++ 或者说 = 进行重写 拿到左值 进行 赋值与 trigger 操作 , 另一种是剖析有无依赖内部的顶层变量 而后进行代码植入,转换则是把植入完后的代码进行 二次加工 如 button html 标签 转换成 js dom 的模式。

退出移动版