同步发在利用 Rails 7 新搭的 blog http://blog.3qruok.com/posts/7
=======
最近在写 blog 和写 pushconfig 这个项目的时候,发现了原来排斥使用的 view_component 其实还是不错的
view_component 是 github 推出的一个 view 级别的抽象组件。
对我来说,view_component 最大的好处是帮我隔离了 view 的复杂,将 rails 原来的 view 的各种魔法都隔离的出来,所有的参数,甚至包括 current_user 这种变量。在我的使用中,但凡于 view_component 相关的对象,都会作为 view_component 的 initialize 参数传入进去。通过这样的方式,我可以控制 view_compnent 组件的复杂性。另外一个不错的内容来自于测试,我可以不用依赖比较麻烦的用户登录来渲染整个页面,之后再测试这整个页面的局部,而是直接将变量传进去,并且只渲染 view_component 这个对象本身生成的 html,从而进行测试。
当然 view_component 的介绍里,他的渲染还比 partial 的渲染快很多,但这对于我来说,其实影响并没有那么大。
当然 view_component 在我的使用中也遇到了两个地方不太好:
目前我使用的是 view_component 默认推荐的目录结构,这家伙会把 view 文件和 init 文件放在同一个目录下,这样会造成 components 文件夹的文件比较多。看起来会比较混乱
另外一个比较尴尬的问题是 tubor stream 在 model 里直接推送 view_component 需要特殊的技巧,因为 view_component 这家伙在渲染的时候是需要 view_context 的,而这个东西是在 controller 的对象里才有的,而如果是在 model 里,这里默认情况下是没有 view_context 的,我们无法使用类似 MessageComponent.new(message: message).render_in(view_context) 的语法的,那么怎么处理这个问题呢? 参考 https://github.com/github/view_component/issues/1106 给出的解决方案是
broadcast_append_to( 'posts', html: PostComponent.new(post: self).render_in(ActionController::Base.new.view_context) )
这个我自己没试,只是贴在这里了
另外关于 view_component 关于 form_for form_with 的兼容性问题,其实我没有太在官网 known issues 上看懂,回头弄明白了再补充下吧