JSX 的解析
简单看了下生成的 bundler.js:
1 | value: function render() { |
解析 jsx 的过程,是通过 babel-plugin-transform-omi-jsx(基于 babel-helper-builder-react-jsx)和 babel-plugin-transform-omi-display-name。
1 | // babel-plugin-transform-omi-jsx |
jsx 最终被解析成如下:
1 | Omi.x( |
其中 tagName 有三种可能:
- 普通的 html 标签
- 通过 Omi.tag(‘component-a’, ComponentA),注册的 tagName
- Component 实例
Omi.x 执行生成虚拟 dom,结构如下:
1 | // VNode |
另外需要注意的一点是,如果 props 设置了 children,会 push 到 VNode 的 children 里去。
组件生命周期
初次渲染:install 流程
render 过程
1. render 的一些配置
_omi_increment: 指定是否增量更新,如果设置为 true,每次更新的时候会增加。
store: 设置所有组件共享的$store。
ssr:
render 流程,使用前面生成的虚拟 DOM,进行标准化后,生成实际的 dom 节点。
2. 标准化虚拟 DOM
// TODO
3. ref 引用处理
如果设置了属性 ref,在 Component 实例,会存储一个键为属性名,值为 DOM 节点的 refs 对象
4. 执行插件
执行插件的方法
插件机制
Omi 的插件,存储在 Omi.plugins。在 reader 的时候,会获取到设置 plugin 属性的 DOM 节点,并执行对应的插件方法。
注册插件方法如下:
1 | Omi.extendPlugin('omi-plugin', function (dom, instance) { |
scope css
比较关键的两个属性
__st_[x]
: 对应的是组件样式的作用域__s_[x]
: 对应的是组件实例的 id
同一个组件,实例化多次,组件作用域 id 一致,但是组件 id 不一致
其中,核心的正则表达式:new RegExp('([^\r\n,{}:]+)(:[^\r\n,{}]+)?(,(?=[^{}]*{)|\s*{)', 'g')
源代码中有相关注释
对应的分组匹配:(.classname)(:pesudo)( {)
解析规则结果如下:
1 | .test { |
确保当前元素和当前元素的子节点能够匹配样式。
生成后在 head 添加 style 标签,存放样式数据。
一些疑问
每个元素要不要都设置__st_[x]
和__s_[x]
,感觉只有组件的根节点需要设置。
style 的 id 要和__st_[x]
匹配好点,目前使用的是__s_[x]
。