JavaScript 小谈 Stimulus.js 和 react_component 的联合使用

jicheng1014 · 2020年12月21日 · 最后由 line933200 回复于 2021年01月09日 · 1467 次阅读
本帖已被管理员设置为精华贴

react 是一个处理复杂数据导致 UI 变化的一个好工具,但是工具虽好,但是不能看啥都是钉子。在我们常见的操作中,大多数情况交互并不是很重,这种情况下,用传统的 rails view 来生成界面,实际上是个不错的选择。

平时在处理 form 的时候,我一般不会完全用 react 处理表单,之后 提交一个 formdata, 而是选择靠 rails 来生成 form 进行快速提交,这样就不需要又写界面又写 rails api。

今天遇到的情况比较有典型性:

大概是表单里有一个字段存一个 json,这个 json 本身会有复杂的配置,有很多操作都影响着这个 json 的生成,

因为操作比较多,于是这块当然用 react_component 比较好实现,但是个 json 本身是由表单最外层的一个 category 选择框来确定不同的模型的,同时这两个界面模块中间还隔了一些表单的其他内容,这些内容因为业务原因,必须放在 category 和 react 组件的中间

平常有两种方案能解决这个问题:

  • 将整个 form 都放在 react_component 里:

这种方式其实就是走 rails api 的方式了,但是由于这里我已经用 rails view 实现了其他表单属性的界面和校验,再改一次很麻烦

  • 在 下拉框 select change 中发起一个 srj, 返回 js 将原来的 react_component 删掉,再重新渲染一个新的 react_component

这种方式处理起来比较简单,即将 react_component 外层用 一个 div 包起来,之后 change 回来的 js 先清空他,在 render escape 一个 react_component,这种方式倒是比较简单,同时也不改其他的代码,只是要多调用一下服务端,感觉有点没必要。

最后决定不如用 stimulusjs 来控制 react_component 的 props 好了,这样就可以直接通过 js 而不过后端来控制显示了。

这是相关的代码逻辑

import {Controller} from 'stimulus'

export default class extends Controller {
  static targets = ["dropdown", "metaArea"]

  connect(){
    this.changeMetaAreaAttribute();
  }

  readDropdownValue(){
    return this.dropdownTarget.value
  }

  needShowMetaArea(){
    return this.dropdownTarget.value === 'Conversations::QuestionConversation'
  }

  changeMetaAreaAttribute(){
    // 注意此处, 因为 react_component 实际存储 props 本身是string 型, 所以需要转化一下
    let json = JSON.parse(this.metaAreaTarget.dataset.reactProps)
    json["category"] = this.readDropdownValue()
    this.metaAreaTarget.dataset.reactProps = JSON.stringify(json) 
    ReactRailsUJS.mountComponents() // 注意此处, 再修改完毕之后, 需要让 React Component 重新渲染一下
  }

}

之后此处的 react_component,需要多传一个参数,让 stimulusjs 能够指定到 target

<%= react_component "AdminMetaEditors", {init_meta: chat_task.meta, category: chat_task.category}, {data: {chat_workflow_category_target: 'metaArea'}} %>

这样就能够 react_component 和 stimulus 混用了

总结:

  1. 在前端上没必要二者选一,成年人向来是全都要。简单逻辑上 stimulus, 复杂逻辑上 react 是一个不错的选择。
  2. react component 和 stimulus 逻辑上是可以交互的,只需要让 stimulus 改变 react_component 的 props,再通知 react_component 渲染即可
jasl 将本帖设为了精华贴。 12月23日 19:38
需要 登录 后方可回复, 如果你还没有账号请 注册新账号