前端工程化
1. ES6
- ECMAScript(ES) 是规范、 JavaScript 是 ES 的实现
- ES6 的第一个版本 在 2015 年 6 月发布,正式名称是《ECMAScript 2015 标准》(简称 ES2015)
- ES6 指是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017 等等
1.1. let
推荐使用let
关键字替代 var
关键字声明变量,因为 var
存在诸多问题,比如:
1.1.1. 越域
1 2 3 4 5 6 | { var a = 1; let b = 2; } console.log(a); // 1 console.log(b); // ReferenceError: b is not defined |
1.1.2. 重复声明
// var 可以声明多次 // let 只能声明一次 var m = 1 var m = 2 let n = 3 // let n = 4 console.log(m) // 2 console.log(n) // Identifier 'n' has already been declared
1.1.3. 变量提升
// var 会变量提升 // let 不存在变量提升 console.log(x); // undefined var x = 10; console.log(y); //ReferenceError: y is not defined let y = 20;
1.2. const
// 1. 声明之后不允许改变 // 2. 一但声明必须初始化,否则会报错 const a = 1; a = 3; //Uncaught TypeError: Assignment to constant variable.
1.3. 解构
1.3.1. 数组解构
let arr = [1, 2, 3]; //以前我们想获取其中的值,只能通过角标。ES6 可以这样: const [x, y, z] = arr;// x,y,z 将与 arr 中的每个位置对应来取值 // 然后打印 console.log(x, y, z);
1.3.2. 对象解构
const person = { name: "jack", age: 21, language: ['java', 'js', 'css'] } // 解构表达式获取值,将 person 里面每一个属性和左边对应赋值 const {name, age, language} = person; // 等价于下面 // const name = person.name; // const age = person.age; // const language = person.language; // 可以分别打印 console.log(name); console.log(age); console.log(language); //扩展:如果想要将 name 的值赋值给其他变量,可以如下,nn 是新的变量名 const {name: nn, age, language} = person; console.log(nn); console.log(age); console.log(language);
1.4. 链判断
如果读取对象内部的某个属性,往往需要判断一下,属性的上层对象是否存在。
比如,读取message.body.user.firstName这个属性,安全的写法是写成下面这样。
let message = null; // 错误的写法 const firstName = message.body.user.firstName || 'default'; // 正确的写法 const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default'; console.log(firstName)
这样的层层判断非常麻烦,因此 ES2020 引入了“链判断运算符”(optional chaining operator)?.,简化上面的写法。
const firstName = message?.body?.user?.firstName || 'default';
1.5. 参数默认值
//在 ES6 以前,我们无法给一个函数参数设置默认值,只能采用变通写法: function add(a, b) { // 判断 b 是否为空,为空就给默认值 1 b = b || 1; return a + b; } // 传一个参数 console.log(add(10)); //现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值 function add2(a, b = 1) { return a + b; } // 传一个参数 console.log(add2(10));
1.6. 箭头函数
//以前声明一个方法 // var print = function (obj) { // console.log(obj); // } // 可以简写为: let print = obj => console.log(obj); // 测试调用 print(100);
// 两个参数的情况: let sum = function (a, b) { return a + b; } // 简写为: //当只有一行语句,并且需要返回结果时,可以省略 {} , 结果会自动返回。 let sum2 = (a, b) => a + b; //测试调用 console.log(sum2(10, 10));//20 // 代码不止一行,可以用`{}`括起来 let sum3 = (a, b) => { c = a + b; return c; }; //测试调用 console.log(sum3(10, 20));//30
1.7. 模板字符串
let info = "你好,我的名字是:【"+name+"】,年龄是:【"+age+"】,邮箱是:【】" console.log(info); # 模板字符串的写法 let info = `你好,我的名字是:${name},年龄是:${person.age},邮箱是:${person.email}` console.log(info);
1.8. Promise
代表 异步对象
,类似Java中的 CompletableFuture
Promise 是现代 JavaScript 中异步编程的基础,是一个由异步函数返回的可以向我们指示当前操作所处的状态的对象。在 Promise 返回给调用者的时候,操作往往还没有完成,但 Promise 对象可以让我们操作最终完成时对其进行处理(无论成功还是失败)
fetch 是浏览器支持从远程获取数据的一个函数,这个函数返回的就是 Promise 对象
const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json" ); console.log(fetchPromise); fetchPromise.then((response) => { console.log(`已收到响应:${response.status}`); }); console.log("已发送请求……");
1.8.1. fetch api
fetch 是浏览器支持从远程获取数据的一个函数,这个函数返回的就是 Promise 对象
const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); console.log(fetchPromise); fetchPromise.then((response) => { console.log(`已收到响应:${response.status}`); }); console.log("已发送请求……");
通过 fetch() API 得到一个 Response 对象;
- response.status: 读取响应状态码
- response.json():读取响应体json数据;(这也是个异步对象)
const fetchPromise = fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); fetchPromise.then((response) => { const jsonPromise = response.json(); jsonPromise.then((json) => { console.log(json[0].name); }); });
1.8.2. Promise状态
首先,Promise 有三种状态:
- 待定(pending):初始状态,既没有被兑现,也没有被拒绝。这是调用 fetch() 返回 Promise 时的状态,此时请求还在进行中。
- 已兑现(fulfilled):意味着操作成功完成。当 Promise 完成时,它的 then() 处理函数被调用。
- 已拒绝(rejected):意味着操作失败。当一个 Promise 失败时,它的 catch() 处理函数被调用。
1.8.3. Promise对象
const promise = new Promise((resolve, reject) => { // 执行异步操作 if (/* 异步操作成功 */) { resolve(value);// 调用 resolve,代表 Promise 将返回成功的结果 } else { reject(error);// 调用 reject,代表 Promise 会返回失败结果 } });
示例:
let get = function (url, data) { return new Promise((resolve, reject) => { $.ajax({ url: url, type: "GET", data: data, success(result) { resolve(result); }, error(error) { reject(error); } }); }) }
1.9. Async 函数
async function 声明创建一个绑定到给定名称的新异步函数。函数体内允许使用 await 关键字,这使得我们可以更简洁地编写基于 promise 的异步代码,并且避免了显式地配置 promise 链的需要。
async 函数
是使用async关键字声明的函数
。async 函数是 AsyncFunction 构造函数的实例,并且其中允许使用 await 关键字。async 和 await
关键字让我们可以用一种更简洁的方式写出基于 Promise 的异步行为,而无需刻意地链式调用 promise。async 函数
返回的还是Promise对象
async function myFunction() { // 这是一个异步函数 }
在异步函数中,你可以在调用一个返回 Promise 的函数之前使用 await关键字。这使得代码在该点上等待,直到 Promise 被完成,这时 Promise 的响应被当作返回值,或者被拒绝的响应被作为错误抛出。
async function fetchProducts() { try { // 在这一行之后,我们的函数将等待 `fetch()` 调用完成 // 调用 `fetch()` 将返回一个“响应”或抛出一个错误 const response = await fetch( "https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/products.json", ); if (!response.ok) { throw new Error(`HTTP 请求错误:${response.status}`); } // 在这一行之后,我们的函数将等待 `response.json()` 的调用完成 // `response.json()` 调用将返回 JSON 对象或抛出一个错误 const json = await response.json(); console.log(json[0].name); } catch (error) { console.error(`无法获取产品列表:${error}`); } } fetchProducts();
1.10. 模块化
将 JavaScript 程序拆分为可按需导入的单独模块的机制。Node.js 已经提供这个能力很长时间了,还有很多的 JavaScript 库和框架已经开始了模块的使用(例如,CommonJS 和基于 AMD 的其他模块系统 如 RequireJS,以及最新的 Webpack 和 Babel)。
好消息是,最新的浏览器开始原生支持模块功能了。
1.10.2. index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="main.js" type="module"/> </head> <body> <h1>模块化测试</h1> </body> </html>
1.10.3. user.js
放在 libs/user.js
const user = { username: "张三", age: 18 } const isAdult = (age)=>{ if (age > 18){ console.log("成年人") }else { console.log("未成年") } } export {user,isAdult} // Java 怎么模块化; // 1、 druid.jar // 2、import 导入类 // JS 模块化; // 1、 xxx.js // 2、 xxx.js 暴露功能; // 3、import 导入 xxx.js 的功能 //xxx.js 暴露的功能,别人才能导入
1.10.4. main.js
// 所有的功能不用写在一个JS中 import {user,isAdult} from './libs/user.js' alert("当前用户:"+user.username) isAdult(user.age);
2. npm
npm 是 nodejs 中进行 包管理 的工具;
2.1. 环境
- 安装
Node.js
- 配置 npm
npm config set registry https://registry.npmmirror.com #设置国内阿里云镜像源 npm config get registry #查看镜像源
2.2. 命令
- npm init: 项目初始化;
- npm init -y:默认一路yes,不用挨个输入信息
- npm install 包名:安装js包到项目中(仅当前项目有效)。指定 包名,或者 包名@版本号
- npm install -g: 全局安装,所有都能用
- 可以去 npm仓库 搜索第三方库
- npm update 包名:升级包到最新版本
- npm uninstall 包名:卸载包
- npm run:项目运行
2.3. 使用流程
Java:
- 项目创建:Java环境 ==》 maven 初始化 ==》 添加依赖 ==》运行项目
- 项目迁移:Java环境 ==》 maven 下载依赖 ==》运行项目
3. Vite
3.1. 简介
官网:https://cn.vitejs.dev
- 快速创建前端项目脚手架
- 统一的工程化规范:目录结构、代码规范、git提交规范 等
- 自动化构建和部署:前端脚手架可以自动进行代码打包、压缩、合并、编译等常见的构建工作,可以通过集成自动化部署脚本,自动将代码部署到测试、生产环境等;
4.4. 基础使用
4.4.1. 插值
<script setup> //基本数据 let name = "张三" let age = 18 //对象数据 let car = { brand: "奔驰", price: 777 } </script> <template> <p> name: {{name}} </p> <p> age: {{age}} </p> <div style="border: 3px solid red"> <p>品牌:{{car.brand}}</p> <p>价格:{{car.price}}</p> </div> </template> <style scoped> </style>vue
4.4.2. 指令
看官方即可
https://cn.vuejs.org/api/built-in-directives.html
4.4.3. 属性绑定
- 使用
v-bind:属性='xx'
语法,可以为标签的某个属性绑定值; - 可以简写为
:属性='xx'
<script setup>
//
let url = "http://www.baidu.com"
</script>
<template>
<a v-bind:href="url">go</a>
<a :href="url">go</a>
</template>
<style scoped>
</style>
4.4.4. 响应式 - ref()
数据的动态变化需要反馈到页面;
Vue通过ref()
和reactive()
包装数据,将会生成一个数据的代理对象。vue内部的 基于依赖追踪的响应式系统 就会追踪感知数据变化,并触发页面的重新渲染。
4.4.4.1. 使用方式
使用步骤:
- 使用 ref() 包装原始类型、对象类型数据,生成 代理对象
- 任何方法、js代码中,使用
代理对象.value
的形式读取和修改值 - 页面组件中,直接使用
代理对象
注意:推荐使用 const(常量) 声明代理对象。代表代理对象不可变,但是内部值变化会被追踪。
<script setup> import { ref } from 'vue' const count = ref(0) function increment() { count.value++ } </script> <template> <button @click="increment"> {{ count }} </button> </template>
4.4.4.2. 深层响应性
import { ref } from 'vue' const obj = ref({ nested: { count: 0 }, arr: ['foo', 'bar'] }) function mutateDeeply() { // 以下都会按照期望工作 obj.value.nested.count++ obj.value.arr.push('baz') }
4.4.5. 响应式 - reactive()
使用步骤:
1使用 reactive() 包装对象类型数据,生成 代理对象
2任何方法、js代码中,使用 代理对象.属性的形式读取和修改值
3页面组件中,直接使用 代理对象.属性
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?