Typescript 触发计算属性更新

Typescript 触发计算属性更新,typescript,knockout.js,Typescript,Knockout.js,我正在尝试将计算属性更新从viewmodel强制更新到UI。然而,我只得到初始值,没有进一步的值。变异属性失败,因为它不是函数 场地 从该.refreshProcessDetails()调用此.processName.valueHasMutated()时,我遇到以下错误: 堆栈:TypeError:this.processName.valueHasMutated不是一个函数\n atvalueHasMutated是一个只有正常观测值才具有的方法。计算的观测值没有这种方法。这主要是因为valueh

我正在尝试将计算属性更新从viewmodel强制更新到UI。然而,我只得到初始值,没有进一步的值。变异属性失败,因为它不是函数

场地

从该.refreshProcessDetails()调用此.processName.valueHasMutated()时,我遇到以下错误:


堆栈:TypeError:this.processName.valueHasMutated不是一个函数\n at

valueHasMutated
是一个只有正常观测值才具有的方法。计算的观测值没有这种方法。这主要是因为
valuehasbutated
没有做你认为它做的事情。它不会在您调用它的可观察对象中触发更新,而是在订阅可观察对象时触发下游更新,因此它在这里对您没有帮助。在本例中,如果这起作用,它将通知HTML绑定进行更新,但不会更改
processName
的值,因此绑定不会做任何事情

一般来说,除了更改所依赖的可观察对象之外,没有办法触发对计算可观察对象的更新。相反,您的计算机可观察对象应该依赖于某个地方的另一个可观察对象(最好),或者您应该自己手动写入一个可观察对象(如果必须)。为此:

  • 如果可以的话,将
    processViewModel.testService.flowModel.process.name
    中正在更改的部分(例如,流程名称,或者正在更改的流程本身等)设置为可观察的部分,以便在更改时自动更新计算结果
  • 或者,根本不需要计算。将processName和processNodeCount保留为正常的可观察对象,并且在调用refreshProcessDetails时,将正确的值写入其中
  • Computed的存在可以自动保持数据模型在整个过程中的同步。你必须要么承诺(使用整个观测值)要么自己做(手动更新正常观测值),你不能停留在中间。< /P>
    请注意,如果您选择了选项2,您将损失大量(全部?)的淘汰值。进行敲除的“正确”方法是保持应用程序的大部分(此处的字段以及模型中的字段)是可观察的,以便一切都能神奇地工作。使用Knockout的代码越大,效果越好——缩小它意味着Knockout更愿意为您做更多的手工工作。

    谢谢,我得想一想。选项2更可取,但由于属性来自DTO模型,因此需要进行大量更改。您的
    TestService
    是否不提供任何您可以订阅的事件?聆听“加载”事件将更适合knockout完全由事件驱动的方法。创建类似于
    refreshProcessDetails
    的轮询函数将导致不理想的结果。
    <script src="../../libraries/knockout-3.4.1.js"></script>
    <input id="nameInput" data-bind="value: processName" type="text"/>
    <input id="nodetotalInput" data-bind="value: processNodeCount" type="text"/>
    
    export class ProcessViewModel {
        public processName: KnockoutObservable<string>;
        public processNodeCount: KnockoutObservable<number>;
    
        constructor() {
            try {
                this.testService = new Test.TestService();
    
                this.setBindings();
            }
            catch (e) {
                console.log(e);
            }
        }
    
        public setBindings(): void {
            this.processName = ko.computed<string>(
                function() { processViewModel.isLoaded() ? processViewModel.testService.flowModel.process.name : ""; }
            );
            this.processNodeCount = ko.computed<number>(
                function() { processViewModel.isLoaded() ? processViewModel.testModel.nodeCount() : 0; }
            );
        }
    
        public isLoaded(): boolean {
            return this.testService.isLoaded();
        }
    
        public refreshProcessDetails() {
            try {
                let message: string = "IsLoaded" + this.isLoaded();
                console.log(message);
    
                /** attempts at triggering an update */
                this.processName();
                this.processName.valueHasMutated(); // fails because it's not a function
    
                this.processNodeCount();
            }
            catch (e) {
                console.log(e);
            }
        }
    }
    
    declare var processViewModel: Process.ProcessViewModel;
    
    window.onload = () => {
        processViewModel = new Process.ProcessViewModel();
        processViewModel.setBindings();
        ko.applyBindings(processViewModel);
    }