swap! 是什么意思? with assoc 和 (-> % .-target .-value) 语法在 ClojureScript 中是什么意思?

What does swap! with assoc and (-> % .-target .-value) syntax mean in ClojureScript?

我正在尝试理解 Web Development With Clojure 一书中的这段代码。关于 clojure 脚本:

(defn message-form [] 
  (let [fields (atom {})] 
   (fn [] 
    [:div.content
     [:div.form-group 
      [:p "Name:"
       [:input.form-control 
        {:type :text 
         :name :name 
         :on-change #(swap! fields assoc :name (-> % .-target .-value)) 
         :value (:name @fields)}]]] 
    [:p "Message:"
     [:textarea.form-control 
      {:rows 4 
       :cols 50 
       :name :message 
       :on-change #(swap! fields assoc :message (-> % .-target .-value))} 
      (:message @fields)]] 
    [:input.btn.btn-primary {:type :submit :value "comment"}]]))) 

谁能解释一下这部分:

#(swap! fields assoc :name (-> % .-target .-value)

尤其是这个: ...(-> % .-目标 .-值)

#() 是一个 reader macro。它是匿名函数 (fn [args] ...) 的缩写形式,其中 % 是该函数的第一个参数。

在这种特殊情况下 #(swap! fields assoc :name (-> % .-target .-value) 等于 (fn [X] (swap! fields assoc :name (-> X .-target .-value))

-> 是一个 threading macro(-> X .-target .-value) 等同于 (.-value (.-target X))

(.-target X)表示获取对象X.

的属性target

所以你定义了一个接收单个参数的匿名函数。此函数将更改 fields 原子,以便其键 :name 将设置为 属性 [=19 中对象的 属性 value 的值=] 对象 X.

在你的问题中,swap! 接受一个原子,一个函数 (assoc) 更新原子存储 后续参数的值到功能。

这是实现相同结果的另一种方法:

#(swap! fields (fn [prev] (assoc prev :name (-> % .-target .-value)))

看到 :name(-> % .-target .-value) 将是您问题的 swap! 调用中的两个后续参数,其中 apply 在内部用于将这些参数应用于assoc。这里只有一个更新函数 - 没有后续参数。

如您所见,prev 是我们要更改的原子的内部值,swap! 只需要一个 'updating' 函数,returns要存储的 swap! 的下一个值。

(-> % .-target .-value) 而言,请记住您已经在 reader 宏中,因此 % 是它的第一个参数。 -> 线程宏线程进入每个后续函数的第一个参数,因此 % 被提供给 .-target,然后其结果被提供给 .-value,给我们: (.-value (.-target %)).

:name 存储在字段中的映射被设置为所提供的某个值的目标值!

稍微宽一点 % 是一个 JavaScript 事件,每当文本输入字段更改时都会提供 - 基本上每当用户键入文本时。您很少需要整个事件 - 只需要输入的文本,这是获取事件目标(而不是源)然后该目标值的地方。 .- 部分意味着您得到的是 JavaScript 属性 - 这是 'interop',与正常的 ClojureScript 语法相反。

[:input {:on-change #(swap! fields assoc :name (-> % .-target .-value)}]

这定义了一个输入和一个函数,每次用户更改输入字段时都会调用该函数,即。 e.输入它。该函数将以更改事件对象作为参数调用,然后绑定到 %。事件目标是输入字段 DOM 元素,其文本内容为 value。然后该函数更改 fields 以包含 :name 该内容。

#(…)% 属于同一类:#(…) 创建一个匿名函数,% 是其参数的名称。

-> 是一个宏,它将通常的 lispy 形式的前缀组合反转为类似于后缀组合的东西或 "piping":(-> % .-target .-value) 扩展为 (.-value (.-target %))

.-value 符号是 ClojureScript 中的 JavaScript 互操作。表示访问JavaScript对象的"value"字段; ClojureScript 中的 (.-value foo) 与 JavaScript 中的 foo.valuefoo["value"] 基本相同。