8

我一直在做一个使用 jQuery.clone()方法的小项目。这样做的陷阱是在具有唯一标识符的 HTML 上使用它。因此,我继续实施getComputedStyle以查找原始唯一元素的样式属性,以便将其复制到克隆并在之后给它一个新的 id(是的,它会产生性能问题,但它是实验性的)。

根据 jQuery 规范,在克隆之后但在附加之前执行此操作将使操作发生在 DOM 之外(因此不会发生 id 'violation')。但是,当我在克隆对象后尝试查找元素的样式属性时,我注意到跨浏览器的一些奇怪行为。在此之前,所有浏览器都返回相同的值,但在被克隆之后:

  • Firefox - 无忧无虑,有趣的是,克隆的计算样式是实际的 CSS 值而不是计算数据(以像素为单位)。

  • IE - 似乎有效,但价值不一定正确。

  • Chrome - 不计算。这是一个例子:

http://codepen.io/anon/pen/zxqmNK?editors=011

var elements = [];
var objects = [];

$('body').find('[id]').each(function() {
    elements.push(this);
});

$('body').clone().find('[id]').each(function() {
    objects.push(this);
});

$.each(elements, function(key, element) {
    var current = window.getComputedStyle(element, null).getPropertyValue('width');
    $('#log').append('<p>' + element.id + ': ' + current + '</p>');
});

$('#log').append('</br>');

$.each(objects, function(count, object) {
    var current = window.getComputedStyle(object, null).getPropertyValue('width');
    $('#log').append('<p>' + object.id + ': ' + current + '</p>');
});

有人知道这是一个错误还是以前见过类似的行为?在网络方面没有太多可做的事情(甚至 Stackoverflow 也不行)。提前感谢您的任何见解。

编辑 - 进行了更多测试,看起来 IE 的行为与 Chrome 相同。只是没有返回任何东西,而是将所有内容设置为“自动”。如果通过 using 访问克隆对象的样式,则.css()返回所有值0px(包括背景等属性)。似乎只有 Mozilla 将克隆的对象视为已应用任何样式。

4

1 回答 1

1

第一种方法

以下是我最初解决它的方法......以不同的方式对待 Mozilla 很诱人,但这需要浏览器嗅探,因此我们将解决无法访问克隆样式的问题。

创建两个具有唯一标识符的对象数组 - 第一个将包含从中复制样式的元素,第二个将包含样式将被转移到的克隆元素:

var individual = [], singular = [];

$('.target').find('[id]').each(function() {

    individual.push(this);
})
.end().clone().find('[id]').each(function() {

    singular.push(this);
});

现在属性和它们的值从存储在 DOM 中的对象数组复制到克隆 - 之后当前标识符的名称更改为唯一的名称:

$.each(individual, function(key) {

    var tag = this.id,
    styles = window.getComputedStyle(this, null),
    element = singular[key];

    $.each(styles, function() {

        var value = styles.getPropertyValue(this);
        $(element).css(this, value);
    });

    $(element).attr('id', tag + '-cloned');
});

在此之后插入克隆的项目,因此不存在双重标识符。请注意,这可能会产生很多样式属性(例如,Firefox 中每个对象大约 220 个)。

演示

var individual = [], singular = [];

$('.target').find('[id]').each(function() {

    individual.push(this);
})
.end().clone().find('[id]').each(function() {

    singular.push(this);
})
.end().queue(function() {

    transFigure();
    $(this).dequeue();
})
.appendTo('body');

function transFigure() {

$.each(individual, function(key) {

    var tag = this.id,
    styles = window.getComputedStyle(this, null),
    element = singular[key];

    $.each(styles, function() {

        var value = styles.getPropertyValue(this);
        $(element).css(this, value);
    });

    $(element).attr('id', tag + '-cloned');
});
}

++++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++++++++

第二种方法

即使上面的工作正常,它也不是很有效,页面调整大小的值可能会开始不同。因此,在遇到并在 JavaScript 的cssRules. 有了这个,您实际上可以直接访问所有样式表!

下面是一个试图解释该过程的笔,但归结为.test将克隆中的唯一标识符cssText与样式表中的唯一标识符进行匹配(使用 )。然后更改id并将其存储在数组中,以便稍后将其插入/添加到样式表本身。

除了更有效的方法(不传输所有默认值)之外,为所有浏览器复制实际 CSS 而不是计算值。并且也可以包括任何衍生物,例如img,和这样的。p它甚至以这种方式复制@rules并保持响应性完好无损。

它的本质:

var singular = [], rules = [];

$('#target').clone().find('[id]').each(function() {

    singular.push(this);
});

var sheet = document.styleSheets[0],
styles = sheet.cssRules;

$.each(singular, function() {

    var selector = '#' + this.id,
    pattern = new RegExp(selector + '(:| |,)');

    $.each(styles, function() {

        var string = this.cssText;

        if (pattern.test(string)) {
        var rule = string.replace(selector, selector + '-duplicate');
        rules.push(rule);
        }
    });
});

$.each(rules, function() {

    var index = styles.length;
    sheet.insertRule(this, index);
});

在此之后,可以将克隆插入到 DOM 中,并应用所有唯一标识符和完整样式。请注意,在上面的示例中,实际上并没有这样做以使代码在使用cssRules. 图像已预先使用不同的标记放入标记中id- 将匹配复制的样式规则。

于 2014-12-16T21:11:21.567 回答