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 代码[重点]
- https://babeljs.io/setup#installation
- 在 package.json "scripts": { "build": "babel src -d lib" }, 创建一个目录 src,在其中创建 babel.js
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"]
}
- npm install --save-dev core-js@3.6.5
- 4.配置 babel-loader https://www.webpackjs.com/loaders/
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 中的图片
- npm install --save-dev html-withimg-loader@0.1.16
- esModule:false
<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'
})
]
};

