元素.
. 我将在这篇文章的后面更详细地讨论这个问题!
这是ClojureScript中反应组件的最基本形式. 就是这样,一个关键字,一个字符串,还有一大堆列表.
相关:
< / div >
构建块
在本ClojureScript教程中, 我将尽量不深入挖掘Clojure(脚本)的伟大之处(这是很多东西), 但我离题了). 尽管如此, 涵盖一些基本概念将是有用的,这样就有可能掌握我们在这里可以做的事情的广度.
对于那些有经验的Clojuristas和Lispians,请随意跳转到下一节!
首先我需要介绍三个主要概念:
关键字
Clojure(脚本)有一个叫做关键字的概念. 它位于常量字符串(比如Java)和键之间. 他们是 求值为自身的符号标识符.
例如,关键字 :猫
总是指 :猫
再也没有别的了. 就像在Java中你可能会说:
MY_KEY = " MY_KEY ";
// ...
关联.把(MY_KEY,东西);
// ...
关联.得到(MY_KEY);
在Clojure中,你只需要:
(关联my-map:my-key thing)
(my-map :my-key) ; equivalent to (:my-key my-map) ...又好又灵活!
还要注意: 在Clojure中,映射既是键到值的集合,就像Java一样 HashMap
)和访问其内容的Functional. 整洁的!
列表
Clojure(脚本)是一种Lisp方言,这意味着它非常强调列表. 正如我之前提到的,有两件事需要注意:
-
[]
向量和an很像吗 ArrayList
.
-
()
序列是不是很像 LinkedList
.
要在Clojure(脚本)中构建一个列表,你可以这样做:
[1 2 3 4]
“你好”“世界”)
["my" "list" "contains" 10 "things"] ; you can mix and match types
; in Clojure lists!
对于序列,这有点不同:
'(1 2 3 4)
”(“你好”“世界”)
的将 '
在下一节中解释.
Functional
最后是函数. Clojure(脚本)中的函数是一个 序列 是打印出来的 没有前置 '
. 该列表的第一个元素是函数本身,接下来的所有元素都是 参数. 例如:
(+ 1 2 3 4) ; -> 10
(str "hello" " " "world") ; -> "hello world"
(println“嗨!") ; prints "hi!对着控制台说
(run-my-function) ; runs the function named `run-my-function`
这种行为的一个必然结果是,您可以构建一个函数的定义,而无需实际执行它! 当程序被求值时,只会执行一个“裸”序列.
(+ 1 1) ; -> 2
'(+ 1 1); -> a list of a function and two numbers
这将在稍后变得相关!
函数可以用几种方式定义:
; A normal function definition, assigning the function
; to the symbol `my-function`
(defn函数
(__arg1最长)
(+ arg1 arg2))
; An anonymous function that does the same thing as the above
(fn (__arg1最长) (+ arg1 arg2))
; Another, 更多的 简洁的 variation of the above
#(+ %1 %2)
更仔细的检查
现在我们已经了解了基本知识, 让我们深入一点细节,看看这里发生了什么.
在ClojureScript中,反应通常使用一个库来完成 试剂. 试剂使用Hiccup及其语法来表示HTML. 从 Hiccup回购维基:
“Hiccup将Clojure数据结构变成这样:”
[:a {:href "http://github ..com GitHub“}]
"变成像这样的HTML字符串:"
GitHub
简单地说, 第一个元素 列表的部分成为HTML元素类型,其余部分成为该元素的内容. 您还可以选择提供一个属性映射,然后将其附加到该元素.
元素可以简单地嵌套在父元素的列表中,从而相互嵌套! 这是一个最容易理解的例子:
[: div
[:h1 "这是标题"]
[:p "下一个元素是1 + 1"]
[:p (+ 1 1)]]
请注意,我们可以将任何旧函数或通用Clojure语法放入结构中,而不必显式声明嵌入方法. 毕竟,这只是一个列表!
更好的是,这个在运行时的值是多少?
[: div
[:h1 "这是标题"]
[:p "下一个元素是1 + 1"]
[:p 2]]
一个关键词和内容的列表! 没有有趣的类型,没有神奇的隐藏方法. 这只是一份简单的清单. 你可以随心所欲地拼接和摆弄这个列表——你看到的就是你得到的.
Hiccup做布局,试剂做逻辑和事件处理, 我们最终得到了一个Functional齐全的反应环境.
一个更复杂的例子
好了,让我们用一些成分把这些联系起来. 反应(和试剂)的神奇之处在于,您可以将视图和布局逻辑划分为模块, 然后您可以在整个应用程序中重用它们.
假设我们创建了一个简单的组件,它显示一个按钮和一些简单的逻辑:
; 小部件.cljs
(defn组件
(有礼貌的?]
[: div
[:p (str "礼貌时请勿按按钮"? ”,请."))]
[:input {:输入“按钮”
:重视“推我”
:on-click #(js/alert) "What did I told you .?")}]])
关于命名的快速说明:Clojure中的模块通常是命名空间的,所以 小部件.cljs
可以在名称空间下导入 小部件
. 这意味着顶层 组件
函数将被访问 部件/组件
. 我喜欢每个模块只有一个顶层组件, 但这是一种风格偏好—您可能更喜欢这样命名组件函数 有礼貌的-组件
or 小部件组件
.
这个简单的组件为我们提供了一个可选的礼貌小部件. (当有礼貌? ”,请.")
计算结果为 ”,请."
当 有礼貌的? = = 真正的
和 零
当它是 假
.
现在我们把它嵌入到 应用程序.cljs
:
(defn应用
[]
[: div
[:h1 "欢迎来到我的应用程序"]
[小部件/组件正确]])
在这里,我们通过将小部件作为列表的第一项调用来将其嵌入到应用程序组件中——就像HTML关键字一样! 然后,我们可以将任何子元素或参数作为同一列表的其他元素提供给组件. 这里我们简单地通过 真正的
,所以在我们的小部件中 有礼貌的? = = 真正的
,因此我们得到了礼貌的版本.
如果我们现在评估我们的应用函数,我们将得到以下结果:
[: div
[:h1 "欢迎来到我的应用程序"]
[部件/组件 真正的]] ; <- 部件/组件 would look 更多的 like a
; function reference, but I have kept it
; clean for legibility.
请注意 部件/组件
没有被评估过! (见 职能组 如果你感到困惑.)
DOM树中的组件只有在更新后才会被评估(并在幕后转换为真正的反应对象), 它能让事情保持漂亮和简洁,并减少你在任何时候都必须处理的复杂性.
有关这一主题的更多细节可供感兴趣的人查阅 在试剂文档中.
列表一直向下
此外, 注意DOM只是一个列表的列表, 组件就是返回列表的列表的函数. 为什么这对学习ClojureScript如此重要?
因为 你可以对函数或列表做的任何事情,你也可以对组件做.
从这里开始,通过使用ClojureScript等Lisp方言可以获得复合回报:组件和HTML元素成为可以像操作任何其他普通数据一样操作的一等对象! 让我再说一遍:
组件和HTML元素是Clojure语言中支持的第一类对象!
没错,你没听错. 这几乎就像lisp被设计用来处理列表一样(提示:它们确实是).)
这包括:
(def["绿色" "鸡蛋"和"火腿"])
(defn li-shout
[x]
[:li (string/大写x)]
(concat [:ol] (map li-shout words)
; becomes
[:ol
(李:“绿色”)
(李:“鸡蛋”)
[:李”和“)
[李:“火腿”]]
; in 小部件.cljs
(defn greeting-组件
(名字)
[: div
[:p (str "Hiya " name ")!")]])
; ...
(def shouty-greeting-组件
#(小部件/greeting-组件 (string/大写%)))
(defn应用
[]
[: div
[:h1 "My App"]
[shouty-greeting-组件 "Luke"]]) ; <- will show Hiya LUKE!
(def default-btn-attrs
{:输入“按钮”
:值“我是一个按钮”
:类“my-button-class”})
(defn two-button-组件
[]
[: div
[:input (assoc default-btn-attrs .)
:on-click #(println "I do one thing"))]
[:input (assoc default-btn-attrs .)
:on-click #(println "I do a different thing"))]])
处理普通的旧数据类型(如列表和映射)要比处理类简单得多, 从长远来看,最终会变得更强大!
一种模式出现
好吧,让我们回顾一下. 到目前为止,我们的ClojureScript教程展示了什么?
- 一切都被简化为最简单的Functional——元素只是列表, 组件就是返回元素的函数.
- 因为组件和元素是一级对象,所以我们可以这样写 更多的 与 少.
这两点非常适合Clojure和函数式编程的精神——代码是 data 被操纵,复杂性是通过连接不太复杂的部分而建立起来的. 我们将程序(本例中的网页)表示为数据(列表), Functional, 并保持这种状态,直到最后一刻,当试剂接管并将其转化为反应代码. 这使得我们的代码可重用, 最重要的是,非常容易阅读和理解,几乎没有魔法.
越来越时尚
现在我们知道了如何制作具有一些基本Functional的应用程序, 所以让我们继续讨论如何让它看起来更好. 有几种方法可以解决这个问题, 最简单的是使用样式表并在组件中引用它们的类:
.我班{
颜色:红色;
}
[: div {:class "my-class"}
“你好,世界!"]
正如您所期望的那样,它将向我们呈现一个美丽的红色“Hello, world”!“文本.
然而, 为什么要在组件中配置视图和逻辑代码时遇到这么多麻烦呢, 但是,然后将样式分离到样式表中—现在不仅要在两个不同的地方查找, 但你也在处理两种不同的语言!
为什么不把我们的CSS写成 组件中的代码 (在这里看到一个主题?). 这将给我们带来很多好处:
- 所有定义组件的东西都在同一个地方.
- 通过巧妙的生成,可以保证类名的唯一性.
- CSS可以是动态的,随着数据的变化而变化.
我个人最喜欢的代码内css风格是与 Clojure样式表(cljss). 嵌入的CSS如下所示:
;; -- STYLES ------------------------------------------------------------
(defstyles 组件-style []
{:颜色“红色”
宽度:“100%”})
;; -- VIEW --------------------------------------------------------------
(defn组件
[]
[: div {:class (组件 style)}]
“你好,世界!"])
defstyles
创建一个函数,它将为我们生成一个唯一的类名(这对任何导入我们组件的人来说都很好).)
class还可以为您做许多其他的事情(组合样式), 动画, 元素覆盖, 等.),我在这里就不详述了. 我建议你自己去看看!
组装一个ClojureScript应用
最后,需要胶水把所有这些粘在一起. 幸运的是,除了一个项目文件和一个 指数.html
在这里,样板文件是最少的.
你需要:
- 项目定义文件,
项目.clj
. 这是任何Clojure项目的主要内容,它定义了您的依赖项甚至直接从GitHub-和其他构建属性(类似于 构建.gradle
or 包.json
.)
- An
指数.html
作为试剂应用程序的绑定点.
- 一些用于开发环境的设置代码,最后用于启动您的试剂应用程序.
您可以在本ClojureScript教程中找到完整的代码示例 可以在GitHub上找到.
所以这就是它(目前). 希望, 我至少激起了你一点点的好奇心, 无论是检查Lisp方言(Clojure(脚本)或其他),还是尝试制作自己的试剂应用程序! 我保证你不会后悔的.
和我一起跟进这篇文章, 进入一个州的状态管理 圆谎-向ClojureScript中的Redux问好!
< / div >< / div >< / div >< / div >
了解基本知识
反应是前端还是后端?
反应是JavaScript的前端开发框架.
< / div >< / div >
什么是ClojureScript?
ClojureScript是一个针对JavaScript的Clojure编译器. 它发出的JavaScript代码与Google Closure优化编译器的高级编译模式兼容. 它继承了Clojure的大部分属性, 一种支持交互式开发的动态编程语言.
< / div >< / div >
Lisp是用什么写的?
Lisp是一组具有共同特征的语言(如Clojure)的名称, Common Lisp, 计划等.),所以“Lisp”本身并不是真正写出来的. (这就像问“蛋糕的原料是什么?“大多数蛋糕都遵循类似的主题,但会有不同的成分.)
< / div >< / div >
Lisp好吗?
是的! Lisp优先考虑“代码即数据”的原则.这可以从名称本身的派生- list Processor中看出. Lisp方言中的一切都是数据——甚至函数调用也是一个参数列表! Lisp是一种奇妙的编程语言风格——有许多不同的风格可以满足任何需求.
< / div >< / div >
Lisp是函数式编程吗?
Lisp方言通常调用函数式和命令式编程语言的一部分. Clojure和ClojureScript是多范式的——它们严重依赖于函数式编程, 并且允许你在需要的时候分支成命令式. 这可以让你体验到两全其美!
< / div >< / div >
什么是谷歌闭包库?
Google Closure Library是一个广泛且完善的JavaScript跨浏览器库, 包含各种UI工具, DOM操作, 服务器通信, 测试, 等. 它旨在与Google闭包编译器一起使用.
< / div >< / div >
什么是谷歌闭包编译器?
谷歌闭包编译器通过操作将JavaScript编译成“更好的JavaScript”, 优化, 最小化以确保它下载和运行得更快. 此外,它还对代码运行一套检查,以尽量减少运行时出现的问题.
< / div >< / div >< / div >< / div >
标签
< / div >< / div >< / div >< / div >
聘请Toptal这方面的专家.< / div >
现在雇佣< / div >< / div >