Cause 1.

I recently encountered a problem in a project where I needed to listen for the width change of a DOM element to assign a child node style to that DOM element. In fact, I didn’t think of this detail at first, but I just thought of the page size change when assigning, i.e

Window.onresize = () => {return(() = > {setTimeout(() => { ... }}, 100)}) ()Copy the code

However, it was too simple. Later, it was found that the width of the DOM element also needs to be monitored in the actual operation, which was a bit confused. After checking the Internet, I found that there was a MutationObserver method

3. MutationObserver

Detailed explanation from MDN

Here’s an example:

<div style="width: 200px" id="parent">
    <div id="some-id"></div>
</div>
Copy the code
#some-id{
	width: 100%;
	height: 100px;
	background-color: aqua;
}
Copy the code
var targetNode = document.getElementById('some-id')
var parentNode = document.getElementById('parent')
targetNode.innerHTML =    `
 
// First create a callback function, mutation. Type indicates the type to listen for changes
var callback = function(mutationsList) {
    for(var mutation of mutationsList) {
        if (mutation.type == 'attributes') {
     		console.log('The ' + mutation.attributeName + ' attribute was modified.');
     	} else if (mutation.type == 'childList') {
            console.log('A child node has been added or removed.'); }}}// Create an object instance
 var observer = new MutationObserver(callback)
 
 // config contains the type to listen on
 var config = { attributes: true.childList: true.subtree: true }
 
 // Start listening, passing in the dom object and config to listen on
 observer.observe(targetNode, config)
 // Comment it out
 // Prevent the MutationObserver instance from receiving further notifications
 // observer.disconnect()
 
 setTimeout((a)= > {
	parentNode.style.width = '400px'
	const inputNodes = targetNode.getElementsByTagName('input')
	console.log(inputNodes[0].offsetLeft)
}, 2000)
Copy the code

For config configuration: see

  1. ChildList: Set true to observe changes to the target child node, such as adding or deleting the target child node, excluding changes to the child node and descendants of the child node
  2. Attributes: Sets true to observe changes in target attributes
  3. CharacterData: Set to true to observe the change of target data
  4. Subtree: Set to true, changes to the target and its descendants are observed
  5. AttributeOldValue: If the attribute is true or omitted, it is set to true, indicating that the value of the target attribute before the change needs to be recorded. If you set attributeOldValue, you can omit the attributes setting
  6. CharacterDataOldValue: If characterData is true or omitted, the characterData setting is set to True, indicating that the previous target data needs to be recorded. If characterDataOldValue is set, the characterData setting can be omitted
  7. AttributeFilter: If not all attribute changes need to be observed and attributes are set to true or ignored, set a list of local names (namespace-free) of attributes that need to be observed

Log (‘The ‘+ mutation. AttributeName +’ attribute was modified.’); The width of some-id has changed. Then I put the CSS width: < span style = “box-sizing: border-box; color: RGB (50, 50, 50); line-height: 20px; white-space: inherit! Important;” 100%, although the width px has changed, this property has not changed, so it will not be executed

3. ResizeObserver

I think the MutationObserver API is playing word games with me. Baidu was useless, so I found a ResizeObserver after surfing the Internet

Take a look at this introduction to MDN:

ResizeObserver interface can listen to the boundary of the Element's content area or SVGElement box change ResizeObserver avoids the resize in their own callback, triggering the infinite callbacks and circular dependencies. It does this only by processing the deeper elements of the DOM in subsequent frames. If (the browser) follows the specification, the call will only be triggered before or after the drawingCopy the code

Ok, that’s the API I’m looking for, again, the example above

Omit... Const resizeObserver = new resizeObserver (entries => {for (letentry of entries) { console.log(entry.target.offsetWidth) } }); Start listening, pass the DOM object resizeObserver.observe(targetNode);Copy the code

Console is running! Prints the width of the targetNode after the parent element width changes!!