5

Cycle で入力をフォーカスするにはどうすればよいですか? DOM 内にアクセスして、.focus()jQuery を使用するかどうかに関係なく呼び出す必要がありますか、それとも Cycle/RxJS を使用する別の方法がありますか?

4

3 に答える 3

6

はい、DOM 内にアクセスして、.focus()jQuery を使用するかどうかに関係なく呼び出す必要があります。ただし、これは副作用であり、これらの種類の副作用をいわゆるdriverに移動するのが Cycle.js の規則です。

ドライバーが知っておく必要がある 2 つの質問は次のとおりです。

  • どの要素に注目したいですか?
  • いつ要素にフォーカスしたいですか?

両方の質問に対する答えは、DOM 要素の単一のストリームによって提供できます。

ドライバーを作成する

まず、ドライバーを作成します。と呼びましょうSetFocus。いわゆる読み取り専用ドライバーにします。アプリのシンクから読み取りますが、アプリにソースを提供しません。を読んでいるため、ドライバーの関数は、ストリームとなる正式なパラメーターを受け入れる必要があります。それを呼び出しますelem$

function makeSetFocusDriver() {
  function SetFocusDriver(elem$) {
    elem$.subscribe(elem => {
      elem.focus();
    });
  }
  return SetFocusDriver;
}

このドライバーは、ストリームに到着した DOM 要素を受け取り、それを呼び出します.focus()

ドライバーを使用する

Cycle.run関数に提供されるドライバーのリストに追加します。

Cycle.run(main, {
  DOM: makeDOMDriver('#app'),
  SetFocus: makeSetFocusDriver() // add a driver
});

次に、メイン関数で:

function main({DOM}) {

  // setup some code to produce the elem$ stream
  // that will be read by the driver ...
  // [1]: say _when_ we want to focus, perhaps we need to focus when
  //      the user clicked somewhere, or maybe when some model value
  //      has changed
  // [2]: say _what_ we want to focus
  //      provide the textbox dom element as actual value to the stream
  //      the result is:
  //      |----o-----o-----o--->
  //      where each o indicates we want to focus the textfield
  //      with the class 'field'
  const textbox$ = DOM.select('.field').observable.flatMap(x => x); // [2]
  const focusNeeded = [
    clickingSomewhere$,    // [1]
    someKindofStateChange$ // [1]
  ];
  const focus$ = Observable.merge(...focusNeeded)
    .withLatestFrom(textbox$, (_, textbox) => textbox); // [2]

  // ...

  // [*]: Add driver to sinks, the driver reads from sinks.
  //      Cycle.js will call your driver function with the parameter
  //      `elem$` being supplied with the argument of `focus$`
  return {
    DOM: vtree$,
    SetFocus: focus$, // [*]
  };
}

次に、集中しfocusNeededたいときに言うように構成できます。.field

于 2016-03-25T11:04:18.687 に答える
5

独自の状況に合わせて調整できますが、これは問題を解決する方法を示しているはずです。テキスト入力とボタンがあるとしましょう。ボタンがクリックされたときに、テキスト入力にフォーカスを置いたままにする必要があります。

最初にインテント()関数を書きます:

function intent(DOMSource) {
    const textStream$ = DOMSource.select('#input-msg').events('keyup').map(e => e.target);
    const buttonClick$ = DOMSource.select('#send-btn').events('click').map(e => e.target);

    return buttonClick$.withLatestFrom(textStream$, (buttonClick, textStream) => {
        return textStream;
    });
}

次に、失われたフォーカスの副作用を処理するためのシンクを持つメイン

function main(sources) {
    const textStream$ = intent(sources.DOM);

    const sink = {
       DOM: view(sources.DOM),
       EffectLostFocus: textStream$,
    }

    return sink;
}

次に、この副作用を処理するドライバーは次のようになります

Cycle.run(main, {
    DOM: makeDOMDriver('#app'),
    EffectLostFocus: function(textStream$) {    
         textStream$.subscribe((textStream) => {
         console.log(textStream.value);
         textStream.focus();
         textStream.value = '';
      })
    }
});

例全体はこのcodepenにあります。

于 2016-02-03T21:16:12.893 に答える
2

以下は、Staltz 氏自身が書いた一例です: https://github.com/cyclejs/cycle-examples/blob/master/autocomplete-search/src/main.js#L298

于 2016-01-28T08:00:40.837 に答える