【问题标题】:Computed observable not updating UI计算的 observable 不更新 UI
【发布时间】:2016-11-03 16:15:50
【问题描述】:

我的淘汰赛网络中的计算变量有问题。这是我的代码:

function ViewModel() {
    var self = this;
    self.seatsRaw = ko.observableArray([]);
    self.selectedSeatId = ko.observable();
    self.session = ko.observable();
    self.seats = ko.computed(function(){
        var seatsComplete= self.seatsRaw().slice(0);
        for (var i = 0; i < seatsComplete.length; i++) {
            if (self.selectedSeatId()) {
                seatsComplete[i].selected = seatsComplete[i].id == self.selectedSeatId();
            } else if (self.session () && Number(self.session ().seat) > 0) {
                seatsComplete[i].selected = seatsComplete[i].id == self.sesion().seat;
            } else {
                seatsComplete[i].selected = false;
            }
        }
        return seatsComplete;
    });
    self.selectSeat = function(data,event) {
    self.selectedSeatId($(this).id);
    };
}

所以,我只收到一个带有座位的数组,我想为数组中的每个对象添加一个字段,以便在 UI 中显示为“已选择”。

我从 ajax 读取会话和席位的原始信息,当我更新它们时,我的 UI 没有任何变化。

为什么会这样?然后,我需要做什么来更新我的 UI?

谢谢!

编辑

<ul class="seats" data-bind="foreach: seats">
      <li data-bind="css: {selected: selected, 'non-selected': !selected}, click: $root.selectSeat">
       <a href="#" data-bind="attr: {id: id}">
            <img data-bind="attr: {src: baseUrl + 'img/seats/' + image}" />
            <p data-bind="text: name"></p>
       </a>
      </li>
 </ul>

Seat 不是 ViewModel...应该是吗?

【问题讨论】:

  • selected 中的 seatsComplete 属性可能必须是可观察的。这意味着您必须使用 seatsComplete[i].selected(seatsComplete[i].id == self.selectedSeatId()) 等设置它。
  • 对不起,这不起作用...
  • 您能展示您的视图 (HTML) 和座位的视图模型吗?
  • 我已经编辑了我的问题。

标签: knockout.js knockout-3.0 computed-observable


【解决方案1】:

感谢您提供一些额外的上下文。我将尝试更好地解释我在 cmets 中的意思。

Seat 不是 ViewModel...应该是吗?

即使Seat 只是一个普通对象,它也是一种视图模型...这是您的代码中发生的事情(据我所知):

当您在计算中创建新数组时,它会被之前的数组具有的相同对象填充。淘汰赛渲染器看不到重新渲染列表项的理由。

看看这个例子。从日志中您可以看到一切“正常工作”,但淘汰赛不会更新。在这个例子之后,我将展示如果我们让 selected 可观察会发生什么。

var seats =[
  { id: 1, selected: false },
  { id: 2, selected: true },
  { id: 3, selected: false }
];

var ViewModel = function() {
  var self = this;
  this.rawSeats = ko.observableArray(seats);
  
  this.selectedSeatId = ko.observable(2);
  this.selectSeat = function(data, event) {
    self.selectedSeatId(data.id)
  }
  
  this.seats = ko.computed(function() {
    var selectedId = self.selectedSeatId();
    self.rawSeats().forEach(function(seat) {
      seat.selected = seat.id === selectedId;
    })
    
    console.log(self.rawSeats());
    return self.rawSeats();
    
  });
  
  }

ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
  <li data-bind="css: { selected: selected }, 
                 text: id,
                 click: $root.selectSeat"></li>
</ul>

现在,有了可观察的属性:

var seats =[
  { id: 1, selected: ko.observable(false) },
  { id: 2, selected: ko.observable(true) },
  { id: 3, selected: ko.observable(false) }
];

var ViewModel = function() {
  var self = this;
  this.rawSeats = ko.observableArray(seats);
  
  this.selectedSeatId = ko.observable(2);
  this.selectSeat = function(data, event) {
    self.selectedSeatId(data.id)
  }
  
  this.seats = ko.computed(function() {
    var selectedId = self.selectedSeatId();
    self.rawSeats().forEach(function(seat) {
      seat.selected(seat.id === selectedId);
    })
    
    return self.rawSeats();
    
  });
  
  }

ko.applyBindings(new ViewModel());
.selected { background: yellow }
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: seats">
  <li data-bind="css: { selected: selected }, 
                 text: id,
                 click: $root.selectSeat"></li>
</ul>

【讨论】:

  • 如果你运行你的代码,你会看到即使你改变你的视图模型点击 li,黄色背景总是在第二个 li。
  • 您是否一直阅读到第二个示例...?第一个是为了显示我相信你犯的错误......
猜你喜欢
  • 2015-10-02
  • 1970-01-01
  • 2019-06-02
  • 2017-01-16
  • 2018-11-09
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
相关资源
最近更新 更多