Dev*_*abc 5 javascript performance reactjs react-dom
(更新:之前我以为是React Router导致的这个问题,但是我把React Router从代码中剥离了,问题依旧,所以我彻底修改了这个问题。)
我有分页页面,每页显示图像列表。(“页面”是指可见的完整内容,不是单独的 html 文件/url。)我想以有效的方式浏览这些页面。
如果我在页面中导航得足够快,则在导航到下一页之前,并非所有图像都会加载到当前页面中。我希望浏览器在导航到下一页时取消所有未完成的图像下载。但这不会发生,浏览器会保留所有未完成的图像等待下载,直到它们全部下载完毕。然后我导航到的页面的图像将被下载。这会导致很大的延迟和带宽浪费。
是否可以取消下载上一页的“待处理”图像?
要对此进行测试,请使用浏览器开发人员工具中的“网络”选项卡。还要选择“禁用缓存”并将节流阀(开发人员工具中的下载速度)设置为“慢速 3G”之类的慢速,否则图像将被加载得太快也看到问题。然后浏览页面并看到待处理图像列表正在堆积,然后单击“禁用图像”按钮。然后,屏幕上将看不到任何图像,但浏览器仍然打开大量待处理的图像下载,这会浪费带宽并导致需要渲染新图像时出现延迟。
你可以在这里测试代码:https : //codepen.io/Devabc/pen/PowjqwZ
//This code is using imgur images to demonstrate.
class Page extends React.Component {
state = {
pageNr: 1,
imagesEnabled: true
};
onLinkClick = event => {
const number = event.target.dataset.value;
console.log("Number: " + number);
this.setState({pageNr: number});
};
onButtonClick = event => {
console.log("toggling images");
this.setState(prevState => {
return {imagesEnabled: ! prevState.imagesEnabled};
});
};
render() {
const links = _.range(0, 5).map(number => {
return (
<a href="#" data-value={number} onClick={this.onLinkClick}>
{number}
</a>
);
});
const pageNr = this.state.pageNr;
const imgStart = pageNr * 100;
const imgEnd = imgStart + 100;
const images = this.state.imagesEnabled
? <ImagesPanel imgStart={imgStart} imgEnd={imgEnd} />
: null;
return (
<div>
<h1>Page {this.state.pageNr}</h1>
<div>Page links: {links}</div>
<div><button onClick={this.onButtonClick}>{this.state.imagesEnabled ? "disable images" : "enable images"}</button></div>
<div>Images:</div>
<div>{images}</div>
</div>
);
}
}
function ImagesPanel(props) {
const images = _.range(props.imgStart, props.imgEnd).map(number => {
return (
<Image imageNr={number} />
);
});
return images;
}
function imageUrl(imageNr) {
const hash = imgurHashes[imageNr];
return "https://i.imgur.com/" + hash + ".jpg";
}
function Image(props) {
const url = imageUrl(props.imageNr);
return <img class="myImage" src={url} border='1' />
}
const imgurHashes = ["wmk2tcs","jvqH2X4","r3dz09r","yJYRtvI","33bUPXj","cYsggBH","URAl4lS","xBpS7lq","5LMFxjU","kUrFsMB","GZf8FnO","Er2lmge","22CbMOq","vJcKGb3","U9ALJof","LxfGswQ","YzyyFHI","vin2W11","c0PQRSY","b6b2qva","6UmvLGc","oTtDO7S","LGoOzDl","XD9o83i","dMUi3dj","XpvMqXC","9JYf6o2","8IBe95g","X26sUn3","qb7Taz9","lWd5TCZ","2UKHpPZ","PMmglpV","pZ5ukGv","ymEZize","nYURuNZ","1SToTrZ","GZHTkpe","NH0qm8I","mZRTNyB","FBAoint","nJWbHb9","BI9zvXf","OeT5kWf","JZ1WPQA","6ZK3S2x","z6M8ryn","3yMODr2","bUoicZu","p3ReIJA","dybF5Sh","DH5ZBEH","fMEbpy5","UyMkbSp","EKXikAy","YG3aJm9","4JWIQhV","lgsvM63","A0MepAi","957yfQF","iNkwwNi","aaJpoxO","Vxy5RgX","jZxV1kQ","JuTUNdL","WY4e0cg","xmgTP7A","O35FJpg","VA3fFhv","oGZVPYQ","X9PRsWA","wSYxWzX","xntVddT","rDn0s52","vQPT1rH","GmlqCZt","zntCiSZ","SoEHjHB","bTFF7HW","QjJRzmx","DZxjoKZ","XdIYgsc","aBZChfb","rAIuEHZ","zt9EJD9","vaEJQA1","9c5pjUL","VXW3Ubz","315aFBb","klp7nh9","fsZktFx","x1XmXYX","8HaInVG","6jJOtkE","9aElwYX","R4dDTw7","9hgY0kI","SW8M5sw","R9jcSrP","dlSSb0P","bhxZCLX","mogQ5tz","oHxiJye","PYyOOm3","Ns89wvi","2uWIFDx","nXN5uhB","UMQn1yZ","JCAEJ3a","VTlkiOu","5JyWm3p","RVE8GoO","XVje7aY","C6qr30z","e54jc67","0X4cRbP","qZaU4lT","WUPHAQD","iILnFAb","oCsxMga","hQyN9oX","GQYDzhE","RcTO075","JlTn7jd","0jJHUWZ","iKp7JGx","YaQeN45","Ot5nFpM","8CeXfPJ","m3cQQye","JYXQaj7","pzPglwg","B4a34uo","3dHvLPv","FEn3aTc","coi9Jpy","GU5ih0m","CtnHd4Y","hbOFsRS","xNW9ED4","avCP3XP","mcbapy0","r9E6DqQ","JDjounb","xHGiHZR","LPN7uSK","QwwPGKE","OGTUcVh","OLxQHfA","Mg0QT9y","0ia7Ca3","LKKHYJn","W8nyx6Q","FjLCYY4","5YEYOe9","vLQHljC","jyL5CS9","oCuKxVQ","L2IyiSA","ffkgeN2","FF7bKmo","JpWF0LA","72kPNNw","tmdNh8K","7PBAKy4","EXMlyuO","p5ZkX5b","Iilf92H","fQbVFiU","wj1csk6","rP14xLY","1iQM4nW","XMq6P6Y","dTRijsS","B3Sz2J8","UkSipp2","eAiZQlr","JJkbcAs","sfA0TJ4","foex9pW","IoCvWfI","5yAxTX7","H6EAfeQ","k8d637d","yIQVrZH","bQdJFx5","CiPGw2A","YZLiutP","BQlEKfd","0W032dR","r4PWPJF","mGBYym5","BC7cuX5","TcoRdCZ","KsCfq9T","KaoAUfC","RdDFY7O","HFhBXSb","kOkYQua","mmT60dj","vIqZffx","r7T9b7N","y1Qtgh9","GFwT6Zc","nWUqQQ3","OZMUUjP","x4ocIKv","wy13lyN","fTj8Om8","0AgyD0C","prWbjvJ","MNJdsJk","brS1te1","4xP3P3i","IlcxIrq","bX7vGyi","U4mhrTE","FVMGYVw","zRFW4oG","jpbvgCe","ZJJEUHu","aU5C2XY","jfFsb9b","WfkChky","qNKDvPo","fhgzlkL","4uEHjGz","cRPiOZz","OzA6TSu","iEhVkeo","tXCZZQY","7DBLToo","9rrTZl5","FWO4ugI","kel6MJM","md4dsMN","kvfKaxR","JMyKehy","3jlMpQk","r1DSqFd","ywuONdJ","eCfhJ5y","vDmQ7Sm","BS6VgDy","wwa7mX9","4E1aIuK","D0zqMuZ","ovehv4U","s3yrw4S","GXm3DCm","gugRkdk","6H2WA7e","M6qdVzv","59aJXiY","As2zA50","wyc2LnT","IuhXtFA","l3V5mZS","QoUlc4T","L7XNlhe","cNk7D2j","MPF5iQY","wRjmFCp","7PZSZrU","EpSMAzy","hLaPhDJ","bS3dM0R","SOCUNXb","Q7BIVld","3Yrg85R","cX4KejE","IQbsyz1","i1qMSgy","K5cU3Qb","NeeB0tr","YHZIvUY","I4BmxjZ","BtThGp0","qWPlax5","pDFqfpR","SdET6fw","9EpcwDb","6nDPyRo","B4X4pYN","mkYU9mK","P6A7I0V","Gwb8Wtr","kSkjNsR","vlEb6D8","Gznsyvk","Vpm3QdO","949USnU","8HyKw0G","4tJmhAP","GLXxX89","X4GGU1t","wRVqclU","rEFHH4Q","vLmSGxD","gkFI4kz","kQASxFm","Cq5brtp","KmWYkSo","2IjiGnN","laGj46X","mgYgH2n","I2iwVFj","oFHxy9R","8VWomE0","y1kV08m","PqXAGBv","MNoiTk8","qEEpz2x","e4ipNRw","CfVVnG8","hHnuzRP","YthPF8u","YBigt6A","tQI8AFu","2K0TnUO","GYReGhp","F2XQStI","7j7145H","BVkgYv1","4hfVk8z","faw1ajs","27H4ogL","0a9ZQ2T","041BIAs","dilQYiq","P1e5AXA","5Tia8aA","PFNJRet","t1Nhl5f","UpfH1sp","H2zXF5f","HLdaLwV","30O8VSP","KsaM1XE","jAhqN6P","Yoi2ylE","wkrg47U","ePmLF64","KLSJPrd","aUdvQ0a","VcqZhpH","zEqDYjX","WXLTAbp","shny07g","UqlXlR5","Bpw7KnV","YeP3Zhe","C5NSYDy","Y6GzbOA","6FxTImw","6PXXJmd","FnVsEu0","Ll2zJnC","JvNbUcB","nEOXggf","t28tvPa","m2qG0pl","KjkkYG5","kCcUVrD","g2G823J","ZyD1f4Z","P3SfyR5","QsA5vHF","DpSxArz","dKt3T4S","w0GfNCC","kvyacI9","Gqdr7qd","KlHHMzZ","VVZ7HVw","hFG5mwe","D4S9tPV","SMVSpk3","MYzi6pi","BzQeber","v7E7VCw","a03HdC6","KSAiRwR","7WkzcMx","z8iVQZP","qCDNLpI","TUerfpq","X08dKd5","qkmDrys","k0MjIxD","vIgbAlY","15TeGJg","j7vx4tU","DNvqPee","2jEQHaF","5Q1M9HL","EFninXx","0VttnZV","XKgdZGL","fDSOKh8","1i5Fhk1","wmUU0tL","O7SVAVF","WMoTmty","UUVTKaF","n9EPI8R","QqnEITA","lao3U57","ITabVKK","ph97wz5","bFfdCGt","9KWJKs3","aKKQd6o","jxzaSfj","6Gv8gBL","iDS0A1T","bTAS7ej","5FvLcFu","GtIFmNQ","kJAU7gn","UZCPmpz","68yuNFU","TuO5PNi","lMV0piH","taKCu3Y","PmNa3M4","Z6gErEZ","5qrVmOD","N5yxt2l","LhrvwLr","QhBn6p8","2kpPEe8","dnxlCK3","GMDnQ32","3qH62l5","Jy6aHR2","2tIZHcB","w0zzrUJ","aSh1mwr","fwCCSBI","k5osQCu","byHHnMX","Uu9Dq9I","K9sC2OO","CsFf1Kz","G28GqCu","OOPc79G","be5NrVR","C5XAmr2","rDNSwSj","AI4BrBq","hGwueuh","EpG6zfG","QORwSKm","sWDMpiD","U2QfeTp","kUqUudt","PGMbcrN","bEaFtGN","KPrPXxO","4iFaBhm","fDcFhWG","P1M2Ld5","aPAlbHH","8ye6kdq","ztVBpFQ","SVL8ujT","5CwT2Og","nIqakeV","SM3Jcoz","QdAk2M4","zpLnMrH","fglMOex","ynj6fe7","YG1DOZh","aJ50pkC","SbvVCaf","azLfxiY","gdw8DHE","1U00sfi","p3zgLIS","h9cTNnw","Z1tt3RC","HHnBLCI","hmkeUl1","aMKRR0h","6MteQjh","PMZzXiM","v2uh5Mk","QEDz82m","70LhmSw","KEGMEbg","tlG769G","gyoNASp","AUnDdta","z1TZP9m","nVmmkCH","IIDRcHT","8m1Go3S","LsscGjy"];
ReactDOM.render(
<Page />,
document.getElementById('root')
);
Run Code Online (Sandbox Code Playgroud)
下面的屏幕截图显示了浏览器中待处理图像的列表,即使此时不应渲染任何图像,因为应该渲染图像的 React 组件已经卸载/删除。
该问题不是由 React 引起的。我不确定这个问题该归咎于谁,可能是文档对象模型标准、HTML 或实现它的浏览器。问题是,一旦图像附加到 DOM(当浏览器开始渲染 HTML 页面时),浏览器就会开始下载它,即使该图像稍后从 DOM 中删除也是如此。
然而,有多种解决方案可以解决这个问题。
该src属性在 HTML 元素中是强制性的img,但将其设置为空字符串(清除)会导致取消图像的下载。(这可能不适用于所有浏览器。)
此解决方案如下所述:如何取消加载图像并在此处演示https://jsbin.com/zakeqaseru/1/edit?output和此处https://jsfiddle.net/nw34gLgt/ (使用浏览器开发人员工具监控图片下载是否被取消。)
可以使用setAttribute()将其src更改为空字符串。将其设置为与将其设置为 string 具有相同的效果,后者也可以工作,但不太干净。删除该属性在大多数浏览器上不起作用。null"null"src
此解决方案是否有效可能因浏览器而异。较旧的浏览器可能会导致在删除时请求网页本身src,如下所述:https://gtmetrix.com/avoid-empty-src-or-href.html
这可能会对浏览器造成很大的性能影响和网络服务器。
如果浏览器无法处理此问题,类似的解决方案是background-image在 HTML 元素上使用该属性,例如 adiv而不是img.
这个 src-clearing 解决方案是在React-Image中实现的:
https: //github.com/mbrevda/react-image/pull/996。为了简洁起见,此处删除了反应图像的实现细节(基本上,有一个承诺的版本Image()接收 AbortController)
signal.addEventListener('abort', () => {
i.src = ''
resolve()
})
Run Code Online (Sandbox Code Playgroud)
React 中的解决方案是这样的:
class Img extends React.Component {
constructor(props) {
super(props);
this.imgRef = React.createRef();
}
componentWillUnmount() {
try {
this.imgRef.current.src = '';
delete this.imgRef.current.src;
} catch (e) {}
}
render() {
return (
<img {...this.props} ref={this.imgRef} />
);
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以像这样使用它:
<Img src="...some image url...." />
Run Code Online (Sandbox Code Playgroud)
通过在编程条件下设置该src属性,您可以确保仅在需要时加载图像。该解决方案还可以与其他解决方案结合使用,以确保在卸载关联的 React 元素时取消下载的图像。
data-src此方法中经常使用(自定义数据)属性,以便在需要渲染图像时复制其值src。
此解决方案仍可能下载未安装的图像。
该解决方案自 Chrome 76(2019 年 7 月?)以来就存在。Chrome 有一个loading针对图像和 iframe 的属性,可以将其设置为"lazy"推迟资源的下载,直到达到距视口的计算距离为止。
loading许多其他浏览器不支持该属性。
有关更多信息,请参阅:
此解决方案仍可能下载未安装的图像。
| 归档时间: |
|
| 查看次数: |
1245 次 |
| 最近记录: |