首页 > 解决方案 > 动态地将 html 上的 observable 更改为另一个

问题描述

我正在尝试通过更改可见性来更新 html 上的 observable,我认为它应该更新绑定但没有发生,是否有另一种方法来更新绑定?

// 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 的值,但是在单击更改按钮后,主计数器应该更改为显示 counter1 值,我认为更改可见性应该重新渲染 DOM 并绑定到 counter1 值,但是它仍然与 counter0 绑定。

标签: htmldata-bindingknockout.js

解决方案


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

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

// 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>


推荐阅读