【问题标题】:Figwheel doesn't detect most changes in my codeFigwheel 没有检测到我的代码中的大多数更改
【发布时间】:2018-02-27 10:50:23
【问题描述】:

Figwheel 可以很好地显示下面的代码。但我必须刷新页面才能看到任何更改。 Figwheel 必须改变什么才能显示变化?有没有强制重绘而不丢失应用程序状态的命令?

顺便说一句:Chrome 已禁用缓存true,并且在保存文件时会出现 CLJS 图标

(defn simple-example []
  [ui/mui-theme-provider {:mui-theme (get-mui-theme
                                       {:palette {:text-color (color :blue800)}})}
   [:div
    [ui/app-bar {:title                 "Hi all"
                 :icon-class-name-right "muidocs-icon-navigation-expand-more"}]
    [ui/paper
     [:div
      [ui/tabs
       [ui/tab {:label "Menu" :value "0"}
        [:div "Hello world"]]]]]]]))

(defn ^:export run []
  (render [simple-example]
          (js/document.getElementById "app")))) 

【问题讨论】:

  • 您每次写入后都会弹出“cljs-icon”吗?那么 figwheel 是否没有加载您的更改或更改没有出现效果?

标签: clojure clojurescript figwheel


【解决方案1】:

需要通知 Reagent 状态更改以在屏幕上重新渲染受影响的组件。您的代码还没有任何内部状态可以被观察以确定是否需要重新渲染。

您可以将您的应用状态存储在试剂原子中。当您取消引用试剂组件(在您的情况下为 simple-example 组件)中的试剂原子时,会为状态原子设置一个事件侦听器,以便任何时候它更改组件都会重新呈现。

simple-example的定义之前添加以下内容:

(defonce counter (reagent.core/atom 0))
(swap! counter inc)

这会创建一个名为counter 的状态,如果它还不存在的话。它还会立即增加它,因此任何已注册的组件都将被刷新。

然后在simple-example 的函数体中的任何位置放置一个@counter deref 调用。这样,函数的初始调用就会安装状态变化监听器。

现在,每当您修改代码时,命名空间都会重新加载,因此counter atom 会增加,从而触发组件的重新渲染。

【讨论】:

  • 谢谢!但我的问题仍然存在:react 组件之外会有代码需要更改。没有强制重新渲染屏幕(或所有组件)的命令吗?也许是一个 REPL 命令? (顺便说一句,我正在使用重新框架)。
  • 也许在根组件中放一个(deref state-atom)
  • 我正在使用 re-frame,我该怎么做?顺便说一句,这是在 figwheel 中推荐的做法吗?
【解决方案2】:

来自docs

设置:figwheel true:figwheel { :on-jsload "example.core/reload-hook" } 会自动将figwheel 客户端代码插入到您的应用程序中。如果您提供:on-jsload 函数的名称,则该函数将在新代码重新加载后被调用。

Reagent 的 reload hook 和配置示例:

(ns your-namespace.core
  (:require [reagent.core :as r]))


(defn render [view]
  (let [node (.getElementById js/document "app")]
    (r/render-component view node)))


(defn rerender []
  (let [node (.getElementById js/document "app")]
    (r/unmount-component-at-node node)
    (render [:div "Reloading"]))


(defn ^:export reload []
  (rerender))

然后在你的project.clj:

:cljsbuild {:builds {:dev {:source-paths ["src"] 
                           :figwheel     {:on-jsload "your-namespace.core/reload"}}}

/编辑

请注意,re-frame 使用 Reagent。在重新构架的情况下,我建议从re-frame-template 开始。例如,

lein new re-frame your-project-name # options, e.g., +re-frisk +cider

这将给出一个默认的core.cljs,如下所示:

(defn dev-setup []
  (when config/debug?
    (enable-console-print!)
    (println "dev mode")))

(defn mount-root []
  (re-frame/clear-subscription-cache!)
  (reagent/render [views/main-panel]
                  (.getElementById js/document "app")))

(defn ^:export init []
  (re-frame/dispatch-sync [:initialize-db])
  (dev-setup)
  (mount-root))

index.html 有一个 id 为 app 的节点并调用 init。而project.cljs 指定on-jsload 如下:

:cljsbuild
{:builds
 [{:id           "dev"
   :source-paths ["src/cljs"]
   :figwheel     {:on-jsload "your-project-name.core/mount-root"}
#_(...)}}

这应该绝对更新带有组件更改的页面。如果它不符合您的要求,我可能误解了您的问题。

【讨论】:

  • 我正在使用re-frame:figwheel true 不起作用。对于:figwheel { :on-jsload "example.core/reload-hook" },应该调用哪个函数(re-frame使用返回函数的函数来创建组件)?
  • @dilvan 我更新了重新框架的答案。如果有帮助,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 2011-11-07
  • 1970-01-01
  • 2022-01-24
  • 2014-12-16
  • 1970-01-01
相关资源
最近更新 更多