Knockout JS: Остановить привязку элементов div к visible: от мигания на экране

Я работаю над одностраничными приложениями, в которых есть куча скрытых div, привязанных (или привязанных?) к KnockoutJS с помощью visible:. Когда страница загружается, все они на мгновение мигают на экране. Я попытался переместить свой JS в <head></head>, но это не дало никакого эффекта, поэтому загрузка JS внизу страницы не является причиной этого.

К сожалению, привязка visible: не распространяется на атрибут CSS display, поэтому я не могу использовать display: none; при загрузке страницы, иначе visible: вообще не будет работать. Если только... Я загружаю страницу с display: none;, а затем меняю ее в самый первый раз, когда я показываю div пользователю.

Но есть ли более элегантный способ добиться этого?


person solefald    schedule 08.10.2012    source источник
comment
возможный дубликат Как лучше всего скрыть экран во время сборки привязки к нокауту?   -  person Rune Vejen Petersen    schedule 28.12.2014


Ответы (3)


В KnockoutJS я обхожу эту проблему, определяя класс CSS с именем hidden с display:none, затем я добавляю этот класс и привязку к мигающему контейнеру:

class="hidden" data-bind="css: { hidden: false }"
person Tuan    schedule 08.10.2012
comment
Это именно то, что мне нужно! Спасибо! - person solefald; 08.10.2012
comment
Что они сказали ^. Спасибо за этот блестящий ответ! - person Josh Lowry; 20.09.2013
comment
Шикарно действительно. Я сделал одну небольшую поправку и заменил hidden на ko-hidden, просто для большего контекста и чтобы не наступать на существующий скрытый класс: class="ko-hidden" data-bind="css: { 'ko-hidden': false }" - person Cᴏʀʏ; 12.11.2013
comment
Стоит отметить, что в bootstrap 3 есть класс .hidden. getbootstrap.com/css/#helper-classes-show-hide - person mg1075; 20.11.2013
comment
Я думал об этом, но не мог понять, почему привязка visible не делает именно этого. Как говорится в вопросе, привязка visible, похоже, не имеет приоритета над правилами таблицы стилей, что довольно сбивает с толку. По крайней мере, это работает. - person crush; 21.07.2015
comment
@crush Потому что привязка не вступит в силу, пока вы не вызовете applyBindings. - person Tuan; 21.07.2015
comment
@Tuan Я совсем не об этом. В случае, когда вы применили display: none через класс CSS, привязка visible не будет работать, если наблюдаемый объект, к которому он привязан, является истинным. Когда связанное значение привязки visible оценивается как истинное, оно просто устанавливает element.style.display = '', что эффективно удаляет style="display: none" из элемента. Затем применяется базовый класс CSS, который имеет display: none, поэтому элемент никогда не отображается. Поэтому единственным обходным решением является использование style="display: none" вместо классов или специального презентационного класса. - person crush; 22.07.2015
comment
Единственный способ заставить привязку visible работать с классами css в экземпляре, где вы хотите, чтобы класс начинался как display: none, — это иметь необязательный аргумент привязки, который указывает, какой стиль display использовать, когда привязка visible оценивается как истина. так как он не будет указан в классе css (там он указан как none). Что-то вроде visible: isVisible(), visibleDisplayType: 'block'. Конечно, этого не существует, поэтому его нужно было бы добавить. - person crush; 22.07.2015

Я решил эту проблему, поместив свой «кричащий» контент в шаблон сценария и используя виртуальные элементы ko для загрузки шаблона, когда переменная устанавливается другим виртуальным элементом.

Например:

<!-- ko if: myVariable -->
<!-- ko template: { name: 'myTemplate' } --><!-- /ko -->
<script type="text/html" id="myTemplate">
    <ul data-bind="foreach: blah...">
        <li></li>
    </ul>
</script>
<!-- /ko -->

Поэтому, когда установлена ​​переменная myVariable, вместо виртуального элемента шаблона будет помещено содержимое контейнера сценария. С помощью этого метода вы не видите никакого мигающего контента :-)

person Milaan    schedule 15.04.2013
comment
у этого есть бонус в том, что он не ставит display:none на все (когда кто-то еще удаляет привязку данных, он может не помнить об удалении display:none - person roo2; 20.02.2014

В итоге я написал пользовательскую привязку для использования вместо visible по умолчанию.

function isHidden(el) {
    var style;

    style = window.getComputedStyle(el);

    return (style.display === 'none')
}

ko.bindingHandlers['cssVisible'] = {
    'update': function (element, valueAccessor) {
        var value,
            isCurrentlyVisible;

        value = ko.utils.unwrapObservable(valueAccessor());
        isCurrentlyVisible = !isHidden(element);

        if (value && !isCurrentlyVisible) {
            ko.utils.toggleDomNodeCssClass(element, 'ko-visible', true);
        }
        else if ((!value) && isCurrentlyVisible) {
            ko.utils.toggleDomNodeCssClass(element, 'ko-visible', false);
        }
    }
}

Затем немного CSS для управления видимостью

[data-bind*="cssVisible"]:not(.ko-visible) {
    display: none;
}

Использование такое же, как привязка visible

<div data-bind="cssVisible: true"></div>
person blues_driven    schedule 08.07.2016