使用供应商前缀进行编程的最佳实践






4.50/5 (2投票s)
本文介绍了一种模式,我们的团队使用它来使使用供应商前缀进行开发时的工作变得更加轻松。
供应商前缀使 Web 开发人员能够在新的标准达到候选推荐阶段之前进行实验。 我之前写过这些前缀也是浏览器供应商用来处理实现和规范之间的时序冲突的一种机制。 在为我们的IE Test Drive站点和各种演示文稿构建新功能的演示时,IE 团队的许多人都在大量使用供应商前缀。
本文介绍了一种模式,我们的团队使用它来使使用供应商前缀进行开发时的工作变得更加轻松。 我们想与您分享它,并听取您对此方法或您认为的最佳实践的任何其他想法。
容易出错的代码
当使用脚本访问带有供应商前缀的 CSS 属性时,很容易最终得到如下所示的代码
var elm = document.getElementById("myElement");
elm.style.msTransitionProperty = "all";
elm.style.msTransitionDuration = "3s";
elm.style.msTransitionDelay = "0s";
elm.style.webkitTransitionProperty = "all";
elm.style.webkitTransitionDuration = "3s";
elm.style.webkitTransitionDelay = "0s";
elm.style.MozTransitionProperty = "all";
elm.style.MozTransitionDuration = "3s";
elm.style.MozTransitionDelay = "0s";
elm.style.OTransitionProperty = "all";
elm.style.OTransitionDuration = "3s";
elm.style.OTransitionDelay = "0s";
虽然功能正常,但它很臃肿、丑陋且容易出错。
将供应商前缀的属性合并为一个名称
更好的模式是定义一个方法,该方法循环浏览属性名称列表,并返回第一个支持的属性;如果浏览器不支持任何属性,则返回 null。
function FirstSupportedPropertyName(prefixedPropertyNames) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedPropertyNames.length; ++i) {
if (typeof tempDiv.style[prefixedPropertyNames[i]] != 'undefined')
return prefixedPropertyNames[i];
}
return null;
}
然后,我们为我们使用的每个带有供应商前缀的属性初始化一个变量,并按我们希望使用的顺序传递一个可能的属性数组。
var transformName = FirstSupportedPropertyName(["transform", "msTransform",
"MozTransform", "WebkitTransform", "OTransform"]);
var backfaceVisibilityName = FirstSupportedPropertyName(["backfaceVisibility",
"msBackfaceVisibility", "MozBackfaceVisibility", "WebkitBackfaceVisibility",
"OBackfaceVisibility"]);
var transitionName = FirstSupportedPropertyName(["transition", "msTransition",
"MozTransition", "WebkitTransition", "OTransition"]);
var animationName = FirstSupportedPropertyName(["animation", "msAnimation",
"MozAnimation", "WebkitAnimation", "OAnimation"]);
var gridName = FirstSupportedPropertyName(["gridRow", "msGridRow", "MozGridRow",
"WebkitGridRow", "OGridRow"]);
var regionsName = FirstSupportedPropertyName(["flowFrom", "msFlowFrom", "MozFlowFrom",
"WebkitFlowFrom", "OFlowFrom"]);
var hyphensName = FirstSupportedPropertyName(["hyphens", "msHyphens", "MozHyphens",
"WebkitHyphens", "OHyphens"]);
var columnName = FirstSupportedPropertyName(["columnCount", "msColumnCount",
"MozColumnCount", "WebkitColumnCount", "OColumnCount"]);
然后,站点中使用这些属性的代码将变成这样
var elm = document.getElementById("myElement");
if (transitionName) {
elm.style[transitionName + "Property"] = "all";
elm.style[transitionName + "Duration"] = "3s";
elm.style[transitionName + "Delay"] = "0s";
}
else {
// fallback for browsers without CSS3 transitions
}
请注意通过在 FirstSupportedPropertyName 中返回 null 实现的简单特性检测。
当 CSS属性具有供应商前缀时,该模式也适用。 对于 CSS值(例如,linear-gradient)具有供应商前缀的情况,您可以使用略有不同的模式
function FirstSupportedFunctionName(property, prefixedFunctionNames, argString) {
var tempDiv = document.createElement("div");
for (var i = 0; i < prefixedFunctionNames.length; ++i) {
tempDiv.style[property] = prefixedFunctionNames[i] + argString;
if (tempDiv.style[property] != "")
return prefixedFunctionNames[i];
}
return null;
}
var linearGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-linear-gradient",
"-moz-linear-gradient", "-webkit-linear-gradient", "-o-linear-gradient"], "(top, black, white)");
var radialGradientName = FirstSupportedFunctionName("backgroundImage", ["-ms-radial-gradient",
"-moz-radial-gradient", "-webkit-radial-gradient", "-o-radial-gradient"],
"(50% 50%, circle cover, black, white)");
测试使用供应商前缀属性的站点
一个常见的问题是,如果某些浏览器尚未支持该属性,或者如果没有浏览器支持没有前缀的基于标准的属性,应该使用哪些属性名称。 有几种方法,每种方法都有优点
- 始终包含所有预期的名称,即使它们尚未在发布的浏览器中工作。这种方法的好处是,随着浏览器添加对其供应商前缀的支持或添加对非前缀属性的支持,您的站点将“正常工作”而无需更改。 风险在于,站点将自动拾取您从未测试过的行为。 供应商前缀表明该行为尚未最终确定,并且所有带有前缀的属性和非前缀属性的行为可能不相同,因此随着浏览器添加支持,您的站点可能“不能正常工作。”
- 仅包含您可以测试的属性名称。好处是,即使浏览器添加对新属性的支持,您的站点也会像您第一次编写它时一样运行。 风险在于,您不必要地降低了功能。 对于示例或演示站点,人们可能会将其解释为浏览器根本没有该功能。
您需要确定适合您站点的正确路径。 在我们的大多数演示中,我们希望在任何支持它的浏览器中展示新的 Web 平台功能。 并且由于这些演示中的小错误不会给用户带来大问题,因此我们通常选择选项 #1。 另一方面,如果您有一个生产站点,其中行为的更改会对您的业务造成问题,则您可以选择更规避风险的路径。
无论您选择哪种路径,不变的是测试。 使用供应商前缀的属性时,您正在利用早期、通常不稳定的功能,即使在浏览器首次引入对属性的支持之后,这些功能也可能会发生更改,因此至关重要的是,每次浏览器更新时都要进行测试,以确保您的站点按预期运行。