gpt4 book ai didi

javascript - 如何使用不完整的 CSS 处理 Chrome 渲染动态添加的元素

转载 作者:行者123 更新时间:2023-11-28 05:39:37 27 4
gpt4 key购买 nike

我在 <A> 上设置类名元素(存在于原始 HTML 中),在使用 $.get 加载 SVG 元素时会在其下附加 SVG 元素。 SVG 元素具有不适用于 Chrome 的样式,除非我执行强制重新渲染的操作。例如,在 Developer View 中选中/取消选中样式属性的框,或者使用 Brackets IDE 并修改 CSS(这会导致 Brackets 撕裂我们所有的 CSS 并为每个键入的字符替换它)。

当我以至少 80 毫秒的间隔将类添加代码放在 setTimeout 上时,它可以工作。在 IE11、Edge、Safari 和 Firefox 中,它可以在没有这种解决方法的情况下工作。根据 Network pane,CSS 在脚本之前加载(也尝试将它们放在尾部而不是头部),这是 Chrome 没有正确管理渲染序列的问题(很可能试图使用最小的重新渲染算法太聪明了对我不利)。

我该如何正确处理?

这是一个 working version ,因为我硬编码了通常使用 jQuery 应用的样式(在生产中我会呈现这个服务器端,但它不是一个令人满意的解决方案)。

这是 broken version

您可以验证在 navigation.js 中移动第 55-64 行进入 setTimeout将使它工作。

在 Mac OS X 上使用 Chrome 版本 51.0.2704.103(64 位)

编辑:根据要求编辑相关的 HTML 和 JS,完整图片请参见上面的链接。

index.htm

<html>
<head>
<link rel="stylesheet" type="text/css" href="styles.css"></link>
<script type="text/javascript" src="scripts/jquery.min.js"></script>
<script type="text/javascript" src="scripts/navigation.js"></script>
</head>

<body>
<header>
<div id="logo" class="icon" data-src="images/logo.svg"></div>

<nav data-src="images/navigation.svg">
<a href="index.htm">news</a>
<a href="articles.htm">articles</a>
<a href="projects.htm">projects</a>
<a href="about.htm">about</a>
</nav>

navigation.js

$(document).ready(function() {
loadNavigationButtons();
});

function loadNavigationButtons() {
var buttonParts =
[
"matte",
"border",
"highlight",
"icon",
"selection"
];

return $.Deferred(function(callback) {
$("nav a").each(function(index) {
var navigationIconSet = $(this)
.closest("nav[data-src]")
.attr("data-src");

var buttonName = $(this).text();
$(this).text("");

if (document.URL.indexOf($(this).attr("href")) != -1) {
// Add navigation-selected class to <a>
$(this).addClass("navigation-selected");
} else {
// Add navigation-unselected class to <a>
$(this).addClass("navigation-unselected");
}

for (var partIndex in buttonParts) {
loadIcon(
// Prepend to this element.
$(this),

// Attempt to find a part for this specific button.
navigationIconSet + "#" + buttonName + "-" + buttonParts[partIndex],

// Fallback to generic part name.
navigationIconSet + "#" + buttonParts[partIndex],

// Class to apply.
"navigation navigation-" + buttonParts[partIndex]

// Not passing callback parameter
);
}

// Append button text.
$("<div></div>")
.text(buttonName)
.addClass("navigation navigation-text")
.appendTo($(this));
});

callback.resolve();
});
}

function loadIcon($container, iconUri, fallbackUri, classToApply, callbackParameter) {
if (~iconUri.indexOf("#")) {
var sourceComponents = iconUri.split("#");
var fallbackComponents;

if (fallbackUri) {
fallbackComponents = fallbackUri.split("#");

// Support fallback only within the same icon set.
if (sourceComponents[0] != fallbackComponents[0]) {
return $.Deferred(function(callback) {
callback.reject($container, null, callbackParameter)
});
}
} else {
fallbackComponents = [null, null];
}

return loadIconFromDefinition(
$container,
sourceComponents[0],
sourceComponents[1],
fallbackComponents[1],
classToApply,
callbackParameter);
} else {
return loadIconFromFile(
$container, iconUri, classToApply, callbackParameter);
}
}

function loadIconFromFile($container, iconUri, classToApply, callbackParameter) {
return $.Deferred(function(callback) {
$.get(iconUri).done(function(icon) {
callback.resolve(
$("svg", icon).prependTo($container),
null,
callbackParameter);
});
});
}

function loadIconDefinition(definitionUri) {
if (!loadIconDefinition.loaded) {
loadIconDefinition.loaded = {};
}

if (loadIconDefinition.loaded[definitionUri]) {
return loadIconDefinition.loaded[definitionUri];
}

loadIconDefinition.loaded[definitionUri] =
$.Deferred(function(callback) {
loadIconFromFile($("body"), definitionUri)
.then(function($loaded) {
// Hide definition after it's loaded.
$loaded.get(0).setAttributeNS(null, "style", "display:none");
callback.resolve($loaded);
});
});

return loadIconDefinition.loaded[definitionUri];
}

function loadIconFromDefinition(
$container, definitionUri, groupName, fallbackGroupName, classToApply, callbackParameter) {
return $.Deferred(function(callback) {
loadIconDefinition(definitionUri).then(function($loaded) {
if (fallbackGroupName &&
!$loaded.find("#" + groupName).length) {
groupName = fallbackGroupName;
}
callback.resolve(
$("<svg class=\"" + classToApply + "\"><use xlink:href='#" + groupName + "'></use></svg>")
.prependTo($container),
$loaded,
callbackParameter);
});
});
}

最佳答案

感觉这个问题在炼狱里度过了足够的时间。

建议的解决方法:

  • 继续动态添加子元素,但始终在服务器端设置父元素类。在 ASP.net 的情况下,使用 Razor 表达式为有问题的父元素呈现简短的 HTML,并且在浏览器获取页面之前已经设置了类属性。这是我选择的解决方法。
  • 隐藏有问题的元素,直到经过足够长的延迟的 setTimeout,这会设置所有必要的类并取消隐藏元素以减少闪烁。可以通过在“对话框”中使用加载进度条来进一步平滑用户体验,该进度条会使页面的其余部分变暗并继续淡入。

此解决方案未实现:

  • 找到当浏览器处于更新 DOM 元素上的类属性能够触发重新渲染的状态时我们可以 Hook 的事件或 Promise。

杂项:

  • 提交 Chromium bug 来描述这种情况...也许 5 年内它会被修复。

关于javascript - 如何使用不完整的 CSS 处理 Chrome 渲染动态添加的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37983914/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com