Reagent 组件创建指南:从基础到高级
前言
Reagent 是一个基于 React 的 ClojureScript 库,用于构建用户界面。在 Reagent 中,组件(component)是构建应用的基本单元。本文将深入讲解 Reagent 中创建组件的三种方式,帮助开发者理解其核心概念和工作原理。
组件核心:渲染函数
每个 Reagent 组件的核心都是一个渲染函数。这个函数:
- 接收数据作为参数
- 返回 Hiccup 格式的 HTML 表示
- 通常是纯函数(相同输入产生相同输出)
(defn greet
[name] ;; 输入参数
[:div "Hello " name]) ;; 返回 Hiccup 格式的 HTML
Hiccup 是 ClojureScript 中表示 HTML 的一种简洁方式,使用向量表示元素,映射表示属性。
组件创建的三种形式
Reagent 提供了三种创建组件的方式,复杂度递增:
形式1:简单函数(Form-1)
最简单的组件形式,直接定义一个渲染函数:
(defn simple-component
[message]
[:div.message message])
特点:
- 纯函数形式
- 无状态
- 适用于约40%的使用场景
- 必须返回单个根元素(或使用片段)
常见错误:
;; 错误:返回多个同级元素
(defn wrong-component
[]
[[:div "A"] [:div "B"]])
;; 正确:使用父元素包裹
(defn right-component
[]
[:div
[:div "A"]
[:div "B"]])
形式2:返回渲染函数的函数(Form-2)
当组件需要本地状态或初始化逻辑时使用:
(defn counter-component []
(let [count (reagent/atom 0)] ;; 本地状态
(fn [] ;; 内部渲染函数
[:div
"Count: " @count
[:button {:on-click #(swap! count inc)} "Increment"]])))
特点:
- 外层函数执行一次(初始化)
- 内层渲染函数执行多次
- 适用于约50%的使用场景
- 可以访问闭包中的状态
常见错误:
;; 错误:忘记在内层函数重复参数
(defn outer [a b]
(fn [] ;; 缺少参数
[:div (str a b)]))
;; 正确:内层函数重复参数
(defn outer [a b]
(fn [a b] ;; 正确声明参数
[:div (str a b)]))
形式3:带生命周期方法的类(Form-3)
最复杂的形式,提供完整的生命周期控制:
(defn timer-with-lifecycle []
(let [seconds (reagent/atom 0)
interval (atom nil)]
(reagent/create-class
{:display-name "timer-component"
:component-did-mount
(fn [this]
(reset! interval (js/setInterval #(swap! seconds inc) 1000)))
:component-will-unmount
(fn [this]
(js/clearInterval @interval))
:reagent-render ;; 注意不是 :render
(fn []
[:div "Seconds: " @seconds])})))
特点:
- 完全控制组件生命周期
- 需要手动管理资源
- 适用于不到1%的特殊场景
- 必须使用
:reagent-render
而非:render
常见错误:
- 错误使用
:render
而非:reagent-render
- 过早优化
component-should-update
- 忘记添加
:display-name
导致调试困难
进阶技巧
with-let 宏
with-let
提供了更简洁的方式来处理资源管理:
(defn mouse-position []
(reagent/with-let [pos (reagent/atom nil)
handler #(reset! pos [(.-pageX %) (.-pageY %)])
_ (.addEventListener js/document "mousemove" handler)]
[:div "Position: " (pr-str @pos)]
(finally
(.removeEventListener js/document "mousemove" handler))))
优势:
- 自动资源清理
- 减少 Form-2 的使用
- 更简洁的代码结构
组件工作原理
- 当 Reagent 遇到函数作为 Hiccup 的第一个元素时,会将其视为渲染函数
- Reagent 将渲染函数与默认生命周期方法合并形成 React 组件
- 对于 Form-2:
- 外层函数只调用一次(初始化)
- 返回的内层函数成为实际渲染函数
- 内层函数会多次调用
总结
- Form-1:简单无状态组件
- Form-2:带本地状态的组件
- Form-3:需要精细生命周期控制的组件
理解这三种形式及其适用场景,能够帮助开发者编写更高效、更易维护的 Reagent 应用。大多数情况下,Form-1 和 Form-2 已经足够应对日常开发需求,而 Form-3 则留给那些需要特殊处理的边界情况。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考