步骤
创建工程
- 准备工作(搭建react-native开发环境搭建开发环境)
- 创建一个rn工程
react-native init trainplatform
- 添加
shadow-cljs
依赖yarn add shadow-cljs
- 手动添加shadow-cljs.end文件
touch shadow-cljs.edn
初始化rn项目
在所建文件夹根目录下执行(默认你已经有一定rn基础,至于rn环境的搭建请阅读此教程)
react-native init trainplatform
进入trainplatform工程下面,运行rn项目
cd trainplatform
react-native run-ios
稍等片刻,不出所料,rn工程已经运行起来了

添加必要的依赖库
还是在trainplatform工程目录下面为rn项目添加react-dom
库。
yarn add react-dom
添加shadow-cljs
开发环境依赖
yarn add shadow-cljs --dev
目前trainplatform
下面的package.json
文件开起来应该是这样的
{
"name": "trainplatform",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
"start": "react-native start",
"test": "jest",
"lint": "eslint ."
},
"dependencies": {
"react": "16.11.0",
"react-dom": "^16.13.1",
"react-native": "0.62.2"
},
"devDependencies": {
"@babel/core": "^7.10.0",
"@babel/runtime": "^7.10.0",
"@react-native-community/eslint-config": "^1.1.0",
"babel-jest": "^26.0.1",
"eslint": "^7.1.0",
"jest": "^26.0.1",
"metro-react-native-babel-preset": "^0.59.0",
"react-test-renderer": "16.11.0",
"shadow-cljs": "^2.9.10"
},
"jest": {
"preset": "react-native"
}
}
修改shadow-cljs.edn 文件
回到工程root目录,即rn-demo
下面,编辑shadow-cljs.edn
文件。
vim shadow-cljs.edn
复制以下内容:
;; shadow-cljs configuration
{:source-paths
["src/dev"
"src/main"
"src/test"]
:dependencies
[[Reagent "0.9.1"]]
:builds
{:app
{:target :react-native
:init-fn rc.app/init
:output-dir "build"
:js-options {:js-package-dirs ["reactnative/node_modules"]}}}}
注意:依赖一定要添加Reagent
。target
就是rn项目创建的项目名字,咱们起的名字就叫reactnative
,当然你也可以起别的喜欢的名字,output-dir
就是指定cljs编译成js之后存放的目录,js-options
指定cljs
引用js
时候的目录。
保存文件,我们进入下一步。
clojurescript编码
创建目录src/main/rc
,并在此目录下新建文件app.cljs
.编辑文件如下:
(ns rc.app
(:require
["create-react-class" :as crc]
["react-native" :as rn]
[reagent.core :as r]))
;; must use defonce and must refresh full app so metro can fill these in
;; at live-reload time `require` does not exist and will cause errors
;; must use path relative to :output-dir
(defn root []
[:> rn/Text {:style {:fontSize 90 :marginTop 100}} "hello world" ])
(defonce root-ref (atom nil))
(defonce root-component-ref (atom nil))
(defn render-root [root]
(let [first-call? (nil? @root-ref)]
(reset! root-ref root)
(if-not first-call?
(when-let [root @root-component-ref]
(.forceUpdate root))
(let [Root
(crc
#js {:componentDidMount
(fn []
(this-as this
(reset! root-component-ref this)))
:componentWillUnmount
(fn []
(reset! root-component-ref nil))
:render
(fn []
(let [body @root-ref]
(if (fn? body)
(body)
body)))})]
(rn/AppRegistry.registerComponent "trainplatform" (fn [] Root))))))
(defn start
{:dev/after-load true}
[]
(render-root (r/as-element [root])))
(defn init []
(start))
让react-native加载cljs编译生成的js代码
至此,我们就差让rn项目加载cljs编译生成的js代码了,回到reactnative目录,打开index.js
,修改为:
///////////////////////////////////////////////////////
// import {AppRegistry} from 'react-native'; //
// import App from './App'; //
// import {name as appName} from './app.json'; //
// //
// AppRegistry.registerComponent(appName, () => App); //
///////////////////////////////////////////////////////
import "./app/index.js";
这样当我们编辑clojurescript代码的时候,rn就会实时reload。最终效果:

网友评论