【JavaWeb】前端工程化(VUE3)

前端工程化(VUE3)

文章目录

  • 前端工程化(VUE3)
  • 一、概述
  • 二、ECMA6Script
    • 2.1 es6的变量和模板字符串
    • 2.2 es6的解构表达式
    • 2.3 es6的箭头函数
    • 2.4 rest和spread
    • 2.5 es6的对象创建和拷贝
    • 2.6 es6的模块化处理
  • 三、前端工程化环境搭建
    • 3.1 Node.js
    • 3.2 npm
      • 3.2.1 npm的配置
      • 3.2.2 npm 常用命令
  • 四、Vue3简介和快速体验
  • 五、Vue3通过Vite实现工程化
    • 5.1 Vite 简介
    • 5.2 Vite创建Vue3工程化项目
    • 5.3 Vite+Vue3项目的目录结构
    • 5.4 Vite+Vue3项目组件(SFC入门)
    • 5.5 Vite+Vue3关于样式的导入方式
    • 5.6 Vite+Vue3响应式和setup函数
    • 5.7 关于JS和TS选择的问题
  • 六、Vue3视图渲染技术
    • 6.1 模板语法
    • 6.2 条件渲染
    • 6.3 列表渲染
    • 6.4 属性计算
    • 6.5 数据监听器
    • 6.6 生命周期
    • 6.7 组件之前传递数据
  • 七、Vue3路由机制router
    • 7.1 路由入门配置
    • 7.2 编程式路由(useRouter)
    • 7.3 路由传参(useRoute)
    • 7.4 路由守卫
  • 八、promise
    • 8.1 基本用法
    • 8.2 catch()
    • 8.3 async和await的使用
  • 九、数据交互axios
    • 9.1 基本用法
    • 9.2 Axios get和post方法
    • 9.3 Axios 拦截器
  • 十、跨域问题
  • 十一、Pinia
    • 11.1 基本用法
    • 11.2 Pinia其他细节
  • 十二、Element Plus

一、概述

前端工程化 是使用 软件工程的方法单独 解决 前端 的开发流程中 模块化、组件化、规范化、自动化 的问题,其主要目的为了提高效率和降低成本。

前端工程化实现的技术栈有很多,我们采用 ES6+nodejs+npm+Vite+VUE3+router+pinia+axios+Element-plus 组合来实现

  • ECMAScript6 VUE3中大量使用ES6语法
  • Nodejs 前端项目运行环境
  • npm 依赖下载工具
  • vite 前端项目构建工具
  • VUE3 优秀的渐进式前端框架
  • router 通过路由实现页面切换
  • pinia 通过状态管理实现组件数据传递
  • axios ajax异步请求封装技术实现前后端数据交互
  • Element-plus 可以提供丰富的快速构建网页的组件仓库

二、ECMA6Script

ECMAScript 6,简称ES6,是JavaScript语言的一次重大更新。它于2015年发布,是原来的ECMAScript标准的第六个版本。ES6带来了大量的新特性,包括箭头函数、模板字符串、let和const关键字、解构、默认参数值、模块系统等等

2.1 es6的变量和模板字符串

ES6 新增了 letconst ,用来声明变量,使用的细节上也存在诸多差异

  • let 和var的差别:let 与 java中变量的定义类似
    • let不能重复声明
    • let有块级作用域,非函数的花括号遇见let会有块级作用域,也就是只能在花括号里面访问
    • let不会预解析进行变量提升
    • let定义的全局变量不会作为window的属性
    • let在es6中推荐优先使用
  • const和var的差异:const 与 java 中被 final 变量类似

模板字符串(template string)是增强版的字符串,用反引号(`)标识,会原样记录字符串,可以使用 ${xxx} 形式输出变量和拼接变量

const times = '3次';
let str = `${times}
够不够?`;
console.log(str);

2.2 es6的解构表达式

let [a, b, c] = [1, 2, 3]; // 数组解构赋值
let {a, b} = {a: 1, b: 2}; // 对象解构赋值

function add([x, y]) {
  return x + y;
}
add([1, 2]); // 函数参数解构赋值

2.3 es6的箭头函数

  1. 函数声明
let fn1 = function(){}
let fn2 = ()=>{} //箭头函数,此处不需要书写function关键字
let fn3 = x =>{} //单参数可以省略(),多参数无参数不可以!
let fn4 = x => console.log(x) //只有一行方法体可以省略{};
let fun5 = x => x + 1 //当函数体只有一句返回值时,可以省略花括号和 return 语句
  1. 使用特点:箭头函数this关键字

在 JavaScript 中,this 关键字通常用来引用函数所在的对象,或者在函数本身作为构造函数时,来引用新对象的实例。但是在箭头函数中,this 的含义与常规函数定义中的含义不同,是由箭头函数定义时的上下文来决定的,而不是由函数调用时的上下文来决定的。箭头函数没有自己的this,this指向的是外层上下文环境的this

let person ={
    name:"张三",
    showName:function (){
        console.log(this) //  这里的this是person
        console.log(this.name)
    },
    viewName: () =>{
        console.log(this) //  这里的this是window
        console.log(this.name)
    }
}
person.showName()
person.viewName()

//this应用
function Counter() {
    this.count = 0;
    window.setInterval(() => {
        // 这里的 this 是上一层作用域中的 this,即 Counter实例化对象;如果用func的方式则this指window
        this.count++;
        console.log(this.count);
    }, 1000);
}
let counter = new Counter();

2.4 rest和spread

rest参数,在形参上使用和JAVA中的可变参数几乎一样

let fun = (...args) =>{console.log(args)}

spread参数,在函数调用实参上使用rest;还可以快速合并数组或者对象

// 1. 函数实参
let a = [1,2,3];
fun(...a); // 如果传 a,则a整体会被当成一个数组作为参数传给方法fun,用 ...a 则 a 中每个元素都会单独作为一个参数传入fun函数中执行
// 2. 合并数组
let a = [1,2,3];
let b = [4,5,6];
let c = [...a,...b]; // [1,2,3,4,5,6]
// 3.合并对象
let a = { x: 'm', y: 'h'};
let b = { y: 'n'};
let c = {...a, ...b}; // {x: 'm', y: 'n'}

2.5 es6的对象创建和拷贝

ES6中新增了对象创建的语法糖,支持了class extends constructor等关键字,让ES6的语法和面向对象的语法更加接近

class Person{
      // 属性
      #n;
      age;
      get name(){
          return this.n;
      }
      set name(n){
          this.n =n;
      }
      // 实例方法
      eat(food){
          console.log(this.age+"岁的"+this.n+"用筷子吃"+food)
      }
      // 静态方法
      static sum(a,b){
          return a+b;
      }
      // 构造器
      constructor(name,age){
          this.n=name;
          this.age = age;
      }
  }
  let person =new Person("张三",10);
  // 访问对象属性
  // 调用对象方法
  console.log(person.name)
  console.log(person.n)
  person.name="小明"
  console.log(person.age)
  person.eat("火锅")
  console.log(Person.sum(1,2))

  class Student extends  Person{
      grade ;
      score ;
      study(){
      }
      constructor(name,age ) {
          super(name,age);
      }
  }

  let stu =new Student("学生小李",18);
  stu.eat("面条")

深拷贝

let arr  =['java','c','python'];
let person ={
    name:'张三',
    language:arr
};
// 深拷贝,通过JSON和字符串的转换形成一个新的对象
let person2 = JSON.parse(JSON.stringify(person));

2.6 es6的模块化处理

目前,前端模块化有多种规范和实现,包括 CommonJS、AMD 和 ES6 模块化。ES6 模块化是 JavaScript 语言的模块标准,使用 import 和 export 关键字来实现模块的导入和导出。现在,大部分浏览器都已经原生支持 ES6 模块化,因此它成为了最为广泛使用的前端模块化标准.

  • ES6模块化的几种暴露和导入方式
    1. 分别导出:对每个需要导出的变量或方法前加 export,如 export PI
    2. 统一导出:模式适用 export 并将需要导出变量或方法放入 export 大括号内,如 export { A, B ,C }
    3. 默认导出:export default PI 一个文件中只能写一个,代表默认的导出对象
  • ES6中无论以何种方式导出,导出的都是一个对象,导出的内容都可以理解为是向这个对象中添加属性或者方法
  • 导入:
import * as m1 from './module.js'
import {PI ,Person ,sum,PI as pi,Person as People,sum as add}  from './module.js'
import {default as add} from './module.js' // 用的少
import add2 from './module.js' // 等效于 import {default as add2} from './module.js'

三、前端工程化环境搭建

3.1 Node.js

Node.js 相对 js 而言相当于Java的虚拟机。Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时环境,可以使 JavaScript 运行在服务器端。使用 Node.js,可以方便地开发服务器端应用程序,如 Web 应用、API、后端服务,还可以通过 Node.js 构建命令行工具等。Node.js 底层用 C++ 编写,运行速度快。Node.js是单线程,但是采用了事件驱动、异步 I/O 模型,可以处理高并发请求。

在 Node.js 中,我们可以使用 JavaScript 来编写服务器端程序,这也使得前端开发人员可以利用自己已经熟悉的技能来开发服务器端程序,同时也让 JavaScript 成为一种全栈语言

下载与安装

  1. 打开官网https://nodejs.org/en下载对应操作系统的 LTS 版本。
  2. 双击安装包进行安装,安装过程中遵循默认选项即可(或者参照https://www.runoob.com/nodejs/nodejs-install-setup.html )。安装完成后,可以在命令行终端输入 node -vnpm -v 查看 Node.js 和 npm 的版本号。

3.2 npm

npm 相当于 java maven 的依赖管理功能。安装了上述 node.js 会自动安装 npm。

3.2.1 npm的配置

npm 安装依赖包时默认使用的是官方源,由于国内网络环境的原因,有时会出现下载速度过慢的情况。为了解决这个问题,可以配置使用阿里镜像来加速 npm 的下载速度,具体操作如下:

npm config set registry https://registry.npmmirror.com

原:https://registry.npmjs.org/ 将替换为 https://registry.npmmirror.com

npm config get registry

恢复官方源可执行下面语句

npm config set registry https://registry.npmjs.org/

配置全局依赖下载后存储位置:默认位置 <用户目录>\AppData\Roaming\npm

npm config set prefix "D:\softwareData\npmRepository"

查看依赖存储位置:

npm config get prefix

npm 升级命令

npm install -g [email protected]

3.2.2 npm 常用命令

  1. 项目初始化
    • npm init :进入一个vscode创建好的项目中, 执行 npm init 命令后,npm 会引导您在命令行界面上回答一些问题,例如项目名称、版本号、作者、许可证等信息,并最终生成一个package.json 文件。package.json信息会包含项目基本信息,类似maven的pom.xml
    • npm init -y :-y yes的意思,所有信息使用当前文件夹的默认值,不用挨个填写
  2. 安装依赖 (查看所有依赖地址 https://www.npmjs.com )
    • npm install 包名 或者 npm install 包名@版本号 :安装包或者指定版本的依赖包(安装到当前项目中)
    • npm install -g 包名 :安装全局依赖包(安装到 D:\softwareData\npmRepository )则可以在任何项目中使用它,而无需在每个项目中独立安装该包
    • npm install :安装package.json中的所有记录的依赖
  3. 升级依赖
    • npm update 包名 :将依赖升级到最新版本
  4. 卸载依赖
    • npm uninstall 包名
  5. 查看依赖
    • npm ls :查看项目依赖
    • npm list -g :查看全局依赖
  6. 运行命令
    • npm run :执行 npm 脚本时使用的命令。npm 脚本是一组在 package.json 文件中定义的可执行命令。npm 脚本可用于启动应用程序,运行测试,生成文档等,还可以自定义命令以及配置需要运行的脚本。
      • 在 package.json 文件中,scripts 字段是一个对象,其中包含一组键值对,键是要运行的脚本的名称,值是要执行的命令。
      • scripts 对象包含 start、test 和 build 三个脚本。当您运行 npm run start 时,将运行 node index.js,并启动应用程序。同样,运行 npm run test 时,将运行 Jest 测试套件,而 npm run build 将运行 webpack 命令以生成最终的构建输出

四、Vue3简介和快速体验

Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。官网为: https://cn.vuejs.org/

Vue的两个核心功能

  • 声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,使得我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系
  • 响应性:Vue 会自动跟踪 JavaScript 状态并在其发生变化时响应式地更新 DOM

Vue3快速体验(非工程化方式)

DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Documenttitle>
    head>
    <body>
        
        <script src="https://unpkg.com/vue@3/dist/vue.global.js">script>
        <div id="app">
            
            
           <h1 v-bind:style="colorStyle">{{headline}}h1>
           
           <p v-text="article">p>
           
           <input v-bind:type ="inputType" value="helloVue3"> <br>
           
           <button  @click="sayHello()">hellobutton>
        div>

        <script>
            //组合api
            const app = Vue.createApp({
                // 在setup内部自由声明数据和方法即可!最终返回!
                setup(){
                    //定义数据
                    //在VUE中实现DOM的思路是: 通过修改修数据而影响页面元素
                    // vue3中,数据默认不是响应式的,需要加ref或者reactive处理,后面会详细讲解
                    let inputType ='text'
                    let headline ='hello vue3'
                    let article ='vue is awesome'  
                    let colorStyle ={'color':'red'}        
                    // 定义函数
                    let sayHello =()=>{
                        alert("hello Vue")
                    }
                    //在setup函数中,return返回的数据和函数可以在html使用
                    return {
                       inputType,
                       headline,
                       article,
                       colorStyle,
                       sayHello
                    }
                }
            });
            //挂载到视图
            app.mount("#app");
        script>
    body>
html>

五、Vue3通过Vite实现工程化

5.1 Vite 简介

Vite作用相当于 Java 中 maven 的项目管理功能

Vite 旨在利用生态系统中的新进展解决前端项目管理问题:浏览器开始原生支持 ES 模块,且越来越多 JavaScript 工具使用编译型语言编写。https://cn.vitejs.dev/guide/why.html前端工程化的作用包括但不限于以下几个方面:

  1. 快速创建项目:使用脚手架可以快速搭建项目基本框架,避免从零开始搭建项目的重复劳动和繁琐操作,从而节省时间和精力。
  2. 统一的工程化规范:前端脚手架可以预设项目目录结构、代码规范、git提交规范等统一的工程化规范,让不同开发者在同一个项目上编写出风格一致的代码,提高协作效率和质量。
  3. 代码模板和组件库:前端脚手架可以包含一些常用的代码模板和组件库,使开发者在实现常见功能时不再重复造轮子,避免因为轮子质量不高带来的麻烦,能够更加专注于项目的业务逻辑。
  4. 自动化构建和部署:前端脚手架可以自动进行代码打包、压缩、合并、编译等常见的构建工作,可以通过集成自动化部署脚本,自动将代码部署到测试、生产环境等。

5.2 Vite创建Vue3工程化项目

项目创建:项目目录下执行命令:执行后会出现选项选择框架。选择生成后,进入项目目录,执行 npm install

npm create vite@latest
cd .\vite-project\
npm install

package.json

{
  "name": "vite-project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
    "build": "vite build", // 为生产环境构建产物
    "preview": "vite preview" // 本地预览生产构建产物
  },
  "dependencies": {
    "vue": "^3.3.8"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^4.5.0",
    "vite": "^5.0.0"
  }
}

scripts 中即可运行选项,这里执行命令启动本地开发环境

npm run dev

5.3 Vite+Vue3项目的目录结构

  • public/ 目录 :用于存放一些公共资源,如 HTML 文件、图像、字体等,这些资源会被直接复制到构建出的目标目录中。
  • src/ 目录 :存放项目的源代码,包括 JavaScript、CSS、Vue 组件、图像和字体等资源。在开发过程中,这些文件会被 Vite 实时编译和处理,并在浏览器中进行实时预览和调试。以下是src内部划分建议:
    1. assets/ 目录:用于存放一些项目中用到的静态资源,如图片、字体、样式文件等。
    2. components/ 目录:用于存放组件相关的文件。组件是代码复用的一种方式,用于抽象出一个可复用的 UI 部件,方便在不同的场景中进行重复使用。
    3. layouts/ 目录:用于存放布局组件的文件。布局组件通常负责整个应用程序的整体布局,如头部、底部、导航菜单等。
    4. pages/ 目录:用于存放页面级别的组件文件,通常是路由对应的组件文件。在这个目录下,可以创建对应的文件夹,用于存储不同的页面组件。
    5. plugins/ 目录:用于存放 Vite 插件相关的文件,可以按需加载不同的插件来实现不同的功能,如自动化测试、代码压缩等。
    6. router/ 目录:用于存放 Vue.js 的路由配置文件,负责管理视图和 URL 之间的映射关系,方便实现页面之间的跳转和数据传递。
    7. store/ 目录:用于存放 Vuex 状态管理相关的文件,负责管理应用程序中的数据和状态,方便统一管理和共享数据,提高开发效率。
    8. utils/ 目录:用于存放一些通用的工具函数,如日期处理函数、字符串操作函数等。
  • vite.config.js 文件:Vite 的配置文件,可以通过该文件配置项目的参数、插件、打包优化等。该文件可以使用 CommonJS 或 ES6 模块的语法进行配置。
  • package.json 文件:标准的 Node.js 项目配置文件,包含了项目的基本信息和依赖关系。其中可以通过 scripts 字段定义几个命令,如 dev、build、serve 等,用于启动开发、构建和启动本地服务器等操作。
  • Vite 项目的入口为 src/main.js 文件,这是 Vue.js 应用程序的启动文件,也是整个前端应用程序的入口文件。在该文件中,通常会引入 Vue.js 及其相关插件和组件,同时会创建 Vue 实例,挂载到 HTML 页面上指定的 DOM 元素中。

vite的运行界面

  • 在安装了 Vite 的项目中,可以在 npm scripts 中使用 vite 可执行文件,或者直接使用 npx vite 运行它。下面是通过脚手架创建的 Vite 项目中默认的 npm scripts:(package.json)
{
  "scripts": {
    "dev": "vite", // 启动开发服务器,别名:`vite dev`,`vite serve`
    "build": "vite build", // 为生产环境构建产物
    "preview": "vite preview" // 本地预览生产构建产物
  }
}
  • 运行设置端口号:(vite.config.js)
//修改vite项目配置文件 vite.config.js
export default defineConfig({
  plugins: [vue()],
  server:{
    port:3000
  }
})

5.4 Vite+Vue3项目组件(SFC入门)

什么是VUE的组件?

  • 一个页面作为整体,是由多个部分组成的,每个部分在这里就可以理解为一个组件,每个.vue文件就可以理解为一个组件,多个.vue文件可以构成一个整体页面

【JavaWeb】前端工程化(VUE3)_第1张图片

  • 传统的页面有.html文件.css文件和.js文件三个文件组成(多文件组件)

  • vue将这文件合并成一个.vue文件(Single-File Component,简称 SFC,单文件组件)

  • .vue文件对js/css/html统一封装,这是VUE中的概念 该文件由三个部分组成

    7.3 路由传参(useRoute)

    路径参数:如 /showDetail/:id

    • 路径参数首先要在 router.js 配置的路由上加上 /:参数名 表示路由参数
    • 发送时可用路径直接发送或者使用:useRouter 返回的对象调用 router.push({name:"showDetail",params:{id:id,language:language}})
    • 接收时使用 useRoute 返回的对象的 params 属性获取

    键值对参数:如 /showDetail?hid=1 ,则将上述 params 替换成 query 属性即可

    7.4 路由守卫

    1. 全局前置守卫:在路由切换前被调用,可以用于验证用户是否已登录、中断导航、请求数据等
    2. 全局后置守卫:在路由切换之后被调用,可以用于处理数据、操作 DOM 、记录日志等
    3. 守卫代码的位置: 在 router.js
    //全局前置路由守卫
    router.beforeEach( (to,from,next) => {
        //to 是目标地包装对象  .path属性可以获取地址
        //from 是来源地包装对象 .path属性可以获取地址
        //next是方法,不调用默认拦截! next() 放行,直接到达目标组件
        //next('/地址')可以转发到其他地址,到达目标组件前会再次经过前置路由守卫
        console.log(to.path,from.path,next)
    
        //需要判断,注意避免无限重定向
        if(to.path == '/index'){
            next()
        }else{
            next('/index')
        }
        
    } )
    
    //全局后置路由守卫
    router.afterEach((to, from) => {
        console.log(`Navigate from ${from.path} to ${to.path}`);
    });
    

    八、promise

    前端中的异步编程技术,类似Java中的多线程+线程结果回调

    • Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象
    • 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理

    Promise对象有以下两个特点。

    1. Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
    2. 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。

    8.1 基本用法

        
    

    8.2 catch()

    Promise.prototype.catch 方法是 .then(null, rejection) 的别名,用于指定发生错误时的回调函数。

    
    

    8.3 async和await的使用

    async/await 是在Promise基础上提供了更加直观和易于使用的语法。

    async 用于标识函数

    1. async标识函数后,async函数的返回值会变成一个promise对象
    2. 如果函数内部返回的数据是一个非promise对象,async函数的结果会返回一个成功状态 promise对象
    3. 如果函数内部返回的是一个promise对象,则async函数返回的状态与结果由该对象决定
    4. 如果函数内部抛出的是一个异常,则async函数返回的是一个失败的promise对象

    await :获取一个 promise 对象的成功值,失败则会抛异常

    1. await右侧的表达式一般为一个promise对象,但是也可以是一个其他值
    2. 如果表达式是promise对象,await返回的是promise成功的值
    3. await会等右边的promise对象执行结束,然后再获取结果,后续代码也会等待await的执行
    4. 如果表达式是其他值,则直接返回该值
    5. await必须在async函数中
    6. 如果await右边的promise失败了,就会抛出异常,需要通过 try … catch捕获处理

    九、数据交互axios

    Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

    原生javascript方式进行ajax(了解):

       
    

    9.1 基本用法

    使用 axios 前需先安装

    npm install axios
    

    使用:

    
    

    response 响应数据:

    {
      data: {}, // `data` 由服务器提供的响应
      status: 200, // `status` 来自服务器响应的 HTTP 状态码
      statusText: 'OK', // `statusText` 来自服务器响应的 HTTP 状态信息
      // `headers` 是服务器响应头
      // 所有的 header 名称都是小写,而且可以使用方括号语法访问
      // 例如: `response.headers['content-type']`
      headers: {},
      config: {}, // `config` 是 `axios` 请求的配置信息
      // `request` 是生成此响应的请求
      // 在node.js中它是最后一个ClientRequest实例 (in redirects),
      // 在浏览器中则是 XMLHttpRequest 实例
      request: {}
    }
    

    axios在发送异步请求时的可选配置:

    {
      // `url` 是用于请求的服务器 URL
      url: '/user',
      // `method` 是创建请求时使用的方法
      method: 'get', // 默认值
      // `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。
      // 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL
      baseURL: 'https://some-domain.com/api/',
      // `transformRequest` 允许在向服务器发送前,修改请求数据
      // 它只能用于 'PUT', 'POST' 和 'PATCH' 这几个请求方法
      // 数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream
      // 你可以修改请求头。
      transformRequest: [function (data, headers) {
        // 对发送的 data 进行任意转换处理
        return data;
      }],
      // `transformResponse` 在传递给 then/catch 前,允许修改响应数据
      transformResponse: [function (data) {
        // 对接收的 data 进行任意转换处理
        return data;
      }],
      // 自定义请求头
      headers: {'X-Requested-With': 'XMLHttpRequest'},
      // `params` 是与请求一起发送的 URL 参数
      // 必须是一个简单对象或 URLSearchParams 对象
      params: {
        ID: 12345
      },
      // `paramsSerializer`是可选方法,主要用于序列化`params`
      // (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
      paramsSerializer: function (params) {
        return Qs.stringify(params, {arrayFormat: 'brackets'})
      },
      // `data` 是作为请求体被发送的数据
      // 仅适用 'PUT', 'POST', 'DELETE 和 'PATCH' 请求方法
      // 在没有设置 `transformRequest` 时,则必须是以下类型之一:
      // - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
      // - 浏览器专属: FormData, File, Blob
      // - Node 专属: Stream, Buffer
      data: {
        firstName: 'Fred'
      },
      // 发送请求体数据的可选语法
      // 请求方式 post
      // 只有 value 会被发送,key 则不会
      data: 'Country=Brasil&City=Belo Horizonte',
      // `timeout` 指定请求超时的毫秒数。
      // 如果请求时间超过 `timeout` 的值,则请求会被中断
      timeout: 1000, // 默认值是 `0` (永不超时)
      // `withCredentials` 表示跨域请求时是否需要使用凭证
      withCredentials: false, // default
      // `adapter` 允许自定义处理请求,这使测试更加容易。
      // 返回一个 promise 并提供一个有效的响应 (参见 lib/adapters/README.md)。
      adapter: function (config) {
        /* ... */
      },
      // `auth` HTTP Basic Auth
      auth: {
        username: 'janedoe',
        password: 's00pers3cret'
      },
      // `responseType` 表示浏览器将要响应的数据类型
      // 选项包括: 'arraybuffer', 'document', 'json', 'text', 'stream'
      // 浏览器专属:'blob'
      responseType: 'json', // 默认值
      // `responseEncoding` 表示用于解码响应的编码 (Node.js 专属)
      // 注意:忽略 `responseType` 的值为 'stream',或者是客户端请求
      // Note: Ignored for `responseType` of 'stream' or client-side requests
      responseEncoding: 'utf8', // 默认值
      // `xsrfCookieName` 是 xsrf token 的值,被用作 cookie 的名称
      xsrfCookieName: 'XSRF-TOKEN', // 默认值
      // `xsrfHeaderName` 是带有 xsrf token 值的http 请求头名称
      xsrfHeaderName: 'X-XSRF-TOKEN', // 默认值
      // `onUploadProgress` 允许为上传处理进度事件
      // 浏览器专属
      onUploadProgress: function (progressEvent) {
        // 处理原生进度事件
      },
      // `onDownloadProgress` 允许为下载处理进度事件
      // 浏览器专属
      onDownloadProgress: function (progressEvent) {
        // 处理原生进度事件
      },
      // `maxContentLength` 定义了node.js中允许的HTTP响应内容的最大字节数
      maxContentLength: 2000,
      // `maxBodyLength`(仅Node)定义允许的http请求内容的最大字节数
      maxBodyLength: 2000,
      // `validateStatus` 定义了对于给定的 HTTP状态码是 resolve 还是 reject promise。
      // 如果 `validateStatus` 返回 `true` (或者设置为 `null` 或 `undefined`),
      // 则promise 将会 resolved,否则是 rejected。
      validateStatus: function (status) {
        return status >= 200 && status < 300; // 默认值
      },
      // `maxRedirects` 定义了在node.js中要遵循的最大重定向数。
      // 如果设置为0,则不会进行重定向
      maxRedirects: 5, // 默认值
      // `socketPath` 定义了在node.js中使用的UNIX套接字。
      // e.g. '/var/run/docker.sock' 发送请求到 docker 守护进程。
      // 只能指定 `socketPath` 或 `proxy` 。
      // 若都指定,这使用 `socketPath` 。
      socketPath: null, // default
      // `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
      // and https requests, respectively, in node.js. This allows options to be added like
      // `keepAlive` that are not enabled by default.
      httpAgent: new http.Agent({ keepAlive: true }),
      httpsAgent: new https.Agent({ keepAlive: true }),
      // `proxy` 定义了代理服务器的主机名,端口和协议。
      // 您可以使用常规的`http_proxy` 和 `https_proxy` 环境变量。
      // 使用 `false` 可以禁用代理功能,同时环境变量也会被忽略。
      // `auth`表示应使用HTTP Basic auth连接到代理,并且提供凭据。
      // 这将设置一个 `Proxy-Authorization` 请求头,它会覆盖 `headers` 中已存在的自定义 `Proxy-Authorization` 请求头。
      // 如果代理服务器使用 HTTPS,则必须设置 protocol 为`https`
      proxy: {
        protocol: 'https',
        host: '127.0.0.1',
        port: 9000,
        auth: {
          username: 'mikeymike',
          password: 'rapunz3l'
        }
      },
      // see https://axios-http.com/zh/docs/cancellation
      cancelToken: new CancelToken(function (cancel) {
      }),
      // `decompress` indicates whether or not the response body should be decompressed 
      // automatically. If set to `true` will also remove the 'content-encoding' header 
      // from the responses objects of all decompressed responses
      // - Node only (XHR cannot turn off decompression)
      decompress: true // 默认值
    }
    

    9.2 Axios get和post方法

    axios.get(url[, config])
    
    axios.get(url,{
       上面指定配置key:配置值,
       上面指定配置key:配置值
    })
    
    axios.post(url[, data[, config]])
    
    axios.post(url,{key:value},{
       上面指定配置key:配置值,
       上面指定配置key:配置值
    })
    

    9.3 Axios 拦截器

    定义 src/utils/request.js 提取拦截器和配置语法

    //  创建instance实例
    const instance = axios.create({
        baseURL:'http://localhost:8080/',
        timeout:10000
    })
    
    //  添加请求拦截
    instance.interceptors.request.use(
        // 请求前处理函数
        config=>{
            //处理指定的请求头
            
            return config
        },
        // 设置请求错误处理函数
        error=>{
        
            return Promise.reject(error)
        }
    )
    // 添加响应拦截器
    instance.interceptors.response.use(
        // 设置响应正确时的处理函数,2xx 范围内的状态码都会触发该函数
        response=>{
          
            return response
        },
        // 设置响应异常时的处理函数,超出 2xx 范围的状态码都会触发该函数
        error=>{
            return Promise.reject(error)
        }
    )
    // 默认导出
    export default instance
    

    十、跨域问题

    同源策略(Sameoriginpolicy)是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号

    解决跨域的两个方式,1 前端代理模式(高并发下效果不好,一般不用)2 后端跨域过滤器

    后端跨域过滤器:CrosFilter过滤器

    package com.pro.filter;
    
    import com.pro.common.Result;
    import com.pro.util.WebUtil;
    import jakarta.servlet.*;
    import jakarta.servlet.annotation.WebFilter;
    import jakarta.servlet.annotation.WebServlet;
    import jakarta.servlet.http.HttpServletRequest;
    import jakarta.servlet.http.HttpServletResponse;
    
    import java.io.IOException;
    
    @WebFilter("/*")
    public class CrosFilter implements Filter {
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            System.out.println(request.getMethod());
            HttpServletResponse response = (HttpServletResponse) servletResponse;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE, HEAD");
            response.setHeader("Access-Control-Max-Age", "3600");
            response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With");
            // 如果是跨域预检请求,则直接在此响应200业务码
            if(request.getMethod().equalsIgnoreCase("OPTIONS")){
                WebUtil.writeJson(response, Result.ok(null));
            }else{
                // 非预检请求,放行即可
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }
    

    未来使用框架,用一个 @CrossOrigin 就可以解决跨域问题了

    十一、Pinia

    Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。由 Vue 核心团队维护,对 Vue 2 和 Vue 3 都可用

    11.1 基本用法

    先安装

    npm install pinia
    

    定义 pinia store 对象 src/store/store.js [推荐这么命名不是强制]

    import {defineStore } from 'pinia'
    
    //定义数据并且对外暴露
    // store就是定义共享状态的包装对象
    // 内部包含四个属性: id 唯一标识 state 完整类型推理,推荐使用箭头函数 存放的数据 getters 类似属性计算,存储放对数据
    // 操作的方法  actions 存储数据的复杂业务逻辑方法
    // 理解: store类似Java中的实体类, id就是类名, state 就是装数据值的属性  getters就是get方法,actions就是对数据操作的其他方法
    export const definedPerson = defineStore(
        {
            id: 'personPinia', //必须唯一
            state:()=>{ // state中用于定义数据
                return {
                    username:'张三',
                    age:0,
                    hobbies:['唱歌','跳舞']
                }
            },
            getters:{// 用于定义一些通过数据计算而得到结果的一些方法 一般在此处不做对数据的修改操作
                     // getters中的方法可以当做属性值方式使用
                getHobbiesCount(){
                    return this.hobbies.length
                },
                getAge(){
                    return this.age
                }
            },
            actions:{ // 用于定义一些对数据修改的方法
                doubleAge(){
                    this.age=this.age*2
                }
            }
        }
    )
    

    main.js 配置 pinia 组件到vue中

    let app =createApp(App)
    app.use(router)
    // app中使用pinia功能
    app.use(pinia) 
    app.mount('#app')
    

    pinia 使用:

    <script setup type="module">
        import { ref} from 'vue';
        import { definedPerson} from '../store/store';
        // 读取存储的数据
        let person= definedPerson()
       
    script>
    
    <template>
        <div>
            <h1>operate视图,用户操作Pinia中的数据h1>
            请输入姓名:<input type="text" v-model="person.username"> <br>
            请输入年龄:<input type="text" v-model="person.age"> <br>
            请增加爱好:
            <input type="checkbox" value="吃饭"  v-model="person.hobbies"> 吃饭
            <input type="checkbox" value="睡觉"  v-model="person.hobbies"> 睡觉
            <input type="checkbox" value="打豆豆"  v-model="person.hobbies"> 打豆豆 <br>
            
            
            <button @click="person.doubleAge()">年龄加倍button> <br>
            
            <button @click="person.$reset()">恢复默认值button> <br>
            
            <button @click="person.$patch({username:'奥特曼',age:100,hobbies:['晒太阳','打怪兽']})">变身奥特曼button> <br>
    		显示pinia中的person数据:{{person}}
        div>
    template>
    <style scoped>
    style>
    

    11.2 Pinia其他细节

    1. 状态监听及初始状态

    State (状态) 在大多数情况下,state 都是你的 store 的核心。人们通常会先定义能代表他们 APP 的 state。在 Pinia 中,state 被定义为一个返回初始状态的函数。

        // 读取存储的数据
        let person= definedPerson()
        // 监听状态
        person.$subscribe((mutation,state)=>{
            console.log('---subscribe---')
            /* 
            mutation.storeId
                person.$id一样
            mutation.payload
                传递给 cartStore.$patch() 的补丁对象。
            state 数据状态,其实是一个代理
            */
            console.log(mutation)
            console.log(mutation.type)
            console.log(mutation.payload)
            console.log(mutation.storeId)
            console.log(person.$id)
            // 数据 其实是一个代理对象
            console.log(state)
        })
    
    1. Getter 完全等同于 store 的 state 的计算属性。可以通过 defineStore() 中的 getters 属性来定义它们。推荐使用箭头函数,并且它将接收 state 作为第一个参数
    export const useStore = defineStore('main', {
      state: () => ({
        count: 0,
      }),
      getters: {
        doubleCount: (state) => state.count * 2,
      },
    })
    
    1. Action 相当于组件中的 method。它们可以通过 defineStore() 中的 actions 属性来定义,并且它们也是定义业务逻辑的完美选择。类似 getter,action 也可通过 this 访问整个 store 实例,并支持完整的类型标注(以及自动补全)。不同的是,action 可以是异步的,你可以在它们里面 await 调用任何 API,以及其他 action
    export const useCounterStore = defineStore('main', {
      state: () => ({
        count: 0,
      }),
      actions: {
        increment() {
          this.count++
        },
        randomizeCounter() {
          this.count = Math.round(100 * Math.random())
        },
      },
    })
    

    十二、Element Plus

    Element Plus 是一套基于 Vue 3 的开源 UI 组件库,是由饿了么前端团队开发的升级版本 Element UI。Element Plus 提供了丰富的 UI 组件、易于使用的 API 接口和灵活的主题定制功能,可以帮助开发者快速构建高质量的 Web 应用程序。

    • Element Plus 可以在支持 ES2018 和 ResizeObserver 的浏览器上运行。 如果您确实需要支持旧版本的浏览器,请自行添加 Babel 和相应的 Polyfill

    • 官网https://element-plus.gitee.io/zh-CN/

    • 由于 Vue 3 不再支持 IE11,Element Plus 也不再支持 IE 浏览器。

    使用步骤:

    1. 安装:npm install element-plus
    2. 引入:main.js
    import { createApp } from 'vue'
    //导入element-plus相关内容
    import ElementPlus from 'element-plus'
    import 'element-plus/dist/index.css'
    
    import App from './App.vue'
    
    const app = createApp(App)
    
    app.use(ElementPlus)
    app.mount('#app')
    
    1. 复制官网组件代码直接使用即可

    https://element-plus.gitee.io/zh-CN/component/button.html

你可能感兴趣的:(#,02,Java,Web,前端)