ES之module

文章介绍了一个基于JavaScript的模块系统,用于解决全局变量管理和加载顺序问题。它展示了如何创建一个名为BaseSlider的基类,处理幻灯片切换,包括初始化、动画控制和索引校正功能。Slider类是BaseSlider的子类,增加了键盘事件监听以支持左右键切换。此外,文章还讨论了ES6模块的export和import语法以及使用注意事项。
摘要由CSDN通过智能技术生成

模块:一个一个的局部作用域的代码块

模块系统需要解决的主要问题

  • 模块化的问题
  • 消除全局变量
  • 管理加载顺序

Module的基本用法

模块里面都是局部无法访问

切换幻灯片示例

Base.js

// 默认参数
const DEFAULTS = {
    // 初始索引
    initialIndex: 0,
    // 切换时是否有动画
    animation: true,
    // 切换速度,单位 ms
    speed: 300
};
// base
const ELEMENT_NODE = 1;
const SLIDER_ANIMATION_CLASSNAME = 'slider-animation';

// 父类
class BaseSlider {
    constructor(el, options) {
        console.log(options)
        if (el.nodeType !== ELEMENT_NODE)
            throw new Error('实例化的时候,请传入 DOM 元素!');

        // 实际参数
        this.options = {
            ...DEFAULTS,
            ...options
        };

        const slider = el;
        const sliderContent = slider.querySelector('.slider-content');
        const sliderItems = sliderContent.querySelectorAll('.slider-item');

        // 添加到 this 上,为了在方法中使用
        this.slider = slider;
        this.sliderContent = sliderContent;
        this.sliderItems = sliderItems;

        this.minIndex = 0;
        this.maxIndex = sliderItems.length - 1;
        this.currIndex = this.getCorrectedIndex(this.options.initialIndex);

        // 每个 slider-item 的宽度(每次移动的距离)
        this.itemWidth = sliderItems[0].offsetWidth;

        this.init();
    }

    // 获取修正后的索引值
    // 随心所欲,不逾矩
    getCorrectedIndex(index) {
        if (index < this.minIndex) return this.maxIndex;
        if (index > this.maxIndex) return this.minIndex;
        return index;
    }

    // 初始化
    init() {
        // 为每个 slider-item 设置宽度
        this.setItemsWidth();

        // 为 slider-content 设置宽度
        this.setContentWidth();

        // 切换到初始索引 initialIndex
        this.move(this.getDistance());

        // 开启动画
        if (this.options.animation) {
            this.openAnimation();
        }
    }

    // 为每个 slider-item 设置宽度
    setItemsWidth() {
        for (const item of this.sliderItems) {
            item.style.width = `${this.itemWidth}px`;
        }
    }

    // 为 slider-content 设置宽度
    setContentWidth() {
        this.sliderContent.style.width = `${
            this.itemWidth * this.sliderItems.length
        }px`;
    }

    // 不带动画的移动
    move(distance) {
        this.sliderContent.style.transform = `translate3d(${distance}px, 0px, 0px)`;
    }

    // 带动画的移动
    moveWithAnimation(distance) {
        this.setAnimationSpeed(this.options.speed);
        this.move(distance);
    }

    // 设置切换动画速度
    setAnimationSpeed(speed) {
        this.sliderContent.style.transitionDuration = `${speed}ms`;
    }

    // 获取要移动的距离
    getDistance(index = this.currIndex) {
        return -this.itemWidth * index;
    }

    // 开启动画
    openAnimation() {
        this.sliderContent.classList.add(SLIDER_ANIMATION_CLASSNAME);
    }

    // 关闭动画
    closeAnimation() {
        this.setAnimationSpeed(0);
    }

    // 切换到 index 索引对应的幻灯片
    to(index) {
        index = this.getCorrectedIndex(index);
        if (this.currIndex === index) return;

        this.currIndex = index;
        const distance = this.getDistance();

        if (this.options.animation) {
            return this.moveWithAnimation(distance);
        } else {
            return this.move(distance);
        }
    }

    // 切换上一张
    prev() {
        this.to(this.currIndex - 1);
    }

    // 切换下一张
    next() {
        this.to(this.currIndex + 1);
    }

    // 获取当前索引
    getCurrIndex() {
        return this.currIndex;
    }
}

export default BaseSlider;

slider.js

import BaseSlider from "./base.js";

// 子类
class Slider extends BaseSlider {
    constructor(el, options) {
        super(el, options);

        this._bindEvent();
    }

    _bindEvent() {
        document.addEventListener('keyup', ev => {
            // console.log(ev.keyCode);
            if (ev.keyCode === 37) {
                // ←
                this.prev();
            } else if (ev.keyCode === 39) {
                // →
                this.next();
            }
        });
    }
}

export default Slider;

index.js

import Slider from "./slider.js";
new Slider(document.querySelector('.slider'), {
    initialIndex: 1,
    animation: true,
    speed: 1000
});

slider.css

/* css reset */
* {
    padding: 0;
    margin: 0;
}
a {
    text-decoration: none;
    outline: none;
}
img {
    vertical-align: top;
}

/* layout */
.slider-layout {
    width: 80%;
    height: 420px;
    margin: 0 auto;
}

/* slider */
.slider,
.slider-content,
.slider-item,
.slider-img {
    width: 100%;
    height: 100%;
}
.slider {
    overflow: hidden;
}
.slider-item {
    float: left;
}
.slider-animation {
    transition-property: transform;
    transition-duration: 0ms;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Class 的应用</title>
    <link rel="stylesheet" href="css/slider.css"/>
</head>
<body>
<div class="slider-layout">
    <div class="slider">
        <div class="slider-content">
            <div class="slider-item">
                <a href="javascript:;"
                ><img src="imgs/1.jpeg" alt="1" class="slider-img"
                /></a>
            </div>
            <div class="slider-item">
                <a href="javascript:;"
                ><img src="imgs/2.jpeg" alt="1" class="slider-img"
                /></a>
            </div>
            <div class="slider-item">
                <a href="javascript:;"
                ><img src="imgs/3.jpeg" alt="1" class="slider-img"
                /></a>
            </div>
            <div class="slider-item">
                <a href="javascript:;"
                ><img src="imgs/4.jpeg" alt="1" class="slider-img"
                /></a>
            </div>
        </div>
    </div>
</div>

<script src="js/index.js" type="module"></script>
</body>
</html>

一个文件就是一个模块,只要你会用到import或export,在使用script标签加载的时候,就要加上type="module"

export default和import from注意事项

  • 一个模块只能有一个export default
  • 一个模块没有导出也可以将其导入 直接import就行
  • 被导入的代码都会执行一遍,也仅会执行一遍
  • 导出export default age,导入import aaa from '/js/module.js' 导入名字可以为aaa与age对应

export和import注意事项 

  • export声明或语句 export const age=18;/export {age};两种导出方式 import {age} from '/js/module.js'(不能随意命名,名字必须相同)
// 记住导出不能匿名
// 多个导出
// export function fn(){};
// export class className{};
// export const age=18;

function fn(){};
class className{};
const age=18;
export {fn as func,className,age};
export default 18;
<script type="module">
    // 1.导出导入起别名
    import {func, className as Person, age} from "./js/module.js";

    // 2.整体导入
    // 会导入所有输出,包括通过export default导出的
    import * as obj from "./js/module.js";

    // 3.同时导入
    // 要求:一定是export default在前
    // import age2,{func, className as Person, age} from "./js/module.js";
    console.log(Person);
    console.log(func);
    console.log(obj);
</script>

 

Module的注意事项

  • 模块顶层的注意事项
  • 模块中,顶层的this指向undefined
  • import关键字和import()函数
  • import命令具有提升效果,会提升到整个模块的头部,率先执行(import执行时,代码块还没执行)
  • import()可以按条件导入,import()返回的是一个Promise对象
  • 导入导出的复合写法
//复合写法导出的,无法在当前模块中使用
export {age} from './module.js';
console.log(age);

// 等价于下面两个
//import {age} from './module.js';
//export {age} from './module.js';
//可以在当前模块中使用
//console.log(age);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值