Aurelia缓存视图中的Knockout绑定问题

时间:2016-11-23 10:43:35

标签: knockout.js aurelia aurelia-cli

我有一个在Aurelia CLI上运行的web应用程序,并使用knockout进行绑定(因为之前我转换为Aurelia的应用程序广泛使用了淘汰赛)。为此,我使用Aurelia-knockout插件没有问题。

我做了(作为测试)两个简单的视图(和相应的路线):

#/test1
#/test2

以下是观点:

<!-- test1.html -->
<template view-cache="*">
    <div knockout>
        <br /><br />
        <div data-bind="foreach: values1">
            <div data-bind="text: $data"></div>
        </div>
    </div>
</template>

<!-- test2.html -->
<template view-cache="*">
    <div knockout>
        <br /><br />
        <div data-bind="foreach: values2">
            <div data-bind="text: $data"></div>
        </div>
    </div>
</template>

正如您从html中看到的那样,我正在缓存视图using the "view-cache" attribute,以便在我导航回该视图时不会重新加载它们。 相应的模型简单定义如下:

//test1.js
export class Test1 {        
    values1 = ko.observableArray([1,2,3]);
}

//test2.js
export class Test2 {        
    values2 = ko.observableArray([4,5,6]);
}

这是我的路由器配置:

routes = [                    
    { route: ['', 'test1'], moduleId: 'views/test1', name: 'test1' },
    { route: ['test2'], moduleId: 'views/test2', name: 'test2' } 
];

config.map(routes);

首次加载页面时,我正确地看到了

123

当我导航到#/ test2时,我正确地看到了

456

但如果我导航回#test1,我会看到

112233

如果我现在再次访问#test2,我会看到数字'重复'。每次我来回走动,都会添加数字。例如,如果我访问#test1 4次,我会得到

111122223333

注意:如果我不缓存视图(通过省略&#34; view-cache&#34;属性),一切正常。

但我想使用视图缓存。据我所知,这是Aurelia团队仍在努力的一个功能,我想知道是否有人有同样的问题以及如何解决它。每当导航发生时,看起来好像敲除了已经存在的敲除绑定。

更新

我刚尝试使用这样的singleton decorator

import * as Framework from 'aurelia-framework';

@Framework.singleton()
export class Test1 {                
    activated = false;
    values1 = ko.observableArray([1,2,3]);

    constructor(){
        console.log('constructed')
    }

    activate() {
        if (this.activated) {
            console.log('activated')
            var val = this.values1();
            this.values1([]);
            this.values1([1,2,3]);
            console.log(this.values1())
        } else this.activated = true;
    }
}

改变之处在于不再调用构造函数,并且viewModel的状态是持久的(这意味着,第二次导航到#test1,变量&#34;激活&#34;是真的。< / p>

仍然,敲除绑定的输出与以前相同。

3 个答案:

答案 0 :(得分:0)

我认为你的激活方法可能存在逻辑问题。 我相信应该阅读

if (!this.activated) ....

并移动

this.activated = true

如果像这样的内容

activate() { if (!this.activated) { console.log('activated') var val = this.values1(); this.values1([]); this.values1([1,2,3]); console.log(this.values1()); this.activated = true; } }

答案 1 :(得分:0)

好的,我找到了一种绕过这个问题的方法,使用KnockoutBindable as explained here

//test1.html (and test2.html, same code only with variable name values1 instead of values2)
<template view-cache="*">
    <div knockout>
        <div repeat.for="item of values2">
            ${item}
        </div>
    </div>
</template>

//test1.js (and test2.js, same as above)
import * as Framework from 'aurelia-framework';
import {KnockoutBindable} from "aurelia-knockout";
import {inject} from 'aurelia-dependency-injection';

@Framework.singleton()
@inject(KnockoutBindable)
export class Test2 {        
    activationData = {
        values2: ko.observableArray([4,5,6])
    }
    knockoutBindable;

    @Framework.bindable
    values2;

    constructor(kb) {
        this.knockoutBindable = kb;        
    }

    activate() {
        this.knockoutBindable.applyBindableValues(this.activationData, this); 
    }
}

现在,如果我来回走动,那么正确保留了数值。 这样做的缺点是我必须创建一个额外的变量来“镜像”敲除变量,而html中的变量使用aurelia语法来避免这个问题。

答案 2 :(得分:0)

采取from here

Aurelia缓存整个&#34; View&#34;如果切换到另一个视图,则对象(包括保存html的文档片段)。如果你回去,Aurelia使用缓存的视图并将其绑定到新的视图模型。这样可以正常工作,因为所有Aurelia绑定都会被完全处理。但模板引擎并不知道动态生成html的Knockout语法。它将它视为&#34;普通的html&#34;并且不会恢复之前运行的更改。

如果从Aurelia调用unbind回调,则此插件调用ko.cleanNode(...)。这将恢复Knockout之前所做的更改(这正是您所需要的)。不幸的是,回调被称为太迟了。旧视图已经分离,这种清理不起作用。文档片段按原样缓存。