在div上切换“显示:无”和“显示:阻止”时呈现错误

时间:2019-07-11 18:48:17

标签: javascript html css web

单击第一个按钮后,我试图显示两个新按钮。为此,我要将要显示的两个按钮设置为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 个答案:

答案 0 :(得分:1)

  

这可以工作,但是会出现奇怪的显示错误,即最初的按钮要大得多,然后迅速恢复到应有的大小。

即使在将项目附加到容器时完全创建了项目,您的浏览器也需要重新计算流程以使元素适合内部。这样做时,您的商品最初可能没有设置正确的值,有时可能会导致奇怪的行为。

创建这样的元素并不是有效的方法。最好编写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>

在这里,我们没有从javascript修改DOM,并且一切看起来都很清晰,表现出预期。

如果您必须使用javascript构建HTML,请小心谨慎,并尽可能做到偶尔。您可以从这里修改代码,以查看更改是否有效。

答案 1 :(得分:0)

这是建议您首先为静态页面(不包含JavaScript)构建Web应用程序,然后扩展该功能以合并JavaScript以实现动态的原因之一。

例如,如果您遵循上述建议,那么在通过JavaScript应用任何效果之前,浏览器的html解析器将首先计算所有DOM容器的属性。如果您不这样做,那么这种不可预测的行为是可以预期的。

具体来说,从您的代码开始,在开始附加到或操作其元素之前,无需做任何工作来确保DOM已准备就绪。请参阅此post,以了解如何使用原始JavaScript实现此目标。确保DOM就绪后,您就可以使用JavaScript隐藏要动态显示的元素,并添加要用于使其可见的事件侦听器。