【问题标题】:Rxjs - Not grabbing the value of dom element in observableRxjs - 没有在 observable 中获取 dom 元素的值
【发布时间】:2015-11-26 08:25:43
【问题描述】:

我正在尝试制作一个从输入框中搜索颜色数组的小部件。

在我的 js 文件中的搜索 Observable 中,我引用了我从中获取按键的输入 dom 元素。每当我尝试获取 $input 的值时,我都会变得不确定。但是,当我进入控制台时,我可以选择元素并获取值。这应该更新该值,以便我将受限制的按键发送到我的搜索功能。目前,我将 undefined 发送回我的 searchColors 函数。

这会引发Uncaught TypeError: Cannot read property 'toLowerCase' of undefined

我认为我的 $input 是这段代码中的主要错误。感谢您的帮助!

Javascript

var Observable = Rx.Observable; 
  var colors = ["AliceBlue",...,"YellowGreen"].map(function (n) {return n.toLowerCase()});
  var $input = document.querySelector("#bg-color-input");
  var $container = document.querySelector("#bg-color-container");
  var $results = document.querySelector("div#ac-list");
  var $clear = document.querySelector("#bg-color-clear");
  var $node, change;

  function setBackground (color) {
    this.style.backgroundColor = color;
  }

  function clearColors () {
    while (this.firstChild) {
      this.removeChild(this.firstChild);
    }
  }

  function searchColors (substr) {
    colors.forEach(function (color) {
      if(color.indexOf(substr.toLowerCase()) > -1) {
        var el = document.createElement('div');
        el.innerHTML = color;
        el.style.backgroundColor = color;
        el.className = 'color-node col-md-1'
        $results.appendChild(el)
      }
    })

    $node = document.querySelectorAll(".color-node");

    change = Observable.fromEvent($node, 'click')
      .map(function (e) { return e.target.innerHTML });

    change.subscribe(setBackground.bind($container));
  }

  var search = Observable.fromEvent($input, 'keypress').
    throttle(20).
    map(function (key) { return $input.value; }).
    distinctUntilChanged().
    map(function (search) { searchColors(search); });

  var clear = Observable.fromEvent($clear, 'click').
    map(function (e) { return e })

  search.subscribe(searchColors.bind($results))
  clear.subscribe(clearColors.bind($results))

HTML

  <div class="container">
    <div id="bg-color-container">
      <h1>Change the Background Color</h1>
      <p>
        By entering a valid named CSS color you can change the background color of this div.
      </p>
      <input type="text" id="bg-color-input">
      <button id="bg-color-clear">Clear</button>
      <div class="row" id="ac-list">
    </div>
  </div>

这是我的代码的 jsbin http://jsbin.com/ravagi/edit?html,js,output

【问题讨论】:

    标签: javascript dom reactive-programming observable rxjs


    【解决方案1】:

    这可以通过使用do 操作符或console.log 日志指令来追踪操作符链的执行。通过这样做,我发现:

    • 您拨打searchColors 两次。第二次传递的值将始终未定义,因为您还没有在map(function (search) { searchColors(search); }); 中返回一个值,所以当您订阅该流时,您会得到undefined。也许您出于调试目的在事后添加了该代码?

    • 一旦你更正了,你会看到$input.value 仍然是undefined。这里的问题是你对keypress 做出反应。您应该对keyup 做出反应。在keypress时间,输入框还没有更新你的key。

    简而言之,将相应的行替换为:

      var search = Observable.fromEvent($input, 'keyup').
        throttle(20).
        map(function (key) { return $input.value; }).
        distinctUntilChanged();
    

    jsbin : http://jsbin.com/cosetocowe/edit?html,js,output

    最后一条评论,在searchColors 函数中,您追加了新元素,因此在您键入时,您将在末尾添加精炼的选择。这就是你所寻求的行为吗?

    【讨论】:

    • 谢谢!我没有意识到按键不会记录值并且我没有返回搜索。我更新了代码,以便反映您的更改。
    【解决方案2】:

    你可以使用 RxJs-DOM

    包含脚本并更改您的搜索定义,仅此而已。

    var search = Rx.DOM.keyup($input)
          .pluck('target','value')
          .filter( function (text) {
            return text.length > 0;
        }).debounce(50)
        .distinctUntilChanged();
    &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs-dom/7.0.3/rx.dom.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 2018-05-10
      • 2016-10-03
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 2013-08-20
      • 1970-01-01
      相关资源
      最近更新 更多