gem 的问题

Tags
webappfrontendgem
Created
Jul 17, 2019 11:48 AM

https://www.mindmeister.com/app/map/3412316197

  • SSR // 依赖 html 函数,可以先 Prerender

shadow 和 light 代码的差异:

  • slot // 另外提供一个非响应式如 headerSlot 属性
    • shadow 的样式穿透到 light dom 里面 // shadow dom 使用动态类名
  • css 选择器 // 使用 `&`,除非 `:host(xxx)`
  • dom mutation observe

模版代码多,查看其他框架

// 自动导入

执行顺序,父 -> 子,但是 mounted 是子 -> 父,只有子孙元素准备好了,父元素才叫准备好

// 和 React/DOM API 保持一致

如何避免自定义元素属性被未来 HTML 标准属性冲突?

// 使用命名空间,全局共享配置

// 不能在构造函数中设置 attribute // createElement 会报错,因为在未升级时将读不到

// 静态 attribute 会被构造函数中的初始化覆盖 // 构造函数传递了参数才执行

不能写全局样式(比如 ::selection ) // Chrome 支持,包括 ::target-text/::highlight 也支持

// 需要使用 adoptedStyle 应用共享样式;或者在 GemElement 上加静态属性 v2 不再继承

// DuoyunOptionsElement.adoptedStyleSheets 修改已存在组件样式

HTML 模版中的 style 元素不能覆盖 adoptedStyle 的样式

// 必须使用 important 或者 @layer(在 constructor stylesheet 中用)

不方便使用锚点定位 // Embed GitHubEmbed GitHub

有一些非继承样式不能通过 inherit 应用到插槽中

// slot 也需要 inherit

自定元素 upgrade 时 constructor 中需要考虑已有 property // 例如 gem-route

不能树抖 // 元素定义都是副作用行为,手动按需导入或者使用构建插件;使用 import defer

模版不能写动态标签 // 使用 jsx ?

不能扩展自内置(a, dialog)元素 // 类型不知道写,其实用 is 也比较麻烦

state 的深度数据更改时并不一定能触发 UI 更新

// 整条数据链更新

// 扁平 state

// 所有组件绑定 state // 经过一些操作变成了 react 的更新方式

元素依赖不能很好的具备 IDE 支持 // 需要手动添加和删除依赖

元素名称更新不具备 IDE 支持 // 需要使用替换,受限于模版的写法

依赖运行时,一些计算(比如模版解析)造成不必要的性能消耗

没有冒泡的 “mouseover” 事件了 // 因为在一个元素内部

ParentNode.append 等方法操作已挂载的 gem 元素时,不会触发 unmounted, mounted 回调(会触发 disconnectCallback/connectCallback)

// 跨文档 append 时事件监听器还是能正常工作

ts 中用字段来标记的 attr 也会被当成 prop

// 自定义attr/prop 全部用 prop 的写法来写

用模版字符串手写 HTML 时(raw) attribute 的值必须写引号,不然值为空字符时解析不符合预期

同样具有 OOP 的问题:https://zhuanlan.zhihu.com/p/46207044

  • 基类方法被覆盖 // 使用私有字段
  • 方法 this 绑定 // 使用类字段
  • 基类,子类方法调用凌乱 // 例如增强 mount 回调就很麻烦、使用静态方法还是函数?使用方法还是字段?

同一功能的代码写在不同的地方(生命周期中)// effect 方法类似 react effect hooks

effect 的依赖写法复杂(返回数组的函数),装饰器依赖访问 this 也麻烦

lit-html 语法复杂:if 块、list

gem 元素内不要直接修改公开的 attr/prop(有可能造成更新死循环),但是 constructor,字段上可以这么做,当然 css state 往往需要内部修改

// gem 初始化 history 的 replace 将导致 electron webContents 崩溃

DOM 有 attr 和 prop 之分,attr 表示语义,prop 表示 js 对象属性,DOM 的有些 attr 和 prop 是同步的,有些不是

// string|boolean|number 类型的属性用 attr,否则使用 prop

为了统一开发体验,最佳实践是所有 attr 能像 prop 一样访问和设置。在 gem 中是在 constructor 中读取 observedAttributes 列表定义成访问器属性来实现的。问题:

  • 并不是所有 attr 都能直接读取, 没有 observedAttributes 的 attr 只能 get/setAttribute
  • attr 和 prop 名字重叠
  • attr 要支持 lit-plugin 需要再写一份标记注释
  • observed* 似乎有些多余, 没有写在 observedAttributes 中时直接访问得到的是 prop,且难以排查
  • observedAttributes 合并原型链上的值

解决方案:使用装饰器。新问题:

  • 装饰器字段通常都有默认值,但是 prop 装饰器没有 // 因为类型不确定
  • v1 使用 TS 装饰器时不能使用 ES2022 私有字段 // 必须关闭 `useDefineForClassFields`
  • 使用 ES 装饰器时必须插入文档才能正确读取属性 // 字段在插入文档时被隐式删除,类似
  • 使用 ES 装饰器时在 DevTools 中修改元素的 Attribute 不会更新元素 // 使用 WebConsole 修改

// 除了 property,其他元素内部装饰器都将描述符转为烤串格式

为啥没有 Svelte 组件?{...$$props} 不能动态绑定事件 // v5 好像可以了

SuperMade with Super