简体   繁体   English

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

[英]Rendering bug while toggling "display: none" and "display: block" on div

I am attempting to display two new buttons after clicking the first one.单击第一个按钮后,我试图显示两个新按钮。 To do this I have the two buttons I want to display set to display: none .为此,我将要显示的两个按钮设置为display: none When the initial button is clicked it toggles its display to none and then displays the other two buttons as display: block .单击初始按钮时,它会将其显示切换为无,然后将其他两个按钮display: blockdisplay: block

This works but a weird display bug occurs where initially the buttons are much larger than they should be, and quickly return to the size they are supposed to be.这是有效的,但一个奇怪的显示错误发生在最初按钮比它们应该大得多的地方,然后迅速恢复到它们应该的大小。

I've attached images to show this, but could not embed because my reputation.我附上了图片来展示这一点,但由于我的声誉而无法嵌入。

Screenshot 1截图 1 在此处输入图片说明

Screenshot 2截图 2 在此处输入图片说明

Screenshot 3截图 3 在此处输入图片说明

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

This works but a weird display bug occurs where initially the buttons are much larger than they should be, and quickly return to the size they are supposed to be.这是有效的,但一个奇怪的显示错误发生在最初按钮比它们应该大得多的地方,然后迅速恢复到它们应该的大小。

Even though your items are completly created when you append them to your container, your browser needs to recalculate your flow, to make elements fit inside.即使您的项目在您将它们附加到您的容器时已完全创建,您的浏览器仍需要重新计算您的流程,以使元素适合其中。 While doing this, your items may initially not have correct values set, which can result in strange behaviors sometimes.执行此操作时,您的项目最初可能没有设置正确的值,这有时会导致奇怪的行为。

Creating elements like this isn't an efficient way to go.创建这样的元素并不是一种有效的方法。 You'd better write your HTML with everything inside, including elements you want to show and those you want to hide , and change their properties on the go.你最好用里面的所有东西来编写你的 HTML,包括你想要显示的元素和你想要隐藏的元素,并随时更改它们的属性。 You'll avoid long, hardly maintainable javascript code, while getting more stable behavior.您将避免使用冗长且难以维护的 javascript 代码,同时获得更稳定的行为。

Here's a fiddle that kinda reproduce what you are trying to achieve :这是一个小提琴,可以重现您想要实现的目标:

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

See, here, we do not modify the DOM from javascript, and everything looks clear, behaving as expected.看,在这里,我们没有从 javascript 修改 DOM,一切看起来都很清楚,行为符合预期。

If you have to build HTML from javascript, do it carefully, and as occasionally as possible.如果您必须从 javascript 构建 HTML,请小心执行,并尽可能不定期地执行。 You can go from here and adapt your code, to see if the changes are effective.您可以从这里开始并调整您的代码,以查看更改是否有效。

This is one of the reasons it is advised to build your web application for static pages (with no JavaScript) first and then scale up the functionality to incorporate JavaScript for dynamism.这是建议首先为静态页面(没有 JavaScript)构建 Web 应用程序,然后扩展功能以合并 JavaScript 以实现动态的原因之一。

For instance, if you adhere to the above advice then the browser's html parser would have computed the properties for all your DOM containers first before you apply any effect via JavaScript.例如,如果您遵循上述建议,那么在您通过 JavaScript 应用任何效果之前,浏览器的 html 解析器将首先计算所有DOM容器的属性。 If you don't do this, then this kind of unpredictable behavior is expected.如果你不这样做,那么这种不可预测的行为是预料之中的。

Specifically, from your code, there is no effort to make sure that the DOM was ready before you start appending to or manipulating it's elements.具体来说,从您的代码来看,在您开始附加或操作其元素之前,无需努力确保DOM已准备就绪。 See this post on how to achieve this using vanilla JavaScript.请参阅有关如何使用 vanilla JavaScript 实现此目的的帖子 Once you've made sure the DOM is ready, you can then hide elements you want to display dynamically using JavaScript and add event listeners you want to use to make them visible.一旦确定DOM已准备就绪,就可以使用 JavaScript 隐藏要动态显示的元素,并添加要使用的事件侦听器以使它们可见。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM