Взаимодействие с платформой
ClojureScript компилируется в JavaScript и выполняется в браузере. Это означает, что либо стандартная библиотека языка должна иметь все средства для взаимодействия с браузером, либо язык должен предоставлять удобные средства для взаимодействия со средой исполнения JavaScript. Язык Clojure в целом следует второму пути и ClojureScript в частности позволяет вашему коду общаться с браузером посредством уже имеющегося JavaScript API.
Теперь, когда у вас уже есть настроенный проект, можно начать применять ClJS на практике. Реализуем приложение, которое бы при загрузке страницы модифицировало содержимое оной. В index.html
уже имеется тег <div id="root">
, его содержимое мы и будем менять. В файле src/main/com/frontend/app.cljs
(в ближайшее время весь код будет относиться к этому файлу) опишите функцию следующего вида:
(defn update []
(-> (.querySelector js/document "#root")
.-innerHTML
(set! "<h1>Hello World!</h1>")))
Здесь используются сразу три вида взаимодействия с JavaScript objects:
(.querySelector js/document "#root")
— это вызов методаquerySelector
применительно к объектуdocument
со строкой"#root"
в качестве аргумента. Такой вызов в JavaScript выглядел бы как строчкаdocument.querySelector("#root")
.(.-innerHTML node)
— обращение к атрибуту объекта, эквивалентное выражениюnode.innerHTML
в JS.(set! value attribute)
— присвоение нового значения атрибуту объекта. В JS это выглядело бы какobject.attribute = value
.
В примере выше обращение к полю не обёрнуто в скобки, поскольку макрос
->
позволяет опускать оные, если на текущем шаге конвейера нужно применить функцию к одному лишь передаваемому по конвееру аргументу. С тем же успехом можно было написать(-> .. (.-innerHTML) ..)
, но макрос->
позволяет слегка сэкономить на скобках. И возможно такое упрощение потому, что обращение к атрибуту — тоже функция. Сам же макрос->
ничего не знает об объектах и атрибутах!
Теперь, когда у вас есть функция update
, её можно вызвать из "точки входа в программу" — из функции init
:
(defn init []
(update))
Попробуйте открыть страницу при запущенном dev server, вы должны увидеть вставленный в тело страницы тег h1
с текстом приветствия.
Вот ещё несколько примеров использования JS interoperability:
(defn log-some-date []
(let [date (js/Date. 1999 12 31)] ;; создание объекта
(.log js/console (.toISOString date)))) ;; вызовы методов
Здесь (js/Date. ...)
, это аналог создания нового объекта типа Date
. В JavaScript вы бы написали new Date(...)
. Заметьте: точка в конце имени типа означает, что вы вызываете конструктор данного типа, без точки вы бы получили доступ к самому классу js/Date
, который не может быть вызван как функция сам по себе.