Взаимодействие с платформой
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, который не может быть вызван как функция сам по себе.