代码之家  ›  专栏  ›  技术社区  ›  jsldnppl

Javascript类实例化

  •  1
  • jsldnppl  · 技术社区  · 6 年前

    我创建了一个简单的javascript类来包装 slick carousel .

    实例化此类的多个实例的最佳方法是什么?

    我现在看到了下面的内容,它搜索DOM并创建组件的新类实例(如果找到)。我怀疑我的项目会增长一点,而这个“根”文件可能是因为有点臃肿/混乱。有没有更好的组织方式?

    我将添加额外的类以实现进一步的功能,因此要尽早找到最好的方法。

    主要的js公司

    import Carousel from '../app/assets/javascripts/carousel/Carousel';
    
    var carouselElements = Array.from(document.getElementsByClassName('slick-media'));  
      if (carouselElements) {
        carouselElements.map(function (element) {
          new Carousel(element, true, {xs: 6, md: 6, lg: 6 });
        });
      }
    

    旋转木马js公司

    export default class Carousel {
       constructor(element, variableWidth = false, breakpoint) {
          this.element = element;
          this.variableWidth = variableWidth;
          this.breakpoint = breakpoint
    
          this._init(element);
    
          /* Bind methods */
          this._init = this._init.bind(this);
       }
    
       _init() {
        this._instantiateSlick(this.element);
       }
    
       _instantiateSlick(element) {
        $(element).slick({
          lazyLoad: 'ondemand',
          slidesToScroll: 1,
          adaptiveHeight: true,
          useTransform: true,
          /* Default over lg breakpoint */
          slidesToShow: this.breakpoint.lg,
          /* Allow slick to calculate widths */
          variableWidth: this.variableWidth,
          responsive: [
            {
              breakpoint: 1199,
              settings: {
                slidesToShow: this.breakpoint.lg,
                slidesToScroll: 1,
                infinite: true
              }
            },
            {
              breakpoint: 991,
              settings: {
                slidesToShow: this.breakpoint.md,
                slidesToScroll: 1,
                infinite: true
              }
            },
            {
              breakpoint: 480,
              settings: {
                slidesToShow: this.breakpoint.xs,
                slidesToScroll: 1,
                infinite: true
              }
            }]
        });
       }
    }
    
    3 回复  |  直到 6 年前
        1
  •  2
  •   T.J. Crowder    6 年前

    你已经澄清了你的问题是关于你如何 使用 您的类(例如,中的代码 main.js ):

    这是关于主要的。js文件,以及它实例化多个实例的方式。这种方法是最好的吗?

    有几个问题需要挑:

    1. 您正在使用 map 创建填充的数组 undefined 永远不要使用。如果不使用返回的数组,请不要使用 地图 ; 使用 forEach 任何 several other ways to loop over arrays and array-like structures .

    2. 没有必要 if ; 方法,如 getElementsByClassName 始终返回a NodeList HTMLCollection (取决于方法),即使它是空的。

    此外,在一个大项目中,如果有多个类,这个文件将变得非常不可读,那么它是否可以扩展?

    我看不出有什么理由让它变得不可读。如果你想坚持 getElementsByClassName (因为它可以 令人惊讶的是 快速的请注意,它不存在于像IE8这样的过时浏览器上):

    import Carousel from '../app/assets/javascripts/carousel/Carousel';
    
    const forEach = Function.call.bind(Array.prototype.forEach);
    
    const hookUpClass = className => {
        forEach(document.getElementsByClassName(className), element => {
            new Carousel(element, true, {xs: 6, md: 6, lg: 6 });
        });
    };
    
    hookUpClass('slick-media');
    hookUpClass('another-class');
    hookUpClass('some-further-class');
    

    注意使用 Array.prototype.forEach 为我们做循环,因为它可以在任何类似数组的东西上工作。这将适用于任何现代浏览器和IE9-IE11。

    如果你不介意的话 非常非常非常 少量开销,您可以使用 querySelectorAll (甚至在IE8上也存在),以获得与所有类匹配的列表,而不必单独处理每个类:

    import Carousel from '../app/assets/javascripts/carousel/Carousel';
    
    document.querySelectorAll('.slick-media, .another-class, .some-further-class').forEach(element => {
        new Carousel(element, true, {xs: 6, md: 6, lg: 6 });
    });
    

    我没有使用 大堆原型forEach公司 那是因为 节点列表 有自己的 forEach公司 也有同样的作用。如果需要支持IE9-IE11,则需要polyfill,这很简单:

    if (typeof NodeList !== "undefined" &&
        NodeList.prototype &&
        !NodeList.prototype.forEach) {
        // Surprisingly, the standard `NodeList.prototype.forEach` is enumerable (as well as
        // writable and configurable) so we can just assign rather than using `defineProperty`
        NodeList.prototype.forEach = Array.prototype.forEach;
    }
    

    或者当然,使用 大堆原型forEach公司 相反,正如我们所做的那样 getElementsByClassName 如果你愿意的话。

    在最新的Chrome和Firefox等尖端环境中,您可以做到以下几点:

    import Carousel from '../app/assets/javascripts/carousel/Carousel';
    
    for (const element of document.querySelectorAll('.slick-media, .another-class, .some-further-class')) {
        new Carousel(element, true, {xs: 6, md: 6, lg: 6 });
    }
    

    ...这取决于 节点列表 存在 可迭代的 . 我没有在上面这样做,因为在 节点列表 比填胶更难 forEach公司 不知道您使用的是什么transpiler(如果您使用的是transpiler)。

        2
  •  2
  •   trincot Jakube    6 年前

    在我看来,使用类来实现这一点似乎有些过头了。以后再也不会访问创建的对象,因为不会保留对它们的引用,所以它们的唯一目的似乎是立即执行一个操作:应用 slick 到具有一些预定义配置的元素。建造完成后,它们立即变得无用。

    其次,在以下情况下,为参数使用默认值不是很有用 之后 您仍然有一个被证明是必需的参数。因此,交换 breakpoint variableWidth .

    作为替代方案,我建议为此创建jQuery插件:

    $.fn.simpleSlick = function (breakpoint, variableWidth = false) {
        this.slick({
            lazyLoad: 'ondemand',
            slidesToScroll: 1,
            adaptiveHeight: true,
            useTransform: true,
            /* Default over lg breakpoint */
            slidesToShow: breakpoint.lg,
            /* Allow slick to calculate widths */
            variableWidth,
            responsive: [{
                breakpoint: 1199,
                settings: {
                    slidesToShow: breakpoint.lg,
                    slidesToScroll: 1,
                    infinite: true
                }
            }, {
                breakpoint: 991,
                settings: {
                    slidesToShow: breakpoint.md,
                    slidesToScroll: 1,
                    infinite: true
                }
            }, {
                breakpoint: 480,
                settings: {
                    slidesToShow: breakpoint.xs,
                    slidesToScroll: 1,
                    infinite: true
                }
            }]
       });
       return this; // to allow chaining
    };
    

    假设 滑溜的 插件按照规则运行(即允许jQuery对象匹配多个元素),您可以轻松地实际使用它:

    $('.slick-media').simpleSlick({xs: 6, md: 6, lg: 6 }, true);
    

    当类是给定的

    如果应该将类的使用视为给定的,那么您仍然可以使用jQuery方式根据其 class 属性(因为您已经将jQuery用于 滑溜的 插件):

    $('.slick-media').each(function () { 
        new Carousel(this, true, {xs: 6, md: 6, lg: 6 });
    });
    

    (但是,再次应用 new 如果不使用生成的对象,则会显示错误的设计)

    如果希望稍后通过DOM元素访问这些Carousel对象,那么可以考虑使用 data 方法:

    $('.slick-media').each(function () { 
        $(this).data('carousel', new Carousel(this, true, {xs: 6, md: 6, lg: 6 }));
    });
    

    对于给定的 elem 元素,则可以访问相应的 Carousel 实例如下:

    var carousel = $(elem).data('carousel'); // Get the Carousel instance
    
        3
  •  1
  •   Jonas Wilms    6 年前

    实际上,您可以将其缩短为:

     Array.from(
      document.getElementsByClassName('slick-media'), 
      node => new Carousel(node, true, {xs: 6, md: 6, lg: 6 })
    );