1

github および google グループでこの質問をしました。結果が出ませんでした。質問は次のとおりです。

再利用可能なコンポーネントをいくつか作成したいとします。

(defn song-player []
  "display songs and controls"
  (let [current-song (atom {"title" "some title", "url" "some-url"})]
    (fn []
      [:div.player
       [:p "title: " (@current-song "title")]
       [:audio#player-audio
        {:src (str (@current-song "url"))}]
       [:input {:type "button"
                :value "Play/Stop"
                :on-click #(let [player (. js/document (getElementById "player-audio"))]
                             (if (.-paused player)
                               (.play player)
                               (.pause player)))}]])))

1 つのページに複数のソング プレーヤーが必要だとします。その場合、ページの ID が重複するため、ID(#player-audio) を audio 要素に割り当てることができません。

では、イベント ハンドラーでローカル コンポーネントを参照するにはどうすればよいでしょうか。この場合、on-click イベントのイベント ハンドラーでローカル オーディオ要素を参照するにはどうすればよいですか?

react.js では、オーディオ コンポーネントに ref を割り当て、this.refs.XXX で参照できます。試薬でこれを行うにはどうすればよいですか? ありがとう!

4

2 に答える 2

1

これを行う方法にはいくつかの問題があると思います。特に、アトムの使用方法と getElementById の使用方法は、試薬/反応で問題を引き起こす可能性があります。私の提案は、アトムを使用してすべての状態 (オーディオ プレーヤーの状態を含む) を保持することです。

タイトルが一意であり、キーとして使用できると仮定すると、すべてのプレーヤーをハッシュのハッシュとして保存します。曲のタイトルを引数として取り、キーワード表現を返す関数を作成すると便利でしょう。

(keyword-title "Some Title") => :some-title

{:first-title {:title "First Title"
               :url "http://....."
       :player :stop} ;; could be :stop :pause :play etc
 :another-title {:title "Another Title"
                 :url "some other url"
         :player :stop}}

「新しい」プレーヤー コンポーネントを作成するとき、実際に行っていることは、状態アトムに別のエントリを追加することです。インタラクティブなボタン/コンポーネントが必要な場合は、状態アトムで動作するように定義します。次に、状態アトムからすべてのエントリをレンダリングするだけのコンポーネントを定義します。

(defn song-player [title url player-state]
  (let [players (r/atom {})] ;; this will only be called once - first time
    (fn [title url player-state]
  (swap! players assoc (keyword-title title) {:title title
                                              :url url
                          :player player-state})
  [player-component players])))

初めて song-player を呼び出すと、players アトムが作成され、次に無名関数が呼び出されます。この匿名関数は、このコンポーネントのレンダリング関数になりました。これが、無名関数と親関数が同じパラメーター シグネチャを持つことが重要な理由です。

プレーヤーコンポーネントは、タイトルに関するすべての状態情報と各タイトルに関連付けられたプレーヤーの状態を含むプレーヤーアトムを取得し、アトムをウォークスルーし、各エントリを適切にレンダリングします

(defn player-component [players]
  (into [:div]
        (for [p (keys @players)]
     ^{:key p} [:div.player
                 [:p "Title: " (get-in @players [p :title])]
         [:audio {:src (get-in @players [p :url])}]
         [:input {:type "button"
                  :value (get-in @players [p :player-state])
              :on-click #(toggle-player-state p players)}]])))

toggle-player-state は、誰かがボタンをクリックしたときの新しい状態を設定します

(defn toggle-player-state [player-id players]
  (if (= :stop (get-in @players [player-id :player-state]))
    (swap! players assoc-in [player-id :player-state] :play)
(swap! players assoc-in [player-id :player-state] :stop)))

明らかに、これは私の思いつきであり、テストされておらず、実際には何よりも疑似コードです。[:audio] タイプが何に拡張されるかはわかりません。ケータリングが必要な制限や、セットアップが必要な他のイベント ハンドラー (:on-complete など) がある可能性があります。ただし、校長はほぼ正しいはずです。Reagent/react では、DOM を直接設定/読み取りすることを避けることが目標だと思います。状態を管理し、あとは試薬/反応に任せます。

于 2015-10-11T08:35:54.197 に答える
0

わかりました、私は何も知りませんが、似たようなものに対する答えを探していました。これまでに思いついたのは次のとおりです。

  1. Reagent は参照を保存しません (理論的には、関数内で「this-as this」を使用して見つけることができます) が、
  2. ここの component-did-mount コールバックに示されている方法を使用して、1 つにジミーすることができます: https://gist.github.com/danielytics/d4374cd51deec7201250

これはあなたを助けるには遅すぎると確信していますが、あなたは決して知りません.

于 2015-09-19T17:43:48.537 に答える