【问题标题】:How would I give CSS property to a cloned element as Javascript?我如何将 CSS 属性作为 Javascript 赋予克隆元素?
【发布时间】:2019-09-10 22:14:13
【问题描述】:

我正在尝试将translateX() 属性赋予被称为this.firstClone 作为javascript 的克隆元素。问题是this.firstClone 没有引用克隆的元素,即使值本身在代码中进行了克隆。

constructor($el) {
  this.$el = $el; // 0
  this.myCards = this.$el.find('a'); // 1
  this.myCount = 1; // 2
  this.myLength = this.myCards.length; // 3
  this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned')); // 4 this makes the clone.
  this.lastClone = this.myCards.last().after(this.myCards.first().clone().addClass('cloned'));
}

在上面,this.firstClone 将最后一个图像克隆为集合中的第一个图像。而且当我删除它时,克隆的元素就消失了。制作、设置或删除克隆图像没有问题。

但是当我 console.log 它时,它指的是 DOM 中具有 translateX(1%) 的第二个元素。当我这样做时,该属性也将设置为第二个元素:this.firstClone.style.transform = "translateX(" + (-1) + "%)";

这是 javascript 的故障吗?还是我只是误解了.first().clone() 方法?

我的目标是为每个克隆的元素赋予 css 属性,但我卡在这里没有任何线索。

完整代码:

'use strict';
(function ($, window, undefined) {
  $.fn.cardSlider = function(options) {
    return this.each(function() {
      const $el = $(this);
      var thatCards = new Card($el, options);
          thatCards.scrolling($el);
    })
  }
  class Card {
    constructor($el) {
      this.$el = $el; // 0
      this.myCards = this.$el.find('a'); // 1
      this.myCount = 1; // 2
      this.myLength = this.myCards.length; // 3
      this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned')); // 4 this makes the clone.
      this.lastClone = this.myCards.last().after(this.myCards.first().clone().addClass('cloned'));
    }
    scrolling($el) {
      console.log(this.firstClone); 
      this.firstClone.style.transform = "translateX(" + (-1) + "%)"; // Browser fires an error. Cannot set property 'transform' of undefined
      this.firstClone.css({
        paddingBottom: 200 + 'px'
      }); // An example for proving that the css property doesn't refer to the real clone.
      for (var i = 0; i < this.myLength; i++) {
        this.myCards[i].style.transform = "translateX(" + Math.pow(2, i) + "%)";
      }
    }
  }
}(jQuery));
$('.outer').cardSlider();
.outer {
  margin: 0 auto;
  width: 70%;
  overflow: hidden;

}
.film {
  display: flex;
  flex-flow: row;
  justify-content: center;
  left: 90%;
}
.images {
  position: relative;
  display: block;
  width: 90%;
  flex-shrink: 0;
  padding-bottom: 74%;
  background-color: blue;
}

.images:first-child, .images:last-child {
  background-color: orange;
  opacity: .4;
}
    <div class="outer">
      <div class="film">
        <a class="images" href="#" draggable="false"></a>
        <a class="images" href="#" draggable="false"></a>
        <a class="images" href="#" draggable="false"></a>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

*我在 Codepen 和这里测试了这段代码,但都没有工作。您可能必须制作新文件来测试它。

【问题讨论】:

  • 你有什么理由这样构造你的代码吗?使用init 数组而不是单个变量?我觉得很难读。
  • @TheBlackIPs 我想将其分组并分开以使其看起来更好更清晰,但现在似乎不再。
  • 没关系,我错了。 myCards.first().before() 不会修改 myCards
  • 如果您想将它们分组,请使用对象。然后你可以写this.init.holderthis.init.cards等。这比this.init[1]这样的幻数更容易理解。
  • @l3lue 您用这种分组策略引入的问题被称为“神奇值”。当您谈论init[4] 时,没有人知道您的意思。数字 4 是任意的。你应该给你的变量起一个不言自明的名字(你在声明它们时已经这样做了)。

标签: javascript jquery html css class


【解决方案1】:

您的代码非常混乱,但我认为您遇到的一个问题是您将错误的元素分配给firstClonelastClone。您可能希望这些变量成为对新克隆的引用,但这不是您的代码所做的。

让我们看看这一行:

this.firstClone = this.myCards.first().before(this.myCards.last().clone().addClass('cloned'));

  • 首先,克隆最后一张卡片并添加类cloned (this.myCards.last().clone().addClass('cloned'))

  • 然后,您将该克隆传递给第一张卡 (this.myCards.first().before(...)) 的函数 before

  • 最后,你将函数before返回的任何东西赋值给变量this.firstClone

问题在于表达式a.before(b)a 之前插入b,然后返回a。但是,您要保存的是对 b 的引用,而不是 a

您必须改用函数insertBefore。它与before 完全相同,但反过来:b.insertBefore(a) 也在a 之前插入b,但这返回b

(在这里查看区别:https://www.mkyong.com/jquery/jquery-before-and-insertbefore-example/

所以我们看到的那一行应该是:

this.firstClone = this.myCards.last().clone().addClass('cloned').insertBefore(this.myCards.first());

这样,您的变量 this.firstClone 包含对新创建的克隆的引用,而不是(以前的)第一个元素。之后的行也是如此:

this.lastClone = this.myCards.first().clone().addClass('cloned').insertAfter(this.myCards.last());

我希望这能解决你的问题。

在上下文中使用:

'use strict';
(function ($, window, undefined) {
  $.fn.cardSlider = function(options) {
    return this.each(function() {
      const $el = $(this);
      var thatCards = new Card($el, options);
          thatCards.scrolling($el);
    })
  }
  class Card {
    constructor($el) {
      this.$el = $el; // 0
      this.myCards = this.$el.find('a'); // 1
      this.myCount = 1; // 2
      this.myLength = this.myCards.length; // 3
      this.firstClone = this.myCards.last().clone().addClass('cloned').insertBefore(this.myCards.first()); // 4 this makes the clone.
      this.lastClone = this.myCards.first().clone().addClass('cloned').insertAfter(this.myCards.last());
    }
    scrolling($el) {
      console.log(this.myCards[1]); // Both refers the same element
      this.firstClone.css({
        paddingBottom: 200 + 'px'
      });
      for (var i = 0; i < this.myLength; i++) {
        this.myCards[i].style.transform = "translateX(" + Math.pow(2, i) + "%)";
      }
    }
  }
}(jQuery));
$('.outer').cardSlider();
.outer {
  margin: 0 auto;
  width: 70%;
  overflow: hidden;

}
.film {
  display: flex;
  flex-flow: row;
  justify-content: center;
  left: 90%;
}
.images {
  position: relative;
  display: block;
  width: 90%;
  flex-shrink: 0;
  padding-bottom: 74%;
  background-color: blue;
}

.images:first-child, .images:last-child {
  background-color: orange;
  opacity: .4;
}
    <div class="outer">
      <div class="film">
        <a class="images" href="#" draggable="false"></a>
        <a class="images" href="#" draggable="false"></a>
        <a class="images" href="#" draggable="false"></a>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

【讨论】:

    【解决方案2】:

    问题在于this.firstClone 是一个jQuery 对象,而不是一个DOM 元素。但是style 是一个 DOM 属性。在 jQuery 中,你使用 .css() 函数来添加样式,所以它应该是:

    this.firstClone.css("transform", "translateX(-1%)");
    

    或者您可以将其作为以下内容的一部分:

      this.firstClone.css({
        paddingBottom: 200 + 'px',
        transform: "translateX(-1%)"
      });
    

    您的代码在 for 循环中工作,因为当您索引 jQuery 集合时,它会返回相应的 DOM 元素(要获取 jQuery 对象,您使用 .eq(i))。所以你也可以把上面写成:

    this.firstClone[0].style.transform = "translateX(-1%)";
    

    【讨论】:

    • 在我问这个问题之前我已经尝试过这些方法,但没有一个不起作用。不过还是谢谢你的回答。
    • 我看到另一个问题解决了另一个问题,即您没有按预期设置 firstClonelastClone
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-21
    • 2015-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-14
    相关资源
    最近更新 更多