将 html 上的 observable 动态更改为另一个

Change the observable to another on the html dynamically

我正在尝试通过更改可见性来更新 html 上的可观察对象,我认为它应该更新绑定但没有发生,还有其他方法可以更新绑定吗?

// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
    this.isVisible = ko.observable(true);
    this.counter0 = ko.observable(0);
    this.counter1 = ko.observable(0);
    this.counterDisplay = this.counter0;
    this.add = function() {
        console.log(this.counterDisplay());
        const newValue = this.counterDisplay() + 1;
        this.counterDisplay(newValue);
    };
    this.changeCounter = () => {
        this.isVisible(!this.isVisible());
        if(this.counterDisplay === this.counter0) {
            this.counterDisplay = this.counter1;
            console.log('change to counter1');
        } else {
            this.counterDisplay = this.counter0;
            console.log('change to counter0');
        }
        this.isVisible(true);
    }
}

// Activates knockout.js
ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<p>Counter Main: <div data-bind="text: counterDisplay, visible: isVisible"></div></p>
<button data-bind="click: add">Add</button>
<button data-bind="click: changeCounter">Change</button>

<p>Counter0: <div data-bind="text: counter0"></div></p>
<p>Counter1: <div data-bind="text: counter1"></div></p>

在示例中,主计数器显示计数器 0 的值,但在单击“更改”按钮后,主计数器应更改为显示计数器 1 的值,我认为更改可见性应重新渲染 DOM 并绑定到 counter1 值,但它仍然与 counter0 绑定。

可见性绑定不会影响绑定本身,它只会更改 DOM 元素显示状态。 更改绑定可以通过使用 ko.cleanNode(DOMElement) 来实现,但只有在您确实需要完全重建绑定时才应使用它,而不是 100 的 99 次。

在您的情况下,简单地创建一个存储活动计数器索引的可观察对象和一个显示活动计数器值的计算对象会更容易。请参阅下面的代码。

// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
 const self = this;
 self.activeCounterIndex = ko.observable('0');
 self.counter0 = ko.observable(0);
 self.counter1 = ko.observable(0);

 this.activeCounterValue = ko.computed(function(){
  return self['counter'+self.activeCounterIndex()]();
 });

 this.add = function() {
  const newValue = self['counter'+self.activeCounterIndex()]() + 1;
  self['counter'+self.activeCounterIndex()](newValue);
 };

 this.changeCounter = () => {
  if (self.activeCounterIndex() === '0') {
   self.activeCounterIndex('1');
  } else {
   self.activeCounterIndex('0');
  }
 }
}

// Activates knockout.js
ko.applyBindings(new AppViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<p>Active counter (#<span data-bind="text:activeCounterIndex"></span>): <b data-bind="text: activeCounterValue"></b></p>
<button data-bind="click: add">Increment active counter</button>
<button data-bind="click: changeCounter">Swich counter</button>

<p>Counter #0: <span data-bind="text: counter0"></span></p>
<p>Counter #1: <span data-bind="text: counter1"></span></p>