浏览代码

Refactoring the renderer.

NaotoshiFujita 3 年之前
父节点
当前提交
0d19fd0bb3

文件差异内容过多而无法显示
+ 0 - 0
dist/css/splide-core.min.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/splide.min.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/themes/splide-default.min.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/themes/splide-sea-green.min.css


文件差异内容过多而无法显示
+ 0 - 0
dist/css/themes/splide-skyblue.min.css


文件差异内容过多而无法显示
+ 0 - 0
dist/js/splide-renderer.min.js


+ 45 - 32
dist/js/splide.cjs.js

@@ -2404,7 +2404,9 @@ let Splide = _Splide;
 Splide.defaults = {};
 Splide.STATES = STATES;
 
-const RENDERING_DEFAULT_OPTIONS = {
+const CLASS_RENDERED = "is-rendered";
+
+const RENDERER_DEFAULT_CONFIG = {
   listTag: "ul",
   slideTag: "li"
 };
@@ -2451,13 +2453,15 @@ class Style {
 }
 
 class SplideRenderer {
-  constructor(contents, options, id, defaults = {}) {
+  constructor(contents, options, config, defaults) {
+    this.slides = [];
     this.options = {};
     this.breakpoints = [];
-    merge(DEFAULTS, defaults);
+    merge(DEFAULTS, defaults || {});
     merge(merge(this.options, DEFAULTS), options || {});
-    this.id = id || uniqueId("splide");
     this.contents = contents;
+    this.config = assign({}, RENDERER_DEFAULT_CONFIG, config || {});
+    this.id = this.config.id || uniqueId("splide");
     this.Style = new Style(this.id, this.options);
     this.Direction = Direction(null, null, this.options);
     assert(this.contents.length, "Provide at least 1 content.");
@@ -2474,11 +2478,27 @@ class SplideRenderer {
   }
   init() {
     this.parseBreakpoints();
+    this.initSlides();
     this.registerRootStyles();
     this.registerTrackStyles();
     this.registerSlideStyles();
     this.registerListStyles();
   }
+  initSlides() {
+    push(this.slides, this.contents.map((content, index) => {
+      content = isString(content) ? { html: content } : content;
+      content.styles = content.styles || {};
+      this.cover(content);
+      assign(content.attrs = content.attrs || {}, {
+        class: `${this.options.classes.slide} ${index === 0 ? CLASS_ACTIVE : ""}`.trim(),
+        style: this.buildStyles(content.styles)
+      });
+      return content;
+    }));
+    if (this.isLoop()) {
+      this.generateClones(this.slides);
+    }
+  }
   registerRootStyles() {
     this.breakpoints.forEach(([width, options]) => {
       this.Style.rule(" ", "max-width", unit(options.width), width);
@@ -2531,7 +2551,7 @@ class SplideRenderer {
     const cloneCount = this.getCloneCount();
     if (this.isFixedWidth(options)) {
       const { value, unit: unit2 } = this.parseCssValue(options[resolve("fixedWidth")]);
-      return `${orient(value) * cloneCount}${unit2}`;
+      return this.buildCssValue(orient(value) * cloneCount, unit2);
     }
     const percent = 100 * cloneCount / options.perPage;
     return `${orient(percent)}%`;
@@ -2623,6 +2643,9 @@ class SplideRenderer {
   isFixedWidth(options) {
     return !!options[this.Direction.resolve("fixedWidth")];
   }
+  isAutoWidth(options) {
+    return !!options[this.Direction.resolve("autoWidth")];
+  }
   isLoop() {
     return this.options.type === LOOP;
   }
@@ -2647,7 +2670,7 @@ class SplideRenderer {
       `${CLASS_ROOT}--${options.type}`,
       `${CLASS_ROOT}--${options.direction}`,
       CLASS_ACTIVE,
-      CLASS_INITIALIZED
+      !this.config.hidden && CLASS_RENDERED
     ].filter(Boolean).join(" ");
   }
   buildAttrs(attrs) {
@@ -2664,31 +2687,22 @@ class SplideRenderer {
     });
     return style.trim();
   }
-  renderSlides(renderingOptions) {
-    const { slideTag: tag } = renderingOptions;
-    const contents = this.contents.map((content, index) => {
-      content = isString(content) ? { html: content } : content;
-      const { styles = {}, html = "" } = content;
-      if (this.options.cover) {
-        const src = html.match(/<img.*?src\s*=\s*(['"])(.+?)\1.*?>/);
-        if (src && src[2]) {
-          styles.background = `center/cover no-repeat url('${src[2]}')`;
-        }
-      }
-      assign(content.attrs = content.attrs || {}, {
-        class: `${this.options.classes.slide} ${index === 0 ? CLASS_ACTIVE : ""}`.trim(),
-        style: this.buildStyles(styles)
-      });
-      return content;
-    });
-    if (this.isLoop()) {
-      this.generateClones(contents, renderingOptions);
-    }
-    return contents.map((content) => {
+  renderSlides() {
+    const { slideTag: tag } = this.config;
+    return this.slides.map((content) => {
       return `<${tag} ${this.buildAttrs(content.attrs)}>${content.html || ""}</${tag}>`;
     }).join("");
   }
-  generateClones(contents, renderingOptions) {
+  cover(content) {
+    const { styles, html = "" } = content;
+    if (this.options.cover) {
+      const src = html.match(/<img.*?src\s*=\s*(['"])(.+?)\1.*?>/);
+      if (src && src[2]) {
+        styles.background = `center/cover no-repeat url('${src[2]}')`;
+      }
+    }
+  }
+  generateClones(contents) {
     const { classes } = this.options;
     const count = this.getCloneCount();
     const slides = contents.slice();
@@ -2724,16 +2738,15 @@ class SplideRenderer {
     const { classes } = this.options;
     return `<button class="${classes.arrow} ${prev ? classes.prev : classes.next}" type="button"><svg xmlns="${XML_NAME_SPACE}" viewBox="0 0 ${SIZE} ${SIZE}" width="${SIZE}" height="${SIZE}"><path d="${this.options.arrowPath || PATH}" /></svg></button>`;
   }
-  html(renderingOptions = {}) {
-    renderingOptions = assign({}, RENDERING_DEFAULT_OPTIONS, renderingOptions);
-    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = renderingOptions;
+  html() {
+    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = this.config;
     let html = "";
     html += `<div id="${this.id}" class="${this.buildClasses()} ${rootClass || ""}">`;
     html += `<style>${this.Style.build()}</style>`;
     html += beforeTrack || "";
     html += `<div class="splide__track">`;
     html += `<${listTag} class="splide__list">`;
-    html += this.renderSlides(renderingOptions);
+    html += this.renderSlides();
     html += `</${listTag}>`;
     html += `</div>`;
     if (arrows) {

+ 45 - 32
dist/js/splide.esm.js

@@ -2400,7 +2400,9 @@ let Splide = _Splide;
 Splide.defaults = {};
 Splide.STATES = STATES;
 
-const RENDERING_DEFAULT_OPTIONS = {
+const CLASS_RENDERED = "is-rendered";
+
+const RENDERER_DEFAULT_CONFIG = {
   listTag: "ul",
   slideTag: "li"
 };
@@ -2447,13 +2449,15 @@ class Style {
 }
 
 class SplideRenderer {
-  constructor(contents, options, id, defaults = {}) {
+  constructor(contents, options, config, defaults) {
+    this.slides = [];
     this.options = {};
     this.breakpoints = [];
-    merge(DEFAULTS, defaults);
+    merge(DEFAULTS, defaults || {});
     merge(merge(this.options, DEFAULTS), options || {});
-    this.id = id || uniqueId("splide");
     this.contents = contents;
+    this.config = assign({}, RENDERER_DEFAULT_CONFIG, config || {});
+    this.id = this.config.id || uniqueId("splide");
     this.Style = new Style(this.id, this.options);
     this.Direction = Direction(null, null, this.options);
     assert(this.contents.length, "Provide at least 1 content.");
@@ -2470,11 +2474,27 @@ class SplideRenderer {
   }
   init() {
     this.parseBreakpoints();
+    this.initSlides();
     this.registerRootStyles();
     this.registerTrackStyles();
     this.registerSlideStyles();
     this.registerListStyles();
   }
+  initSlides() {
+    push(this.slides, this.contents.map((content, index) => {
+      content = isString(content) ? { html: content } : content;
+      content.styles = content.styles || {};
+      this.cover(content);
+      assign(content.attrs = content.attrs || {}, {
+        class: `${this.options.classes.slide} ${index === 0 ? CLASS_ACTIVE : ""}`.trim(),
+        style: this.buildStyles(content.styles)
+      });
+      return content;
+    }));
+    if (this.isLoop()) {
+      this.generateClones(this.slides);
+    }
+  }
   registerRootStyles() {
     this.breakpoints.forEach(([width, options]) => {
       this.Style.rule(" ", "max-width", unit(options.width), width);
@@ -2527,7 +2547,7 @@ class SplideRenderer {
     const cloneCount = this.getCloneCount();
     if (this.isFixedWidth(options)) {
       const { value, unit: unit2 } = this.parseCssValue(options[resolve("fixedWidth")]);
-      return `${orient(value) * cloneCount}${unit2}`;
+      return this.buildCssValue(orient(value) * cloneCount, unit2);
     }
     const percent = 100 * cloneCount / options.perPage;
     return `${orient(percent)}%`;
@@ -2619,6 +2639,9 @@ class SplideRenderer {
   isFixedWidth(options) {
     return !!options[this.Direction.resolve("fixedWidth")];
   }
+  isAutoWidth(options) {
+    return !!options[this.Direction.resolve("autoWidth")];
+  }
   isLoop() {
     return this.options.type === LOOP;
   }
@@ -2643,7 +2666,7 @@ class SplideRenderer {
       `${CLASS_ROOT}--${options.type}`,
       `${CLASS_ROOT}--${options.direction}`,
       CLASS_ACTIVE,
-      CLASS_INITIALIZED
+      !this.config.hidden && CLASS_RENDERED
     ].filter(Boolean).join(" ");
   }
   buildAttrs(attrs) {
@@ -2660,31 +2683,22 @@ class SplideRenderer {
     });
     return style.trim();
   }
-  renderSlides(renderingOptions) {
-    const { slideTag: tag } = renderingOptions;
-    const contents = this.contents.map((content, index) => {
-      content = isString(content) ? { html: content } : content;
-      const { styles = {}, html = "" } = content;
-      if (this.options.cover) {
-        const src = html.match(/<img.*?src\s*=\s*(['"])(.+?)\1.*?>/);
-        if (src && src[2]) {
-          styles.background = `center/cover no-repeat url('${src[2]}')`;
-        }
-      }
-      assign(content.attrs = content.attrs || {}, {
-        class: `${this.options.classes.slide} ${index === 0 ? CLASS_ACTIVE : ""}`.trim(),
-        style: this.buildStyles(styles)
-      });
-      return content;
-    });
-    if (this.isLoop()) {
-      this.generateClones(contents, renderingOptions);
-    }
-    return contents.map((content) => {
+  renderSlides() {
+    const { slideTag: tag } = this.config;
+    return this.slides.map((content) => {
       return `<${tag} ${this.buildAttrs(content.attrs)}>${content.html || ""}</${tag}>`;
     }).join("");
   }
-  generateClones(contents, renderingOptions) {
+  cover(content) {
+    const { styles, html = "" } = content;
+    if (this.options.cover) {
+      const src = html.match(/<img.*?src\s*=\s*(['"])(.+?)\1.*?>/);
+      if (src && src[2]) {
+        styles.background = `center/cover no-repeat url('${src[2]}')`;
+      }
+    }
+  }
+  generateClones(contents) {
     const { classes } = this.options;
     const count = this.getCloneCount();
     const slides = contents.slice();
@@ -2720,16 +2734,15 @@ class SplideRenderer {
     const { classes } = this.options;
     return `<button class="${classes.arrow} ${prev ? classes.prev : classes.next}" type="button"><svg xmlns="${XML_NAME_SPACE}" viewBox="0 0 ${SIZE} ${SIZE}" width="${SIZE}" height="${SIZE}"><path d="${this.options.arrowPath || PATH}" /></svg></button>`;
   }
-  html(renderingOptions = {}) {
-    renderingOptions = assign({}, RENDERING_DEFAULT_OPTIONS, renderingOptions);
-    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = renderingOptions;
+  html() {
+    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = this.config;
     let html = "";
     html += `<div id="${this.id}" class="${this.buildClasses()} ${rootClass || ""}">`;
     html += `<style>${this.Style.build()}</style>`;
     html += beforeTrack || "";
     html += `<div class="splide__track">`;
     html += `<${listTag} class="splide__list">`;
-    html += this.renderSlides(renderingOptions);
+    html += this.renderSlides();
     html += `</${listTag}>`;
     html += `</div>`;
     if (arrows) {

+ 32 - 9
dist/types/renderer/SplideRenderer/SplideRenderer.d.ts

@@ -1,6 +1,6 @@
 import { Splide } from '../../core/Splide/Splide';
 import { Options } from '../../types';
-import { RenderingOptions, SlideContent } from '../types/types';
+import { RendererConfig, SlideContent } from '../types/types';
 /**
  * The class to generate static HTML of the slider for the first view.
  *
@@ -17,6 +17,10 @@ export declare class SplideRenderer {
      * Holds slide contents.
      */
     private readonly contents;
+    /**
+     * Stores data of slides.
+     */
+    private readonly slides;
     /**
      * The Direction component.
      */
@@ -29,6 +33,10 @@ export declare class SplideRenderer {
      * Holds options.
      */
     private readonly options;
+    /**
+     * Holds options for this instance.
+     */
+    private readonly config;
     /**
      * The slider ID.
      */
@@ -41,15 +49,19 @@ export declare class SplideRenderer {
      * The SplideRenderer constructor.
      *
      * @param contents - An array with slide contents. Each item must be an HTML or a plain text.
-     * @param options  - Optional. Options.
-     * @param id       - Optional. An ID of the slider.
-     * @param defaults - Static default options.
+     * @param options  - Optional. Slider options.
+     * @param config   - Static default options.
+     * @param defaults - Default options for the slider. Pass `Splide.defaults` if you are using it.
      */
-    constructor(contents: string[] | SlideContent[], options?: Options, id?: string, defaults?: Options);
+    constructor(contents: string[] | SlideContent[], options?: Options, config?: RendererConfig, defaults?: Options);
     /**
      * Initializes the instance.
      */
     private init;
+    /**
+     * Initializes slides.
+     */
+    private initSlides;
     /**
      * Registers styles for the root element.
      */
@@ -196,6 +208,12 @@ export declare class SplideRenderer {
      * @return `true` if the slide width is fixed, or otherwise `false`.
      */
     private isFixedWidth;
+    /**
+     * Checks if the `autoWidth` is active or not.
+     *
+     * @return `true` if the `autoWidth` is active, or otherwise `false`.
+     */
+    private isAutoWidth;
     /**
      * Checks if the slider type is loop or not.
      *
@@ -239,14 +257,19 @@ export declare class SplideRenderer {
     /**
      * Generates HTML of slides with inserting provided contents.
      *
-     * @param renderingOptions - Rendering options.
+     * @return The HTML for all slides and clones.
      */
     private renderSlides;
+    /**
+     * Add the `background` style for the cover mode.
+     *
+     * @param content - A slide content.
+     */
+    private cover;
     /**
      * Generates clones.
      *
-     * @param contents         - An array with SlideContent objects.
-     * @param renderingOptions - Rendering options.
+     * @param contents - An array with SlideContent objects.
      */
     private generateClones;
     /**
@@ -274,6 +297,6 @@ export declare class SplideRenderer {
      *
      * @return The generated HTML.
      */
-    html(renderingOptions?: RenderingOptions): string;
+    html(): string;
 }
 //# sourceMappingURL=../../../../src/js/renderer/SplideRenderer/SplideRenderer.d.ts.map

文件差异内容过多而无法显示
+ 0 - 1
dist/types/renderer/SplideRenderer/SplideRenderer.d.ts.map


+ 2 - 2
dist/types/renderer/constants/defaults.d.ts

@@ -1,8 +1,8 @@
-import { RenderingOptions } from '../types/types';
+import { RendererConfig } from '../types/types';
 /**
  * Default options for generating static HTML.
  *
  * @since 3.0.0
  */
-export declare const RENDERING_DEFAULT_OPTIONS: RenderingOptions;
+export declare const RENDERER_DEFAULT_CONFIG: RendererConfig;
 //# sourceMappingURL=../../../../src/js/renderer/constants/defaults.d.ts.map

+ 1 - 1
dist/types/renderer/constants/defaults.d.ts.map

@@ -1 +1 @@
-{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,EAAE,gBAGvC,CAAC"}
+{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGhD;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,EAAE,cAGrC,CAAC"}

+ 54 - 0
dist/types/renderer/types/types.d.ts

@@ -0,0 +1,54 @@
+export interface SlideContent {
+    /**
+     * The HTML or text for each slide.
+     */
+    html?: string;
+    /**
+     * The collection of styles.
+     */
+    styles?: Record<string, string | number>;
+    /**
+     * The collection of attributes.
+     */
+    attrs?: Record<string, string | number | boolean>;
+}
+/**
+ * The interface for the config of the renderer.
+ *
+ * @since 3.0.0
+ */
+export interface RendererConfig {
+    /**
+     * The slider ID.
+     */
+    id?: string;
+    /**
+     * The additional class for the root element.
+     */
+    rootClass?: string;
+    /**
+     * The tag used for the list element.
+     */
+    listTag?: string;
+    /**
+     * The tag used for each slide.
+     */
+    slideTag?: string;
+    /**
+     * Determines whether to render arrows or not.
+     */
+    arrows?: string;
+    /**
+     * The additional HTML rendered before the track element.
+     */
+    beforeTrack?: string;
+    /**
+     * The additional HTML rendered after the track element.
+     */
+    afterTrack?: string;
+    /**
+     * Keeps the slider hidden.
+     */
+    hidden?: boolean;
+}
+//# sourceMappingURL=../../../../src/js/renderer/types/types.d.ts.map

+ 1 - 0
dist/types/renderer/types/types.d.ts.map

@@ -0,0 +1 @@
+{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IAEzC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;CACnD;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB"}

+ 2 - 1
src/css/core/object/objects/root.scss

@@ -3,7 +3,8 @@
   position: relative;
   visibility: hidden;
 
-  &.is-initialized {
+  &.is-initialized,
+  &.is-rendered {
     visibility: visible;
   }
 }

+ 80 - 53
src/js/renderer/SplideRenderer/SplideRenderer.ts

@@ -1,14 +1,6 @@
 import { PATH, SIZE, XML_NAME_SPACE } from '../../components/Arrows/path';
 import { Direction, DirectionComponent } from '../../components/Direction/Direction';
-import {
-  CLASS_ACTIVE,
-  CLASS_CLONE,
-  CLASS_INITIALIZED,
-  CLASS_LIST,
-  CLASS_ROOT,
-  CLASS_SLIDE,
-  CLASS_TRACK,
-} from '../../constants/classes';
+import { CLASS_ACTIVE, CLASS_CLONE, CLASS_LIST, CLASS_ROOT, CLASS_SLIDE, CLASS_TRACK } from '../../constants/classes';
 import { DEFAULTS } from '../../constants/defaults';
 import { TTB } from '../../constants/directions';
 import { EVENT_MOUNTED } from '../../constants/events';
@@ -16,7 +8,6 @@ import { LOOP, SLIDE } from '../../constants/types';
 import { EventInterface } from '../../constructors';
 import { Splide } from '../../core/Splide/Splide';
 import { Options } from '../../types';
-import { RenderingOptions, SlideContent } from '../types/types';
 import {
   assert,
   assign,
@@ -33,8 +24,10 @@ import {
   uniqueId,
   unit,
 } from '../../utils';
-import { RENDERING_DEFAULT_OPTIONS } from '../constants/defaults';
+import { CLASS_RENDERED } from '../constants/classes';
+import { RENDERER_DEFAULT_CONFIG } from '../constants/defaults';
 import { Style } from '../Style/Style';
+import { RendererConfig, SlideContent } from '../types/types';
 
 
 /**
@@ -65,6 +58,11 @@ export class SplideRenderer {
    */
   private readonly contents: string[] | SlideContent[];
 
+  /**
+   * Stores data of slides.
+   */
+  private readonly slides: SlideContent[] = [];
+
   /**
    * The Direction component.
    */
@@ -80,6 +78,11 @@ export class SplideRenderer {
    */
   private readonly options: Options = {};
 
+  /**
+   * Holds options for this instance.
+   */
+  private readonly config: RendererConfig;
+
   /**
    * The slider ID.
    */
@@ -94,16 +97,17 @@ export class SplideRenderer {
    * The SplideRenderer constructor.
    *
    * @param contents - An array with slide contents. Each item must be an HTML or a plain text.
-   * @param options  - Optional. Options.
-   * @param id       - Optional. An ID of the slider.
-   * @param defaults - Static default options.
+   * @param options  - Optional. Slider options.
+   * @param config   - Static default options.
+   * @param defaults - Default options for the slider. Pass `Splide.defaults` if you are using it.
    */
-  constructor( contents: string[] | SlideContent[], options?: Options, id?: string, defaults: Options = {} ) {
-    merge( DEFAULTS, defaults );
+  constructor( contents: string[] | SlideContent[], options?: Options, config?: RendererConfig, defaults?: Options ) {
+    merge( DEFAULTS, defaults || {} );
     merge( merge( this.options, DEFAULTS ), options || {} );
 
-    this.id        = id || uniqueId( 'splide' );
     this.contents  = contents;
+    this.config    = assign( {}, RENDERER_DEFAULT_CONFIG, config || {} );
+    this.id        = this.config.id || uniqueId( 'splide' );
     this.Style     = new Style( this.id, this.options );
     this.Direction = Direction( null, null, this.options );
 
@@ -117,12 +121,36 @@ export class SplideRenderer {
    */
   private init(): void {
     this.parseBreakpoints();
+    this.initSlides();
     this.registerRootStyles();
     this.registerTrackStyles();
     this.registerSlideStyles();
     this.registerListStyles();
   }
 
+  /**
+   * Initializes slides.
+   */
+  private initSlides(): void {
+    push( this.slides, this.contents.map( ( content, index ) => {
+      content = isString( content ) ? { html: content } : content;
+      content.styles = content.styles || {};
+
+      this.cover( content );
+
+      assign( ( content.attrs = content.attrs || {} ), {
+        class: `${ this.options.classes.slide } ${ index === 0 ? CLASS_ACTIVE : '' }`.trim(),
+        style: this.buildStyles( content.styles ),
+      } );
+
+      return content;
+    } ) );
+
+    if ( this.isLoop() ) {
+      this.generateClones( this.slides );
+    }
+  }
+
   /**
    * Registers styles for the root element.
    */
@@ -217,7 +245,7 @@ export class SplideRenderer {
 
     if ( this.isFixedWidth( options ) ) {
       const { value, unit } = this.parseCssValue( options[ resolve( 'fixedWidth' ) ] );
-      return `${ orient( value ) * cloneCount }${ unit }`;
+      return this.buildCssValue( orient( value ) * cloneCount, unit );
     }
 
     const percent = 100 * cloneCount / options.perPage;
@@ -444,6 +472,15 @@ export class SplideRenderer {
     return !! options[ this.Direction.resolve( 'fixedWidth' ) ];
   }
 
+  /**
+   * Checks if the `autoWidth` is active or not.
+   *
+   * @return `true` if the `autoWidth` is active, or otherwise `false`.
+   */
+  private isAutoWidth( options: Options ): boolean {
+    return !! options[ this.Direction.resolve( 'autoWidth' ) ];
+  }
+
   /**
    * Checks if the slider type is loop or not.
    *
@@ -494,7 +531,7 @@ export class SplideRenderer {
       `${ CLASS_ROOT }--${ options.type }`,
       `${ CLASS_ROOT }--${ options.direction }`,
       CLASS_ACTIVE,
-      CLASS_INITIALIZED, // todo
+      ! this.config.hidden && CLASS_RENDERED,
     ].filter( Boolean ).join( ' ' );
   }
 
@@ -535,48 +572,39 @@ export class SplideRenderer {
   /**
    * Generates HTML of slides with inserting provided contents.
    *
-   * @param renderingOptions - Rendering options.
+   * @return The HTML for all slides and clones.
    */
-  private renderSlides( renderingOptions: RenderingOptions ): string {
-    const { slideTag: tag } = renderingOptions;
+  private renderSlides(): string {
+    const { slideTag: tag } = this.config;
 
-    const contents = this.contents.map( ( content, index ) => {
-      content = isString( content ) ? { html: content } : content;
+    return this.slides.map( content => {
+      return `<${ tag } ${ this.buildAttrs( content.attrs ) }>${ content.html || '' }</${ tag }>`;
+    } ).join( '' );
+  }
 
-      const { styles = {}, html = '' } = content;
+  /**
+   * Add the `background` style for the cover mode.
+   *
+   * @param content - A slide content.
+   */
+  private cover( content: SlideContent ): void {
+    const { styles, html = '' } = content;
 
-      if ( this.options.cover ) {
-        const src = html.match( /<img.*?src\s*=\s*(['"])(.+?)\1.*?>/ );
+    if ( this.options.cover ) {
+      const src = html.match( /<img.*?src\s*=\s*(['"])(.+?)\1.*?>/ );
 
-        if ( src && src[ 2 ] ) {
-          styles.background = `center/cover no-repeat url('${ src[ 2 ] }')`;
-        }
+      if ( src && src[ 2 ] ) {
+        styles.background = `center/cover no-repeat url('${ src[ 2 ] }')`;
       }
-
-      assign( ( content.attrs = content.attrs || {} ), {
-        class: `${ this.options.classes.slide } ${ index === 0 ? CLASS_ACTIVE : '' }`.trim(),
-        style: this.buildStyles( styles ),
-      } );
-
-      return content;
-    } );
-
-    if ( this.isLoop() ) {
-      this.generateClones( contents, renderingOptions );
     }
-
-    return contents.map( content => {
-      return `<${ tag } ${ this.buildAttrs( content.attrs ) }>${ content.html || '' }</${ tag }>`;
-    } ).join( '' );
   }
 
   /**
    * Generates clones.
    *
-   * @param contents         - An array with SlideContent objects.
-   * @param renderingOptions - Rendering options.
+   * @param contents - An array with SlideContent objects.
    */
-  private generateClones( contents: SlideContent[], renderingOptions: RenderingOptions ): void {
+  private generateClones( contents: SlideContent[] ): void {
     const { classes } = this.options;
     const count  = this.getCloneCount();
     const slides = contents.slice();
@@ -641,7 +669,7 @@ export class SplideRenderer {
       +	`<svg xmlns="${ XML_NAME_SPACE }" viewBox="0 0 ${ SIZE } ${ SIZE }" width="${ SIZE }" height="${ SIZE }">`
       + `<path d="${ this.options.arrowPath || PATH }" />`
       + `</svg>`
-      + `</button>`
+      + `</button>`;
   }
 
   /**
@@ -649,9 +677,8 @@ export class SplideRenderer {
    *
    * @return The generated HTML.
    */
-  html( renderingOptions: RenderingOptions = {} ): string {
-    renderingOptions = assign( {}, RENDERING_DEFAULT_OPTIONS, renderingOptions );
-    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = renderingOptions;
+  html(): string {
+    const { rootClass, listTag, arrows, beforeTrack, afterTrack } = this.config;
 
     let html = '';
 
@@ -663,7 +690,7 @@ export class SplideRenderer {
     html += `<div class="splide__track">`;
     html += `<${ listTag } class="splide__list">`;
 
-    html += this.renderSlides( renderingOptions );
+    html += this.renderSlides();
 
     html += `</${ listTag }>`;
     html += `</div>`;

+ 1 - 0
src/js/renderer/constants/classes.ts

@@ -0,0 +1 @@
+export const CLASS_RENDERED = 'is-rendered';

+ 2 - 2
src/js/renderer/constants/defaults.ts

@@ -1,4 +1,4 @@
-import { RenderingOptions } from '../types/types';
+import { RendererConfig } from '../types/types';
 
 
 /**
@@ -6,7 +6,7 @@ import { RenderingOptions } from '../types/types';
  *
  * @since 3.0.0
  */
-export const RENDERING_DEFAULT_OPTIONS: RenderingOptions = {
+export const RENDERER_DEFAULT_CONFIG: RendererConfig = {
   listTag : 'ul',
   slideTag: 'li',
 };

+ 19 - 4
src/js/renderer/types/types.ts

@@ -1,3 +1,8 @@
+/**
+ * The interface for the content of each slide.
+ *
+ * @since 3.0.0
+ */
 export interface SlideContent {
   /**
    * The HTML or text for each slide.
@@ -5,22 +10,27 @@ export interface SlideContent {
   html?: string;
 
   /**
-   * The collection of styles.
+   * The collection of styles. They will remain after Splide is applied.
    */
   styles?: Record<string, string | number>;
 
   /**
-   * The collection of attributes.
+   * The collection of attributes. They will remain after Splide is applied.
    */
   attrs?: Record<string, string | number | boolean>;
 }
 
 /**
- * The interface for rendering options.
+ * The interface for the config of the renderer.
  *
  * @since 3.0.0
  */
-export interface RenderingOptions {
+export interface RendererConfig {
+  /**
+   * The slider ID.
+   */
+  id?: string;
+
   /**
    * The additional class for the root element.
    */
@@ -50,4 +60,9 @@ export interface RenderingOptions {
    * The additional HTML rendered after the track element.
    */
   afterTrack?: string;
+
+  /**
+   * Keeps the slider hidden.
+   */
+  hidden?: boolean;
 }

+ 8 - 2
src/js/test/php/examples/renderer.php

@@ -88,11 +88,16 @@ $settings = get_settings();
             },
           },
         ],
-        options
+        options,
+        {
+          id: 'test',
+          arrows: true,
+          // hidden: true,
+        }
       );
 
       var wrapper = document.getElementById( 'wrapper' );
-      wrapper.innerHTML = renderer.html( { arrows: true } );
+      wrapper.innerHTML = renderer.html();
 
       setTimeout( () => {
         var splide = new Splide( wrapper.firstElementChild, options );
@@ -105,6 +110,7 @@ $settings = get_settings();
 <body>
 
 <div id="wrapper"></div>
+<span>The end of the slider</span>
 
 </body>
 </html>

部分文件因为文件数量过多而无法显示