前端工程化

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 中进行 包管理 的工具;

下载:https://nodejs.org/en

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. 使用方式

使用步骤:

  1. 使用 ref() 包装原始类型、对象类型数据,生成 代理对象
  2. 任何方法、js代码中,使用 代理对象.value 的形式读取和修改值
  3. 页面组件中,直接使用 代理对象

注意:推荐使用 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页面组件中,直接使用 代理对象.属性

 
import { reactive } from 'vue'

const state = reactive({ count: 0 })

<button @click="state.count++">
{{ state.count }}
</button>

基本类型用 ref(),对象类型用 reactive(),ref 要用 .valuereactive直接 . 。页面取值永不变。

也可以 ref 一把梭,大不了 天天 .value

4.4.6. 表单绑定

复制如下模板到组件,编写你的代码,实现表单数据绑定。

复制代码
<div style="display: flex;">
  <div style="border: 1px solid black;width: 300px">
    <form>
      <h1>表单绑定</h1>
      <p style="background-color: azure"><label>姓名(文本框):</label><input/></p>
      <p style="background-color: azure"><label>同意协议(checkbox):</label>
        <input type="checkbox"/>
      </p>
      <p style="background-color: azure">
        <label>兴趣(多选框):</label><br/>
        <label><input type="checkbox" value="足球"/>足球</label>
        <label><input type="checkbox" value="篮球"/>篮球</label>
        <label><input type="checkbox" value="羽毛球"/>羽毛球</label>
        <label><input type="checkbox" value="乒乓球"/>乒乓球</label>
      </p>
      <p style="background-color: azure">
        <label>性别(单选框):</label>
        <label><input type="radio" name="sex" value="男">男</label>
        <label><input type="radio" name="sex" value="女">女</label>
      </p>
      <p style="background-color: azure">
        <label>学历(单选下拉列表):</label>
        <select>
          <option disabled value="">选择学历</option>
          <option>小学</option>
          <option>初中</option>
          <option>高中</option>
          <option>大学</option>
        </select>
      </p>
      <p style="background-color: azure">
        <label>课程(多选下拉列表):</label>
        <br/>
        <select multiple>
          <option disabled value="">选择课程</option>
          <option>语文</option>
          <option>数学</option>
          <option>英语</option>
          <option>道法</option>
        </select>
      </p>
    </form>
  </div>
  <div style="border: 1px solid blue;width: 200px">
    <h1>结果预览</h1>
    <p style="background-color: azure"><label>姓名:</label></p>
    <p style="background-color: azure"><label>同意协议:</label>
    </p>
    <p style="background-color: azure">
      <label>兴趣:</label>
    </p>
    <p style="background-color: azure">
      <label>性别:</label>
    </p>
    <p style="background-color: azure">
      <label>学历:</label>
    </p>
    <p style="background-color: azure">
      <label>课程:</label>
</p> </div> </div>
复制代码

4.4.7. 计算属性 - computed

计算属性:根据已有数据计算出新数据

复制代码
<script setup>
import {computed, reactive, toRef, toRefs} from "vue";

//省略基础代码

const totalPrice = computed(()=>{
  return price.value * num.value - coupon.value*100
})

</script>

<template>
  <div class="car">
    <h2>优惠券:{{ car.coupon }} 张</h2>
    <h2>数量:{{ car.num }}</h2>
    <h2>单价:{{ car.price }}</h2>
    <h1>总价:{{totalPrice}}</h1>
    <button @click="getCoupon">获取优惠</button>
    <button @click="addNum">加量</button>
    <button @click="changePrice">加价</button>
  </div>

</template>

<style scoped>

</style>
复制代码

4.5. 进阶用法

4.5.1. 监听 - watch

watch(num, (value, oldValue, onCleanup) => {
  console.log("newValue:" + value + ";oldValue:" + oldValue)
  onCleanup(() => {
    console.log("onCleanup....")
  })
})

4.5.2. 生命周期

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。

在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码。

 

生命周期整体分为四个阶段,分别是:创建、挂载、更新、销毁,每个阶段都有两个钩子,一前一后。

常用的钩子:

  • onMounted(挂载完毕)
  • onUpdated(更新完毕)
  • onBeforeUnmount(卸载之前)
复制代码
<script setup>
import {onBeforeMount, onBeforeUpdate, onMounted, onUpdated, ref} from "vue";
const  count = ref(0)
const btn01 = ref()

// 生命周期钩子
onBeforeMount(()=>{
  console.log('挂载之前',count.value,document.getElementById("btn01"))
})
onMounted(()=>{
  console.log('挂载完毕',count.value,document.getElementById("btn01"))
})
onBeforeUpdate(()=>{
  console.log('更新之前',count.value,btn01.value.innerHTML)
})
onUpdated(()=>{
  console.log('更新完毕',count.value,btn01.value.innerHTML)
})
</script>

<template>
  <button ref="btn01" @click="count++"> {{count}} </button>
</template>

<style scoped>
</style>
复制代码

4.5.3. 组件传值

4.5.3.1. 父传子 - Props

父组件给子组件传递值;

单向数据流效果:

  • 父组件修改值,子组件发生变化
  • 子组件修改值,父组件不会感知到
复制代码
//父组件给子组件传递数据:使用属性绑定
<Son :books="data.books" :money="data.money"/>
  
//子组件定义接受父组件的属性
let props = defineProps({
  money: {
    type: Number,
    required: true,
    default: 200
  },
  books: Array
});
复制代码

4.5.3.2. 子传父 - Emit

props 用来父传子,emit 用来子传父

复制代码
//子组件定义发生的事件
let emits = defineEmits(['buy']);
function buy(){
  // props.money -= 5;
  emits('buy',-5);
}

//父组件感知事件和接受事件值
  <Son :books="data.books" :money="data.money"
       @buy="moneyMinis"/>
复制代码

4.5.4. 插槽 - Slots

子组件可以使用插槽接受模板内容。

4.5.4.1. 基本使用

复制代码
<!-- 组件定义 -->
<button class="fancy-btn">
  <slot></slot> <!-- 插槽出口 -->
</button>

<!-- 组件使用 -->
<FancyButton>
  Click me! <!-- 插槽内容 -->
</FancyButton>
复制代码

4.5.4.2. 默认内容

<button type="submit">
  <slot>
    Submit <!-- 默认内容 -->
  </slot>
</button>

4.5.4.3. 具名插槽

定义

复制代码
<div class="container">
  <header>
    <slot name="header"></slot>
  </header>
  <main>
    <slot></slot>
  </main>
  <footer>
    <slot name="footer"></slot>
  </footer>
</div>
复制代码

使用: v-slot可以简写为 #

<BaseLayout>
  <template v-slot:header>
    <!-- header 插槽的内容放这里 -->
  </template>
</BaseLayout>

4.6. 总结

 

几个简写:

  • v-on=@
  • v-bind= :
  • v-slot= #

 

posted @   佳沃  阅读(13)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示