JS内容导出导入
项目目录引入
这部分非常重要,也是后面学习Web前端框架的基础部分的内容。这里不搞清楚的情况下去学Vue框架基本完蛋。这里先建立一个前端项目目录,通过该目录做演示。
纯前端项目的话就是分模块编写,一个功能一个模块,然后HTML文件负责演示,JS文件负责作为处理逻辑,然后CSS用于装饰。这里就忽略CSS,项目就简单的HTML+JS组成。
项目目录结构如下:
JsProject/ ├── main.js # 主入口 ├── index.html # 主页演示 │ ├── personal/ # 个人主页功能 │ ├── index.js # 总闸 │ ├── userInfo.js # 用户信息 + 头像 │ └── demo.html # 个人主页演示 │ └── utils/ # 工具函数 ├── index.js # 总闸 ├── format.js # 格式化 + 校验 └── request.js # 网络请求JS分文件编写
JS语言理解
因为实际前端项目用框架中.js文件大多都是拿来做配置文件,比如功能集中导入,路由配置等等。导致可能产生误解。所有这里需要先理清楚JS是一门前后端通吃的语言,甚至可以连接数据库。
JS和C、Python一样是写处理逻辑的语言,就上面项目目录为例:
personal/userInfo.js:用户数据管理(获取用户信息、更新头像、修改设置)utils/format.js:数据格式化(时间转字符串、金额加逗号、手机号脱敏)
每个.js文件都在干同一件事:接收输入 → 处理逻辑 → 输出结果。和C语言、Python没有本质区别,只是JS跑在浏览器里,处理的是点击、输入、请求这些用户交互。
直接说了大学里面的C语言期末大作业,比如写学生管理系统,JS也完全可以像C语言那么独立写出程序设计出来。
JS分文件编写
分文件编写的就是把代码按功能拆开,放到不同的文件里,最后再组合起来用。分文件的目录就是保持逻辑的清晰。其实就上述项目而言一个HTML文件+一个JS文件就能完全实现。
但项目稍微大点就难受了,想找一个函数翻半天,改一行代码怕影响别的地方。所以分文件不是为了"能不能跑",是为了"好不好维护"。
对比其他语言
JS的分文件编写和那个和C语言的分文件编写,Python的分模块编写,是一个意思。对比一下其他语言的做法如下:
| 语言 | 写法 | 作用 |
|---|---|---|
| C | #include "math.h" | 引入头文件 |
| Python | from utils import add | 导入模块 |
| JS | import {add} from './utils.js' | 导入模块 |
JS导出与导入
JS 文件写好功能,用export丢出去,另一个文件用import接过来用。JS中的导入和导出都用两种常见的方式。总结归纳如下:
| 默认导出/导入 | 命名导出/导入 | |
|---|---|---|
| 导出 | export default { name, add } | export const name = 'lqz' |
| 导入 | import 任意名 from | import { 固定名 } from |
| 名字 | 导入时随便取 | 导入时必须一样 |
| 数量 | 一个文件只能一个 | 一个文件可以多个 |
有无{} | 没有{} | 有{} |
默认导出
默认导出是一种集中的导出,把该.js文件下所有需要导出的内容写进一个export default声明里打包成一个对象导出。然后导入的时候也是看成一个对象导入,对象名由我们自己随意取。
export default声明
JS 的模块导出非常灵活,既可以导出单个变量/函数,也可以导出包含多个内容的对象。JS用export default声明出需要导出的内容。
语法格式
exportdefault{// 把要导出的东西全放这里}export default只能声明一次,所有你想导出的内容就只能放这里。整个.js文件就只能存在一个export default的声明。export default的作用就是把要导出的内容打包成一个对象,整体导出。
代码示例
把utils/format.js下的内容打包成对象导出。
constname='LeeChang'functionformatTime(date){returndate.toLocaleString('zh-CN')}functionformatMoney(amount){return'¥'+amount.toFixed(2)}// 把上面的变量和函数全部都导出exportdefault{name,formatTime,formatMoney}导入方式
export default声明导出后,就可以在别的地方使用。
代码示例
比如在main.js中,导入utils/format.js导出的内容。
// 导入时对象名,自己取,我就乱取bilbil了importbilbilfrom'./utils/format.js'console.log(bilbil.name)// 'LeeChang'console.log(bilbil.formatTime(newDate()))// 2026/6/24 14:30:00console.log(bilbil.formatMoney(99.9))// ¥99.90命名导出
命名导出是模块化开发中最常用的方式,它允许我们在每个变量、函数或类声明时直接加上export关键字,实现按需导出。导入时只需要拿自己需要的那部分。
export关键字
JS 使用export关键字标记需要导出的内容。与默认导出不同,命名导出可以有多个export关键字的声明,在需要导出的变量、函数、或者对象加上该关键字就导出了。
两种使用方式
语法格式1
// 方式一:声明时直接导出(常用)exportconstname='value'exportfunctionfn(){}语法格式2
// 方式二:先声明,再统一导出constname='value'functionfn(){}// 导出的时候可以用as重命名,当然也可以不重命名export{nameasuserName,fnasfunc}
关于语法格式二,容易和默认导出产生误解,命令导出是导出的对象是独立的,而默认方式导出的是整体打包成的对象,这决定了他们导入时候的方式。
代码示例
把用户信息模块personal/userInfo.js下的内容逐个导出。
// 常量导出exportconstuserName='LeeChang'exportconstuserAge=18// 函数导出exportfunctionupdateName(newName){console.log('姓名已更新为:',newName)}exportfunctionupdateAvatar(url){console.log('头像已更新:',url)}// 也可以先定义,再统一导出(等效写法)// const userName = 'LeeChang'// const userAge = 18// function updateName(newName) { ... }// export { userName, userAge, updateName, updateAvatar }导入方式
一个.js文件中可以存在任意多个export声明。每个export导出的内容都保留了自己的标识符名称,导入时必须使用对应的名称来引用。export声明导出后,有三种常见的导入方式。
代码示例
在main.js中导入用户信息模块personal/userInfo.js内容。
方式1:按需导入:只导入需要的部分,用
{}包裹,名称必须与导出时一致。// 只拿 userName 和 updateNameimport{userName,updateName}from'./personal/userInfo.js'console.log(userName)// 'LeeChang'updateName('Changli')// 姓名已更新为:Changli方式2:全部导入并起别名:用
* as 别名把所有导出内容打包成一个对象,通过对象属性访问。// 全部导入,挂载到 user 对象上import*asuserfrom'./personal/userInfo.js'console.log(user.userName)// 'LeeChang'console.log(user.userAge)// 18user.updateAvatar('/new.jpg')// 头像已更新:/new.jpg方式三:导入时重命名:当多个模块有同名导出时,用
as在导入时重命名避免冲突。// 导入时重命名import{userNameasname,updateNameasrename}from'./personal/userInfo.js'console.log(name)// 'LeeChang'rename('Changli')// 姓名已更新为:Changli
易疑惑点
导出是"白名单制度",你明确导出的才能被外部访问,没列在名单里的都是私有的,外部永远拿不到。要注意:"拿不到"指的是外部无法直接访问这个变量,而不是这个变量彻底消失了。
比如你导出一个函数,函数内部用到了其他变量,那个变量没导出。在你导入这个函数使用的时候,函数依然能正常运行,因为它内部的变量在定义时就绑定好了,闭包会把它们记住。外部拿不到那个变量,但函数自己能用。
所以正确理解是:私有变量对"外部代码"不可见,但对"内部函数"依然可见。
index.js文件机制
如果文件夹下有index.js,导入时可以只写到文件夹层级。这个机制依赖于 Node.js/Vite构建工具的模块解析规则:当导入路径指向一个文件夹时,系统会自动查找该文件夹下的index.js文件。
只有叫index.js的文件才能享受"只写到目录层"的简写待遇,其他.js文件必须手动写完整路径。
index.js作用
不用index.js文件
例如上面项目目录结构中的utils/文件夹里通常有多个功能相关的.js文件,如果一个个导入main.js中会非常繁琐:
// 这样太麻烦,要记住每个文件里有什么import{formatTime,formatMoney}from'./utils/format.js'import{request,api}from'./utils/request.js'使用index.js文件
由于index.js文件特殊的机制,如果在该文件夹中创建一个index.js文件,把其他的所有.js文件全部都导入进index.js中去,最后只用导入一个index.js就行。这样导入文件夹就相当于导入了该文件夹下所有.js文件。
// 把 format.js 和 request.js 的所有内容汇集起来,统一导出export*from'./format.js'export*from'./request.js'export * from './format.js'这是ES6语法,叫"重导出“,它做了两件事
- 导入
format.js里所有命名导出的内容 - 再直接导出这些内容
也就是先导入index.js后,再从index.js中又导出去。
main.js中导入:
// 只导入一个文件就行,自动找 utils/index.jsimport{formatTime,request}from'./utils'其实步骤没有省,但是逻辑非常清晰。
index文件总结
| 要点 | 说明 |
|---|---|
| 入口文件 | 文件夹下的index.js是默认入口 |
| 简写导入 | import {} from './personal'自动找personal/index.js |
| 作用是总闸 | 汇集文件夹内所有文件,统一对外导出 |
| 导出选择 | 命名导出(按需用)或默认导出(整体用)均可 |
不仅限于 JS 文件,Vue 框架中组件也常用这种模式。比如components/index.js把所有组件集中导出,外部一键导入所有组件。
导出方式选择
index.js在做统一导出时,命名导出和默认导出都能用,看需求:
命名导出和导入
// utils/index.js,命名导出export*from'./format.js'export*from'./request.js'// main.js,按需导入import{formatTime,request}from'./utils'默认导出和导入
// utils/index.js,默认导出// 默认导出不支持ES6那种重导出的写法import*asformatfrom'./format.js'import*asrequestfrom'./request.js'exportdefault{...format,...request}// main.js,整体导入importutilsfrom'./utils'utils.formatTime()utils.request()