2016-11-23 4 views
1

У меня есть веб-приложение, которое работает на CLI Aurelia и использует нокаут для его привязок (потому что предыдущее приложение, которое я конвертирую в Aurelia, использовало нокаут широко). Для этого я использую плагин Aurelia-нокаут без проблем.Проблема с нокаутом, связанная с кэшированием Aurelia

Я сделал (как тест) двух простых видов (и соответствующие маршруты):

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

когда я навигации to #/test2 Я правильно вижу

456 

, но если бы я вернуться обратно # test1 Я вижу

112233 

, если я теперь возвращайся # test2 Я вижу также число "дублируется. И каждый раз, когда я иду туда и обратно, цифры всегда добавляются. Например, если я посещаю # test1 4 раза, я получаю

111122223333 

ПРИМЕЧАНИЕ: Если я не кэшировать мнения (путем исключения «вид-кэш» атрибут) все работает нормально.

Но я хотел бы использовать кеширование вида. Я знаю из того, что я читал, что это функция, с которой работает команда Aurelia, я просто хотел бы знать, есть ли у кого-то одна проблема и как ее решить. Похоже, что привязки нокаутов «добавляются» к уже существующим при каждом наступлении навигации.

Update

Я просто попытался с помощью 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, переменная «активирована» истинна.

Тем не менее, результат привязки нокаута такой же, как и раньше.

+0

как насчет использования 'ko.observableArray' вместо' ko.observable'? –

+0

извините, конечно, я хотел использовать наблюдаемые массивы. Во всяком случае, я просто попробовал это, и ничего не изменилось. (Я исправил код в вопросе) –

+0

как насчет очистки массива перед его заполнением? например 'values1 = ko.observableArray ([]);' и затем присваивать '[1,2,3]' массиву 'values1 ([1,2,3]);' – gkb

ответ

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; } }

+0

Нет, если он еще не активирован, я просто хочу активировать его и ничего больше. Если он уже активирован, я хочу попытаться сбросить свойство, чтобы проверить, работает ли привязка нокаута. Проблема в том, что каждый дополнительный визит на страницу «добавляет» те же значения снова и снова к наблюдаемому свойству, связанному с html (как я описал) –

+0

Это потому, что каждый раз, когда объект активирован, ваш код добавляет значения в массив , Вы должны инициализировать массив один раз, когда вы активируете объект, а затем при предыдущих активациях ничего не делать. –

+0

Мой код не добавляет значения в массив, он просто сбрасывает значения массива. Во всяком случае, это был просто дополнительный тест, который я сделал, если вы посмотрите на мой вопрос до раздела «обновления», нет логики «активировать» и по-прежнему возникает одна и та же проблема. –

0

Ok Я нашел способ обойти проблема, используя 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, чтобы избежать этой проблемы.

0

Взятые from here:

Aurelia кэширует весь "View" объект (в том числе документ-фрагмента, который держит HTML) при переходе на другой вид. Если вы вернетесь, Aurelia использует кешированный вид и привязывает его к вашей новой модели представлений. Это отлично работает, потому что все привязки Aurelia снова обрабатываются. Но механизм шаблонов не знает синтаксиса Knockout, который динамически генерирует html. Он рассматривает его как «нормальный html» и не отменяет изменений предыдущих прогонов.

Этот плагин вызывает ko.cleanNode (...), если вызываемый обратный вызов вызывается из Aurelia. Это возвращает изменения, сделанные ранее (так точно, что вам нужно). К сожалению, обратный вызов называется слишком поздним. Старый вид уже отсоединен, и эта очистка не влияет. Фрагмент документа кэшируется как есть.