Deng
Deng
ES6之Module模块与Babel编译 | odjBlog
    欢迎来到odjBlog的博客!

ES6之Module模块与Babel编译

web前端学习 odjbin 4年前 (2022-01-15) 83次浏览 0个评论

Module 模块

Module 是什么

  • 模块:一个一个的局部作用域的代码块
  • 什么是模块系统:
  • 模块系统需要解决的主要问题
    • ①模块化的问题
    • ②消除全局变量
    • ③管理加载顺序

Module 的基本用法

  • export default BaseSlider;
  • import BaseSlider from './base.js';
  • 一个文件就是一个模块
  • 只要你会用到 import 或 export,在使用 script 标签加载时,就要加上 type="module"

export default 和对应的 import [非常重要]

  • 1.认识导出和导入
    • 导出的东西可以被导入(import),并访问到
mo.js
const age=18;
// console.log(age);
// export default age;
// export default 20;
// export default {};
//一个模块只能有一个 export default
// const fn=()=>{};
// export default fn;
// export default function (){};
export default class{};
<script type="module">
     //1.认识导出和导入
     //导出的东西可以被导入(import),并访问到
     //一个模块没有导出,也可以将其导入
     //被导入的代码都会执行一遍,也仅会执行一遍
     //  import './mo.js';//18
     //2.基本用法
     //可以随便起名
     import aa from './mo.js';
     console.log(aa);
</script>

export 和对应的 import [非常重要]

  <script type="module">
    //1.基本用法
    // export 声明或语句
    //不能随意命名 ① export const age = 18;
    import { age } from "./mo.js"; //② export {age};
    console.log(age);
    //2.多个导出
    //1. function fn(){}
    // export function fn(){}//function (){} 匿名不行
    import { fn } from "./mo.js";
    console.log(fn);
    //2. class className {}
    // export class className{}//export class {} 匿名不行
    import { className } from "./mo.js";
    console.log(className);
    //3.多个导出..
    // export { fn as func, className, age };
    // export default 1;
    //多个导入..
    import { fn, age, className } from "./mo.js";
    console.log(fn, age, className); //ƒ fn(){} 18 class className{}
    //4.导出导入时起别名
    import { func, age, className as Person } from "./mo.js";
    console.log(func, age, Person);
    //5.整体导入
    //会导入所有输出,包括通过 export default 导出的
    import * as obj from "./mo.js";
    console.log(obj);
    //6.同时导入
    //一定是 export default 的在前
    import age2, { func, age, className } from "./mo.js";
    console.log(age2);
  </script>

Module 的注意事项[简单听听]

//mo.js
console.log(this);
if (typeof this!=='undefined'){
    throw new Error('请使用模块的方式加载');
}
export const age=18;
<script type="module">
    //1.模块顶层的 this 指向
    //在模块中,顶层的 this 指向 undefined
    import './mo.js';
    //2.import 和 import()(了解)
    //import 命令具有提升效果,会提升到整个模块的头部,率先执行
    //import 执行的时候,代码还没执行
    //import 和 export 命令只能在模块的顶层,不能在代码块中执行
    //import()可以按条件导入
    if (PC){
       import('pc.js').then().catch();
    }else if(Mobile){
       import('mobile.js').then().catch();
    }
    //3.导入导出的复合写法
    //复合写法导出的,无法在当前模块中使用
    // export {age} from './mo.js';//不推荐
    //等价于
    import {age} from './mo.js';
    export {age} from './mo.js';
    console.log(age);
</script>

Module 的应用

 <div class="slider-layout">
      <div class="slider">
        <div class="slider-content">
          <div class="slider-item">
            <a href="javascript:;"
              ><img src="./imgs/1.jpg" alt="1" class="slider-img"
            /></a>
          </div>
        </div>
      </div>
    </div>

    <script src="./index.js"></script>
//index.js
import Slider from "./slider";
 new Slider(document.querySelector(".slider"));
//slider.js
import BaseSlider from './base.js';
import keyboard from './keyboard.js';
// import Mouse from './keyboard.js';
class Slider extends BaseSlider {
    constructor(el, options) {
      super(el, options);

      this._bindEvent();
    }
    _bindEvent() {
      keyboard.bindEvent(this)
      // Mouse.bindEvent(this)
    }
  }
  export default Slider
//default.js
const DEFAULTS = {
  // 初始索引
  initialIndex: 0,
  // 切换时是否有动画
  animation: true,
  // 切换速度,单位 ms
  speed: 300,
};
export default DEFAULTS;
// export default {
//   // 初始索引
//   initialIndex: 0,
//   // 切换时是否有动画
//   animation: true,
//   // 切换速度,单位 ms
//   speed: 300,
// };
//constant.js
export const ELEMENT_NODE = 1;
export const SLIDER_ANIMATION_CLASSNAME = 'slider-animation';
export const LEFT_KEYCODE=37
export const RIGHT_KEYCODE=39
//keyboard.js
import { LEFT_KEYCODE,RIGHT_KEYCODE } from "./constants";
const keyboard = {
  bindEvent(slider) {
    document.addEventListener("keyup", (ev) => {
      if (ev.keyCode === LEFT_KEYCODE) {
        // ←
        slider.prev();
      } else if (ev.keyCode === RIGHT_KEYCODE) {
        // →
        slider.next();
      }
    });
  },
};
export default keyboard;
//base.js
// 默认参数
import DEFAULTS from "./default";
// 常量
import {ELEMENT_NODE,SLIDER_ANIMATION_CLASSNAME} from './constants'

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;

Babel 与 webpack

Babel 是什么

官网 : https://babeljs.io/

  • Babel 是 javaScript 的编译器,用来将 ES6 的代码,转换成 ES6 之前的代码
  • Babel 本身可以编译 ES6 的大部分语法,比如 let、const、箭头函数、类
  • 但是对于 ES6 新增的 API,比如 Set、Map、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign/Array.from)都不能直接编译,需要借助其它的模块
  • Babel 一般需要配合 Webpack 来编译模块语法

Babel 的使用方式[重点]

https://babeljs.io/setup
CLI 命令行工具 webpack

使用 Babel 前的准备工作[重点]

  • node.js 是个平台或者工具,对应浏览器
  • 后端的 JavaScript=ECMAScript+IO+File+...等服务端的操作
  • npm: node 包管理工具
  • https://nodejs.org/zh-cn/ 稳定版
    在你的项目目录上 node -v -> npm -v -> npm init -> ok?->然后一直回车 就会出现 package.json 文件
  • npm install --save-dev @babel/core @babel/cli

使用 Babel 编译 ES6 代码[重点]

let name = 'Alex';
const age = 18;
const add = (x, y) => x + y;
new Promise((resolve, reject) => {
    resolve('成功');
});
Array.from([1, 2]);
class Person {
}
import './index.js';
  • npm install @babel/preset-env --save-dev
  • 创建文件: .babelrc { "presets": ["@babel/preset-env"] }
  • npm run build 编译完成

Webpack 是什么

  • webpack 是静态模块打包器,当 webpack 处理应用程序时,会将所有这些模块打包成一个或多个文件
  • 模块: webpack 可以处理 js/css/图片,图标字体等单位
  • 静态: 开发过程中存在于本地的 js/css/图片/图标字体等文件,就是静态的
  • 动态的内容,webpack 没办法处理,只能处理静态的

Webpack 初体验[重点]

  • 1.初始化项目 npm init
  • 2.安装 webpack 需要的包 npm install --save-dev webpack-cli@3.3.12 webpack@4.44.1
  • 3.配置 webpack webpack.config.js [根目录上创建]
const path = require('path');
module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(_dirname, 'dist'),
        filename: 'bundle.js'
    }
}
  • 4.编译并测试
"scripts": {
    "webpack": "webpack --config webpack.config.js"
  },

src 目录下

module.js:
export default 18;
console.log('module.js');
index.js:
import age from './module.js';
console.log('index.js',age);
  • 测试
<!--    <script src="./src/index.js" type="module"></script>-->
    <script src="./dist/bundle.js" ></script>

index.js 18

entry 和 output[核心概念]

  • 1.entry: 指定入口文件 //单入口,多入口怎么写 webpack.config.js
 entry: {
        main: './src/index.js',
        search:'./src/search.js'
    },
  • 2.output
module.exports = {
    mode:'development',
    //单入口: entry: './src/index.js',
    entry: {
        main: './src/index.js',
        search:'./src/search.js'
    },
    // output: {
    //     path: path.resolve('dist'),
    //     filename: 'bundle.js'
    // }
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    }
};

loader[核心概念]

webpack/js/css 图片

  • loader 让 webpack 能够去处理那些非 JS 文件的模块
  • 2.babel-loader npm install --save-dev babel-loader@8.1.0
  • 3.安装 Babel npm install --save-dev @babel/core@7.11.0 @babel/preset-env@7.11.0
.babelrc
{
  "presets":["@babel/preset-env"]
}
  webpack.config.js
  module: {
      rules: [{
          test:/\.js$/,
          exclude: /node_modules/,
          loader: "babel-loader"
      }]
  }
  • 5.引入 core-js //编译新增 API npm install --save-dev core-js@3.6.5 import "core-js/stable";

plugins[核心概念]

  • 1.loader 被用于帮助 webpack 处理各种模块,而插件则可以用于执行范围更广的任务 https://www.webpackjs.com/plugins/
  • 2.html-webpack-plugin npm install --save-dev html-webpack-plugin@4.3.0
  • 3.配置 html-webpack-plugin 插件
webpack.config.js
  plugins: [
        new HtmlWebpackPlugin({
            template: './1.html'
        })
    ]
  • 4.多页面时 html-webpack-plugin 插件的配置
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    mode: 'development',
    entry: {
        index: './src/index.js',
        search: './src/search.js'
    },
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    },
    plugins: [
        //多入口
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: "index.html",
            chunks: ['index'],
            minify: {
                //删除 index.html 中的注释
                removeComments: true,
                //删除 index.html 中的空格
                collapseWhitespace: true,
                //删除各种 html 标签属性值的双引号
                removeAttributeQuotes: true
            }
        }),
        new HtmlWebpackPlugin({
            template: './search.html',
            filename: "search.html",
            chunks: ['search']
        })
    ]
};

处理 CSS 文件

npm install --save-dev css-loader@4.1.1 npm install --save-dev style-loader@1.2.1

body{
    background-color: pink;
}
import './index.css';
const path= require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
    mode: 'development',
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    },
    module:{
        rules: [{
            test:/\.css$/,
            // loader: 'css-loader'
            use:['style-loader','css-loader']//右往左用
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'index.html'
        })
    ]
};

dist->index.html 运行,背景颜色变为 pink

npm install --save-dev mini-css-extract-plugin@0.9.0

webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
 module:{
        rules: [{
            test:/\.css$/,
            use:[MiniCssExtractPlugin.loader,'css-loader']
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ]
};

使用 file-loader 处理 CSS 中的图片

  • 如果是外部的资源,是不需要考虑 webpack 的,只有本地的图片才需要被 webpack 处理

-file-loader npm install --save-dev file-loader@6.0.0

body{
    /*background-image: url(https://www.imooc.com/static/img/index/logo.png);*/
    background-image: url(img/logo.png);
    background-repeat: no-repeat;
}
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    },
    module: {
        rules: [{
            test: /\.css$/,
            use: [{loader: MiniCssExtractPlugin.loader,
                options: {
                    publicPath:'../'
                }
            }, 'css-loader']
        },
            {
                test:/\.(jpg|png|gif)$/,
                use:{
                    loader: 'file-loader',
                    options: {
                        name:'img/[name].[ext]'
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ]
};

使用 html-withimg-loader 处理 HTML 中的图片

<img src="./src/img/logo.png" alt="">
  {
            test:/\.(jpg|png|gif)$/,
            use:{
                loader: 'file-loader',
                options: {
                    name:'img/[name].[ext]',
                    esModule:false
                }
            }
        },
  {
            test:/\.(htm|html)$/,
            loader: 'html-withimg-loader'
        }

使用 file-loader 处理 JS 中的图片

package.json
"devDependencies": {
    "css-loader": "^4.1.1",
    "file-loader": "^6.0.0",
    "html-webpack-plugin": "^4.3.0",
    "mini-css-extract-plugin": "^0.9.0",
    "style-loader": "^1.2.1",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12"
  }
  <img src="./src/img/logo.png" alt="">
body{
    background-color: pink;
}
index.js
import './index.css';
import img from './img/logo.png';
console.log(img);
const imgEl = document.createElement('img');
imgEl.src=img;
document.body.appendChild(imgEl);

使用 url-loader 处理图片

  • 用于图标字体 npm install --save-dev url-loader@4.1.0
  • 大于 limit 的值,还是按照 file-loader 来处理
  • 小于,,则按 base64 处理

使用 webpack-dev-server 搭建开发环境

npm install --save-dev webpack-dev-server@3.11.0

  • "dev": "webpack-dev-server --open chrome"
index.js
import './index.css';
console.log('index2');
package.json
  "scripts": {
    "webpack": "webpack",
    "dev": "webpack-dev-server --open chrome"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^4.1.1",
    "html-webpack-plugin": "^4.3.0",
    "mini-css-extract-plugin": "^0.9.0",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
    }
webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        path: path.resolve('dist'),
        filename: '[name].js'
    },
    module: {
        rules: [{
            test: /\.css$/,
            use: [{loader: MiniCssExtractPlugin.loader,
                options: {
                    publicPath:'../'
                }
            }, 'css-loader']
        }]
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index.html',
            filename: 'index.html'
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ]
};

总结

喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
已稳定运行:3年255天5小时17分