第三节:ES6模块化历史 及 默认、按需、直接导入导出、Vue单文件

一. 模块化历史

1. 浏览器端模块化

 (1). AMD(Asynchronous Module Definition,异步模块定义) :代表产品为:Require.js 

 (2). CMD(Common Module Definition,通用模块定义) :代表产品为:Sea.js

2. 服务器端模块化

服务器端的模块化规范是使用CommonJS规范:

 (1).使用require引入其他模块或者包

 (2).使用exports或者module.exports导出模块成员

 (3).一个文件就是一个模块,都拥有独立的作用域

3. 大一统的ES6模块化

 (1).每一个js文件都是独立的模块

 (2).导入模块成员使用import关键字

 (3).暴露模块成员使用export关键字

PS: 推荐使用ES6模块化,因为AMD,CMD局限使用与浏览器端,而CommonJS在服务器端使用。 ES6模块化是浏览器端和服务器端通用的规范. 

 

二. ES6模块化

1. 匹配规则

(1). 如果是完整路径,则直接引入 。eg:import moudleA from "./find.js";

(2). 如果不是完整路径,比如:import mA from  './find'

 A. 先找同名的js文件,即找 find.js

 B. 如果找不到,再找find文件夹,找到后,再匹配find文件夹中的index.js文件。

 C. 如果找不到index.js文件,会去当前文件夹中的package.json文件中查找main选项中的入口文件

 D. 全都没有的话,则报错

2. 默认导出、导入

(1). 默认导出

A. 模式1 (def1.js)

/*
   默认导出 
   1. 使用 export default 进行导出
   2. 1个js文件中只能有1个 export default
 */

// 1. 变量
let userName1 = 'ypf1';
let age1 = 20;

// 2. 方法
function getInfo1() {
    return {
        school1: 'bejing1',
        street1: 'zhonghan1'
    }
}

function getInfo2() {
    return "hello vue3";
}

// 对外导出
export default {
    userName1,
    age1,
    getInfo1,
    getInfo2
}

B. 模式2 (def2.js)

/*
   默认导出 
   1. 使用 export default function(){} 直接导出1个函数, 接收的时候仍然需要用对象接收

 */

export default function(){
    return {
        school2: 'bejing2',
        street2: 'zhonghan2'
    }
}

(2). 默认导入

A. 必须用一个对象接收,对象名任意,不加{}
B. 如果接收的是export default function(){}形式的导出,这里的接收对象,就直接是函数了

<script>
    /* 一. 接收默认导出 
     * 1. 必须用一个对象接收,对象名任意,不加{}
     * 2. 如果接收的是export default function(){}形式的导出,这里的接收对象,就直接是函数了
     */
    import myDef1 from './01_默认导出/def1.js';
    import myDef2 from './01_默认导出/def2.js';

    export default {
        setup() {
            // 一. 测试默认导出
            // 1. 形式1
            {
                console.log('-------测试默认导出_形式1------------')
                console.log(myDef1.userName1, myDef1.age1);
                var obj1 = myDef1.getInfo1();
                console.log(obj1.school1, obj1.street1);
                // 或者直接解构
                const { school1, street1 } = myDef1.getInfo1();
                console.log(school1, street1);
                var obj2 = myDef1.getInfo2();
                console.log(obj2);
            }
            // 2. 形式2
            {
                console.log('-------测试默认导出_形式2------------')
                var obj1 = myDef2(); //注:这里myDef2直接就是函数了
                console.log(obj1.school2, obj1.street2);
                // 或者直接解构
                const { school2, street2 } = myDef2();
                console.log(school2, street2);
            }
            
        }
    }
</script>

3. 按需导出、导入 

(1). 按需导出

 A. 使用 export + 变量,或 export +方法,进行逐个导出 (详见need1.js文件)

 B. 也可以先声明,然后通过 eport {} 进行选择性的导出   (详见need2.js文件)

 C. 以上两种方式共存 (详见need3.js) 

need1.js

// 1. 变量
export let userName1 = 'ypf1';
export let age1 = 20;

// 2. 方法
export function getInfo1() {
    return {
        school1: 'bejing1',
        street1: 'zhonghan1'
    }
}

export function getInfo2() {
    return "hello vue3";
}

need2.js

let age3=88;
let name3='ypf3';

function getInfo3(){
    return 'hello info3';
}

export {
    age3,
    getInfo3
}

need3.js

/*
   按需导出 
   1. 使用 export + 变量,或 export +方法, 与  eport {}   共存
 */

export let mySchool1='beijing1';

let mySchool2='beijing2';
function checkLogin(){
    return 'ok';
}
export {
    mySchool2,
    checkLogin
}

(2). 按需导入

 A. 必须使用 {} 接收,且接收的名称要和导出的名称一致

 B. 如果想改名称,可以使用as,比如 {userName1 as myName1}

<script>
    /* 二. 接收按需导出
     * 1. 必须使用 {} 接收,且接收的名称要和导出的名称一致
     * 2. 如果想改名称,可以使用as,比如 {userName1 as myName1}    
     */
    import { userName1, age1 as myAge1, getInfo1, getInfo2 } from './02_按需导出/need1.js';
    import { age3, getInfo3 } from './02_按需导出/need2.js';
    import {mySchool1,mySchool2,checkLogin} from './02_按需导出/need3.js';
    
    export default {
        setup() {
            
            // 二. 测试按需导出
            // 1. 形式1
            {
                console.log('-------测试按需导出_形式1------------')
                console.log(userName1, myAge1);
                var obj1 = getInfo1();
                console.log(obj1.school1, obj1.street1);
                // 或者直接解构
                const { school1, street1 } = getInfo1();
                console.log(school1, street1);
                var obj2 = getInfo2();
                console.log(obj2);
            }
            // 2.形式3
            {
                console.log('-------测试按需导出_形式2------------')
                console.log(age3);
                var obj1 = getInfo3();
                console.log(obj1);
            }
            // 3. 形式3-共存
            {
                console.log('-------测试按需导出_形式3_共存------------')
                console.log(mySchool1,mySchool2);
                var obj1 = checkLogin();
                console.log(obj1);
            }
        }
    }
</script>

4. 统一入口

 通过1个index.js文件作为中转,从而引入多个js 

 详见里面的hook封装位置:https://www.cnblogs.com/yaopengfei/p/15390818.html

5. 直接运行

// 四. 直接运行的代码
import './04_直接运行/test1.js'

注:如何运行呢?

 nodejs中不能直接执行ES的模块化写法,需要npm init一下,然后在package.json中,加上一句话:  "type": "module",  

 

三. Vue单文件

1. 传统Vue组件的缺陷

  全局定义的组件不能重名,字符串模板缺乏语法高亮,不支持css(当html和js组件化时,css没有参与其中)  没有构建步骤限制,只能使用H5和ES5,不能使用预处理器(babel)

2. 解决方案

 使用Vue单文件组件,每个单文件组件的后缀名都是.vue 每一个Vue单文件组件都由三部分组成

(1).template组件组成的模板区域

(2).script组成的业务逻辑区域

(3).style样式区域

代码如下: 

<template>

    组件代码区域

</template>

<script>

    js代码区域

</script>

<style scoped>

    样式代码区域

</style>

 

 

 

 

 

!

  • 作       者 : Yaopengfei(姚鹏飞)
  • 博客地址 : http://www.cnblogs.com/yaopengfei/
  • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
  • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
 

 

posted @ 2021-03-07 21:02  Yaopengfei  阅读(800)  评论(3编辑  收藏  举报