bem-site / bem-forum-content-ru

Content BEM forum for Russian speak users
MIT License
56 stars 6 forks source link

Неожиданная инициализация блока #334

Closed Guria closed 9 years ago

Guria commented 9 years ago

Возникла непонятная проблема. Происходит инициализация блока на дом ноде, которой в bemhtml было задано js()(false). В html всё нормально: класса i-bem нет, аттрибута data-bem тоже. Есть только имя класса блока. Однако при наступлении live события этой DOM ноде внезапно инициализируется блок, при этом появляются и data-bem и block_js_inited и i-bem. Пока не удалось локализовать в кусок, который мог бы опубликовать. Может есть идеи почему так может произойти?

Guria commented 9 years ago

Нашёл: в bemjson

[
{
    block: 'blockB',
    js: true,
    content: {
      block: 'blockA',
      js: false,
      content: {
        block: 'input'
      },
    }
  },
  {
    block: 'blockA',
    js: true,
    content: {
      block: 'input'
    },
  }
]

в js

modules.define('blockA', ['i-bem__dom'], function(provide, BEMDOM){
  provide(BEMDOM.decl(this.name, {
    onSetMod: {
      js : {
        inited : function() {
          console.log('init block A');
        }
      }
    }
  },{
    live : function(){
      this.liveInitOnBlockInsideEvent(
        { modName : 'focused', modVal : '*' },
        'input',
        function(){
          console.log('live of blockA');
        });
    }
  }));
});

modules.define('blockB', ['i-bem__dom', 'blockA'], function(provide, BEMDOM, BlockA){
  provide(BEMDOM.decl( {block: this.name, baseBlock:BlockA }, {
    onSetMod: {
      js : {
        inited : function() {
          this.__base();
          console.log('init block B');
        }
      }
    }
  },{
    live: false
  }));
});

При клике в первый инпут инициализируется blockA у которого выставленно js(false). Происходит это только при присутствии на странице другого blockA у которого выставленно js(true).

Сообщу отдельно если удастся сузить пример.

Guria commented 9 years ago

Укоротил:

  {
    block: 'blockA',
    js: false,
    content: {
      block: 'input'
    },
  },
  {
    block: 'blockA',
    js: true,
    content: {
      block: 'input'
    },
  }
]
modules.define('blockA', ['i-bem__dom'], function(provide, BEMDOM){
  provide(BEMDOM.decl(this.name, {
    onSetMod: {
      js : {
        inited : function() {
          console.log('init block A');
        }
      }
    }
  },{
    live : function(){
      this.liveInitOnBlockInsideEvent(
        { modName : 'focused', modVal : '*' },
        'input',
        function(){
          console.log('live of blockA');
        });
    }
  }));
});

При клике в инпут инициализируются оба блока. Кажется, это довольно серьёзная бага.

tadatuta commented 9 years ago

@dfilatov Дима, подскажи, пожалуйста, это бага или фича?

dfilatov commented 9 years ago

Это не бага, это особенность live-блоков. Не может из них часть вдруг оказаться совсем без js. Непонятен реальный кейс такого использования.

Guria commented 9 years ago

Понял. Я нарвался на это дело случайно и не уверен, что мне этот кейс действительно нужен. Более того, в текущем исполнении он явно пахнет. Если внимательно посмотреть первый комментарий можно увидеть, что же я пытался изобразить:

Тем не менее такое поведение live инициализации показалось довольно нелогичным, хотя бы потому что вообще не ясно каким образом вопреки документации инициализируется блок без i-bem и data-bem.

Я покурил дебаггер и есть вопрос: BEMDOM._findBlocks() действительно задуман искать все блоки, в том числе без js реализации? Кажется можно дополнить селектор проверкой класса i-bem BEM_CLASS.

qfox commented 9 years ago

Как-то пахнет, да.

Надо бы посмотреть много ли сломается, если поменять логику. Сложно оценить, стоит ли это менять так сразу.

veged commented 9 years ago

@Guria поиск блоков действительно задуман так, что ищутся все блоки, даже без собственного js-представления — это полезно, когда, например, верхнеуровневый блок хочет переставлять модификаторы внутренним, при этом внутренние могут быть без js

а можно рассказать про конкретную задачу — а то, судя по вопросам, кажется, что это можно было бы делать други, более предусмотренным нами, способом ;-)

Guria commented 9 years ago

Конечно же мне подходят более предусмотренные способы, которыми я уже восспользовался. Оригинальный вопрос снимается. Остаётся только небольшая недокументированная магия, когда происходит инициализация блока, который на первый взгляд инициализироваться не должен был. И ещё сохраняется некоторая неконсистентность: "нежелательной" инициализации не происходило, если на странице не было второго такого же блока, но со включенным js: true.

veged commented 9 years ago

вообще мы не подразумевали, что инициализация может быть "нежелательной" — на блок либо есть js и тогда он предусматривает и нормально переносит инициализацию, либо js нет и тогда инициализация не создаёт никаких видимых эффектов

если на странице не встретилось ни одного js: true блока, то и live секция не исполняется — это специальная оптимизация