Ошибка рендеринга при переключении «display: none» и «display: block» на div - PullRequest
1 голос
/ 11 июля 2019

Я пытаюсь отобразить две новые кнопки после нажатия первой.Для этого у меня есть две кнопки, которые я хочу отобразить на display: none.Когда нажата исходная кнопка, она переключает свой дисплей на ноль, а затем отображает две другие кнопки как display: block.

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

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

Снимок экрана 1 enter image description here

Снимок экрана 2 enter image description here

Снимок экрана 3 enter image description here

HTML

<div class = "container">
   <div class = "row p-0"> 
      <div class = "col text-field-wrapper m-0 p-0"></div>
      <div class = "col button-field-wrapper"></div>
   </div>
</div>

CSS:

.button-field-wrapper {
    font-size: 12px; 
    margin: 18px 0 0 0; 
    height: 36px; 
    display: block;
}
.hide {
    display: none
}
.text-field-wrapper: {
    height: 56px; 
    display: block;
}

JavaScript:

constructor() {
    super();
    this.active = false;
    this.default = true;
    this.maxWidth = 200;
    this.error = false; 
    this.overflow = false; 
    this.getWidth();

    this.inputText = "Enter A Title";
    this.appendChild(template.content.cloneNode(true));


    this.tf_wrapper = this.getElementsByClassName("text-field-wrapper")[0];
    this.bt_wrapper = this.getElementsByClassName("button-field-wrapper")[0];

    this.renderInputField.bind(this)(this.tf_wrapper);
    this.renderButtonField.bind(this)(this.bt_wrapper);
    this.renderOptionField.bind(this)(this.bt_wrapper);
    this.optionWrapper.setAttribute("class", "hide", "option-wrapper")


} 

renderOptionField(bt_wrapper) {
    this.optionWrapper = document.createElement("DIV");
    this.optionWrapper.setAttribute("class", "option-wrapper");
    bt_wrapper.appendChild(this.optionWrapper);

    this.cancelButton = document.createElement("Button");
    this.cancelButton.setAttribute("class", "cancel-button");
    this.cancelButton.addEventListener("click", 
    this.onCancel.bind(this))

    this.closeIcon = document.createElement("object");
    this.closeIcon.setAttribute("type", "image/svg+xml");
    this.closeIcon.setAttribute("class", "close-icon");
    this.closeIcon.setAttribute("data", "Close.svg")
    this.cancelButton.appendChild(this.closeIcon)
    this.cancelButton.innerHTML += "Cancel";

    this.saveButton = document.createElement("Button");
    this.saveButton.setAttribute("class", "save-button");
    this.saveButton.addEventListener("click", this.onSave.bind(this))
    this.saveIcon = document.createElement("object");
    this.saveIcon.setAttribute("type", "image/svg+xml");
    this.saveIcon.setAttribute("class", "save-icon");
    this.saveIcon.setAttribute("data", "Check.svg")
    this.saveButton.appendChild(this.saveIcon)
    this.saveButton.innerHTML += "Save";
    this.optionWrapper.appendChild(this.cancelButton);
    this.optionWrapper.appendChild(this.saveButton);        
}

onEdit() {
    this.editWrapper.setAttribute("class", "edit-wrapper hide")
    this.optionWrapper.setAttribute("class", "option-wrapper")
    this.textField.setAttribute("class", "text-field-active single- 
    line")
    this.active = true;
}

Ответы [ 2 ]

1 голос
/ 12 июля 2019

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

Даже если вашэлементы полностью создаются, когда вы добавляете их в свой контейнер, ваш браузер должен пересчитать ваш поток, чтобы элементы поместились внутри.При этом ваши элементы могут изначально не иметь правильных значений, что иногда может привести к странному поведению.

Создание таких элементов неэффективно.Вам лучше написать свой HTML со всем внутри, , включая элементы, которые вы хотите показать, и те, которые вы хотите скрыть , и менять их свойства на ходу.Вы избежите длинного, трудно поддерживаемого кода javascript и получите более стабильное поведение.

Вот скрипка, которая как бы воспроизводит то, чего вы пытаетесь достичь:

// Script.js

// Load all the elements you need to operate on
const container = document.querySelector('#container');
const staticElements = container.querySelectorAll('.static');
const editElements = container.querySelectorAll('.edit');
const inputField = container.querySelector('input');
const title = container.querySelector('.title');

// Hide all static elements, and display the edit ones
function setEditMode() {
  inputField.value = title.innerHTML;

  for (const element of staticElements) {
    element.classList.add('hidden');
  }
  
  for (const element of editElements) {
    element.classList.remove('hidden');
  }
}

// Reverse of above function
function setStaticMode() {
  for (const element of staticElements) {
    element.classList.remove('hidden');
  }
  
  for (const element of editElements) {
    element.classList.add('hidden');
  }
}

// Call above, but before update static value
function save() {
  title.innerHTML = inputField.value;
  setStaticMode();
}
/* style.css */

#container {
  display: flex;
}

#container > * {
  margin: 5px;
}

.editable {
  font-size: 20px;
  color: #AAAAAA;
}

.button {
  border-style: solid;
  border-color: lightblue;
  border-width: 1px;
  border-radius: 3px;
  padding: 3px;
  cursor: pointer;
}

.editActions {
  display: flex;
}

.editActions > * {
  margin: 0 5px;
}

.hidden {
  display: none;
}
<!—-index.html—->

<div id="container">
  <div class="title static">Enter a title</div>
  <input type="text" class="hidden edit">
  <div class="button static" onClick="setEditMode()">
    edit
  </div>
  <div class="hidden editActions edit">
    <div class="button" onClick="setStaticMode()">
      cancel
    </div>
    <div class="button" onCLick="save()">
      save
    </div>
  </div>
</div>

Смотрите, здесь мы не модифицируем DOM из javascript, и все выглядит ясно, ведя себя как ожидалось.

ЕслиВы должны построить HTML из javascript, делать это осторожно и как можно реже.Вы можете перейти отсюда и адаптировать свой код, чтобы увидеть, насколько эффективны изменения.

0 голосов
/ 13 июля 2019

Это одна из причин, по которой рекомендуется сначала создать ваше веб-приложение для статических страниц (без JavaScript), а затем расширить функциональность, чтобы включить JavaScript для динамизма.

Например, если вы придерживаетесьсогласно приведенному выше совету, html-анализатор браузера сначала вычислит свойства для всех ваших DOM контейнеров, прежде чем применять какой-либо эффект через JavaScript.Если вы этого не сделаете, то ожидается непредвиденное поведение такого рода.

В частности, из вашего кода не делается никаких усилий, чтобы убедиться, что DOM был готов, прежде чем вы начнете добавлять или манипулироватьэто элементы.Посмотрите эту запись о том, как этого добиться, используя ванильный JavaScript.Убедившись, что DOM готов, вы можете скрыть элементы, которые вы хотите динамически отображать, используя JavaScript, и добавить прослушиватели событий, которые вы хотите использовать, чтобы сделать их видимыми.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...