Angular 保姆级别教程高阶应用 - RxJs

RxJS

13.1.1 什么是 RxJS ?

RxJS 是一个用于处理异步编程的 JavaScript 库,目标是使编写异步和基于回调的代码更容易。

13.1.2 为什么要学习 RxJS ?

就像 Angular 深度集成 TypeScript 一样,Angular 也深度集成了 RxJS。

服务、表单、事件、全局状态管理、异步请求 …

13.1.3 快速入门
  1. 可观察对象 ( Observable ) :类比 Promise 对象,内部可以用于执行异步代码,通过调用内部提供的方法将异步代码执行的结果传递到可观察对象外部。

  2. 观察者 ( Observer ):类比 then 方法中的回调函数,用于接收可观察对象中传递出来数据。

  3. 订阅 ( subscribe ):类比 then 方法,通过订阅将可观察对象和观察者连接起来,当可观察对象发出数据时,订阅者可以接收到数据。
    在这里插入图片描述

   import { Observable } from "rxjs"const observable = new Observable(function (observer) {setTimeout(function () {observer.next({name: "Tom"})}, 2000)})const observer = {next: function (value) {console.log(value)}}observable.subscribe(observer)
13.2 可观察对象
13.2.1 Observable
  1. 在 Observable 对象内部可以多次调用 next 方法向外发送数据。

    const observable = new Observable(function (observer) {let index = 0setInterval(function () {observer.next(index++)}, 1000)
    })const observer = {next: function (value) {console.log(value)}
    }observable.subscribe(observer)
    
  2. 当所有数据发送完成以后,可以调用 complete 方法终止数据发送。

    const observable = new Observable(function (observer) {let index = 0let timer = setInterval(function () {observer.next(index++)if (index === 3) {observer.complete()clearInterval(timer)}}, 1000)
    })const observer = {next: function (value) {console.log(value)},complete: function () {console.log("数据发送完成")}
    }observable.subscribe(observer)
    
  3. 当 Observable 内部逻辑发生错误时,可以调用 error 方法将失败信息发送给订阅者,Observable 终止。

    import { Observable } from "rxjs"const observable = new Observable(function (observer) {let index = 0let timer = setInterval(function () {observer.next(index++)if (index === 3) {observer.error("发生错误")clearInterval(timer)}}, 1000)
    })const observer = {next: function (value) {console.log(value)},error: function (error) {console.log(error)}
    }observable.subscribe(observer)
    
    1. 可观察对象是惰性的,只有被订阅后才会执行
    const observable = new Observable(function () {console.log("Hello RxJS")
    })
    // observable.subscribe()
    
  4. 可观察对象可以有 n 多订阅者,每次被订阅时都会得到执行
    在这里插入图片描述

    const observable = new Observable(function () {console.log("Hello RxJS")
    })observable.subscribe()
    observable.subscribe()
    observable.subscribe()
    observable.subscribe()
    observable.subscribe()
    
  5. 取消订阅

    import { interval } from "rxjs"const obs = interval(1000);
    const subscription = obs.subscribe(console.log);setTimeout(function () {subscription.unsubscribe()
    }, 2000)
    
    13.2.2 Subject
  6. 用于创建空的可观察对象,在订阅后不会立即执行,next 方法可以在可观察对象外部调用

    import { Subject } from "rxjs"const demoSubject = new Subject()demoSubject.subscribe({next: function (value) {console.log(value)}})
    demoSubject.subscribe({next: function (value) {console.log(value)}})setTimeout(function () {demoSubject.next("hahaha")
    }, 3000)
    
    13.2.3 BehaviorSubject

拥有 Subject 全部功能,但是在创建 Obervable 对象时可以传入默认值,观察者订阅后可以直接拿到默认值。

import { BehaviorSubject } from "rxjs"const demoBehavior = new BehaviorSubject("默认值")
demoBehavior.subscribe({next: function (value) {console.log(value)}})
demoBehavior.next("Hello")
13.2.3 ReplaySubject

功能类似 Subject,但有新订阅者时两者处理方式不同,Subject 不会广播历史结果,而 ReplaySubject 会广播所有历史结果。

import { ReplaySubject } from "rxjs"const rSubject = new ReplaySubject()rSubject.subscribe(value => {console.log(value)
})rSubject.next("Hello 1")
rSubject.next("Hello 2")setTimeout(function () {rSubject.subscribe({next: function (value) {console.log(value)}})
}, 3000)
13.3 辅助方法
13.3.1 range

range(start, length),调用方法后返回 observable 对象,被订阅后会发出指定范围的数值。
在这里插入图片描述

import { range } from "rxjs"range(0, 5).subscribe(n => console.log(n))// 0
// 1
// 2
// 3
// 4

方法内部并不是一次发出 length 个数值,而是发送了 length 次,每次发送一个数值,就是说内部调用了 length 次 next 方法。

13.3.2 of

将参数列表作为数据流返回。

在这里插入图片描述

of("a", "b", [], {}, true, 20).subscribe(v => console.log(v))
13.3.3 from

在这里插入图片描述

将 Array,Promise, Iterator 转换为 observable 对象。

from(["a", "b", "c"]).subscribe(v => console.log(v))
// a
// b
// c
import { from } from "rxjs"function p() {return new Promise(function (resolve) {resolve([100, 200])})
}from(p()).subscribe(v => console.log(v))
// [100, 200]
13.3.4 interval、timer

Interval:每隔一段时间发出一个数值,数值递增
在这里插入图片描述

import { interval } from "rxjs"interval(1000).subscribe(n => console.log(n))

**timer **:间隔时间过去以后发出数值,行为终止,或间隔时间发出数值后,继续按第二个参数的时间间隔继续发出值
在这里插入图片描述

import { timer } from "rxjs"timer(2000).subscribe(n => console.log(n))
timer(0, 1000).subscribe(n => console.log(n))
13.3.5 Concat

合并数据流,先让第一个数据流发出值,结束后再让第二个数据流发出值,进行整体合并。
在这里插入图片描述

import { concat, range } from "rxjs"concat(range(1, 5), range(6, 5)).subscribe(console.log)
13.3.7 combineLatest

将两个 Obserable 中最新发出的数据流进行组合成新的数据流,以数组的形式发出。和当前最新的进行组合。
在这里插入图片描述

import { combineLatest, timer } from "rxjs"const firstTimer = timer(0, 1000) // emit 0, 1, 2... after every second, starting from now
const secondTimer = timer(500, 1000) // emit 0, 1, 2... after every second, starting 0,5s from now
combineLatest(firstTimer, secondTimer).subscribe(console.log)// [0, 0] after 0.5s
// [1, 0] after 1s
// [1, 1] after 1.5s
// [2, 1] after 2s
13.3.8 zip

将多个 Observable 中的数据流进行组合。和将来最新的进行组合。

import { zip, of } from "rxjs"
import { map } from "rxjs/operators"let age = of(27, 25, 29)
let name = of("Foo", "Bar", "Beer")
let isDev = of(true, true, false)zip(name, age, isDev).pipe(map(([name, age, isDev]) => ({ name, age, isDev }))).subscribe(console.log)// { name: 'Foo', age: 27, isDev: true }
// { name: 'Bar', age: 25, isDev: true }
// { name: 'Beer', age: 29, isDev: false }
13.3.9 forkJoin

forkJoin 是 Rx 版本的 Promise.all(),即表示等到所有的 Observable 都完成后,才一次性返回值。
在这里插入图片描述

import axios from "axios"
import { forkJoin, from } from "rxjs"axios.interceptors.response.use(response => response.data)forkJoin({goods: from(axios.get("http://localhost:3005/goods")),category: from(axios.get("http://localhost:3005/category"))
}).subscribe(console.log)
13.3.10 throwError

返回可观察对象并向订阅者抛出错误。

在这里插入图片描述

import { throwError } from "rxjs"throwError("发生了未知错误").subscribe({ error: console.log })
13.3.11 retry

如果 Observable 对象抛出错误,则该辅助方法会重新订阅 Observable 以获取数据流,参数为重新订阅次数。

import { interval, of, throwError } from "rxjs"
import { mergeMap, retry } from "rxjs/operators"interval(1000).pipe(mergeMap(val => {if (val > 2) {return throwError("Error!")}return of(val)}),retry(2)).subscribe({next: console.log,error: console.log})
13.3.12 race

接收并同时执行多个可观察对象,只将最快发出的数据流传递给订阅者。

import { race, timer } from "rxjs"
import { mapTo } from "rxjs/operators"const obs1 = timer(1000).pipe(mapTo("fast one"))
const obs2 = timer(3000).pipe(mapTo("medium one"))
const obs3 = timer(5000).pipe(mapTo("slow one"))race(obs3, obs1, obs2).subscribe(console.log)
13.3.13 fromEvent

将事件转换为 Observable。

import { fromEvent } from "rxjs"const btn = document.getElementById("btn")
// 可以将 Observer 简写成一个函数,表示 next
fromEvent(btn, "click").subscribe(e => console.log(e))
13.4 操作符
  1. 数据流:从可观察对象内部输出的数据就是数据流,可观察对象内部可以向外部源源不断的输出数据。
  2. 操作符:用于操作数据流,可以对象数据流进行转换,过滤等等操作。
13.4.1 map、mapTo

**map:**对数据流进行转换,基于原有值进行转换。

在这里插入图片描述

import { interval } from "rxjs"
import { map } from "rxjs/operators"interval(1000).pipe(map(n => n * 2)).subscribe(n => console.log(n))

**mapTo:**对数据流进行转换,不关心原有值,可以直接传入要转换后的值。

在这里插入图片描述

import { interval } from "rxjs"
import { mapTo } from "rxjs/operators"interval(1000).pipe(mapTo({ msg: "接收到了数据流" })).subscribe(msg => console.log(msg))
13.4.2 filter

对数据流进行过滤。

import { range } from "rxjs"
import { filter } from "rxjs/operators"range(1, 10).pipe(filter(n => n % 2 === 0)).subscribe(even => console.log(even))
13.4.3 pluck

获取数据流对象中的属性值。
在这里插入图片描述

import { interval } from "rxjs"
import { pluck, mapTo } from "rxjs/operators"interval(1000).pipe(mapTo({ name: "张三", a: { b: "c" } }), pluck("a", "b")).subscribe(n => console.log(n))
13.4.4 first

获取数据流中的第一个值或者查找数据流中第一个符合条件的值,类似数组中的 find 方法。获取到值以后终止行为。

在这里插入图片描述

import { interval } from "rxjs"
import { first } from "rxjs/operators"interval(1000).pipe(first()).subscribe(n => console.log(n))interval(1000).pipe(first(n => n === 3)).subscribe(n => console.log(n))
13.4.5 startWith

创建一个新的 observable 对象并将参数值发送出去,然后再发送源 observable 对象发出的值。

在异步编程中提供默认值的时候非常有用。

在这里插入图片描述

import { interval } from "rxjs"
import { map, startWith } from "rxjs/operators"interval(1000).pipe(map(n => n + 100),startWith(505)).subscribe(n => console.log(n))
// 505
// 100
// 101
// 102
// ...
13.4.6 every

查看数据流中的每个值是否都符合条件,返回布尔值。类似数组中的 every 方法。
在这里插入图片描述

import { range } from "rxjs"
import { every, map } from "rxjs/operators"range(1, 9).pipe(map(n => n * 2),every(n => n % 2 === 0)).subscribe(b => console.log(b))
13.4.7 delay、delayWhen

**delay:**对上一环节的操作整体进行延迟,只执行一次。

import { from } from "rxjs"
import { delay, map, tap } from "rxjs/operators"from([1, 2, 3]).pipe(delay(1000),tap(n => console.log("已经延迟 1s", n)),map(n => n * 2),delay(1000),tap(() => console.log("又延迟了 1s"))).subscribe(console.log)// tap 操作符不会对数据流造成影响, 它被用来执行简单的副作用, 比如输出, 但是复杂的副作用不要在这执行, 比如 Ajax

**delayWhen:**对上一环节的操作进行延迟,上一环节发出多少数据流,传入的回调函数就会执行多次。

import { range, timer } from "rxjs"
import { delayWhen } from "rxjs/operators"range(1, 10).pipe(delayWhen(n => {console.log(n)return timer(n * 1000)})).subscribe(console.log)
13.4.8 take、takeWhile、takeUtil

take:获取数据流中的前几个
在这里插入图片描述

import { range } from "rxjs"
import { take } from "rxjs/operators"range(1, 10).pipe(take(5)).subscribe(console.log)

**takeWhile:**根据条件从数据源前面开始获取。

在这里插入图片描述

import { range } from "rxjs"
import { takeWhile } from "rxjs/operators"range(1, 10).pipe(takeWhile(n => n < 8)).subscribe(console.log)

**takeUntil:**接收可观察对象,当可观察对象发出值时,终止主数据源。
在这里插入图片描述

import { interval, timer } from "rxjs"
import { takeUntil } from "rxjs/operators"interval(100).pipe(takeUntil(timer(2000))).subscribe(console.log)
// 结果少两个数据流的原因:第一次和最后一次,都需要延迟 100 毫秒。
13.4.9 skip、skipWhile、skipUntil

**skip:**跳过前几个数据流。

在这里插入图片描述

import { range } from "rxjs"
import { skip } from "rxjs/operators"range(1, 10).pipe(skip(5)).subscribe(console.log)

**skipWhile:**根据条件进行数据流的跳过。

在这里插入图片描述

import { range } from "rxjs"
import { skipWhile } from "rxjs/operators"range(1, 10).pipe(skipWhile(n => n < 5)).subscribe(console.log)

**skipUntil:**跳过数据源中前多少时间发出的数据流,发送从这个时间以后数据源中发送的数据流。

import { timer, interval } from "rxjs"
import { skipUntil } from "rxjs/operators"interval(100).pipe(skipUntil(timer(2000))).subscribe(console.log)
13.4.10 last

获取数据流中的最后一个。

在这里插入图片描述

import { range } from "rxjs"
import { last } from "rxjs/operators"range(1, 10).pipe(last()).subscribe(console.log)

如果数据源不变成完成状态,则没有最后一个。

import { interval } from "rxjs"
import { last, take } from "rxjs/operators"interval(1000).pipe(take(5), last()).subscribe(console.log)
13.4.11 concatAll、concatMap

**concatAll:**有时 Observable 发出的又是一个 Obervable,concatAll 的作用就是将新的可观察对象和数据源进行合并。

Observable => [1, 2, 3]

Observable => [Observable, Observable]

在这里插入图片描述

import { fromEvent, interval } from "rxjs"
import { map, take, concatAll } from "rxjs/operators"fromEvent(document, "click").pipe(map(event => interval(1000).pipe(take(2))),concatAll()).subscribe(console.log)
import { map, concatAll } from "rxjs/operators"
import { of, interval } from "rxjs"interval(1000).pipe(map(val => of(val + 10)),concatAll()).subscribe(console.log)

**concatMap:**合并可观察对象并处理其发出的数据流。
在这里插入图片描述

13.4.13 reduce、scan

reduce: 类似 JavaScript 数组中的 reduce,对数数据进行累计操作。reduce 会等待数据源中的数据流发送完成后再执行,执行时 reduce 内部遍历每一个数据流进行累计操作,操作完成得到结果将结果作为数据流发出。

在这里插入图片描述

import { interval } from "rxjs"
import { take, reduce } from "rxjs/operators"interval(500).pipe(take(5),reduce((acc, value) => acc += value, 0)).subscribe(v => console.log())

scan:类似 reduce,进行累计操作,但执行时机不同,数据源每次发出数据流 scan 都会执行。reduce 是发送出最终计算的结果,而 scan 是发出每次计算的结果。

在这里插入图片描述

import { interval } from "rxjs"
import { take, scan } from "rxjs/operators"interval(500).pipe(take(5),scan((acc, value) => acc += value, 0)).subscribe(v => console.log())
13.4.14 mergeAll、mergeMap

**mergeAll:**交叉合并可观察对象。

在这里插入图片描述

import { fromEvent, interval } from "rxjs"
import { map, mergeAll } from "rxjs/operators"fromEvent(document, "click").pipe(map(() => interval(1000)),mergeAll()).subscribe(console.log)

mergeMap:交叉合并可观察对象以后对可观察对象发出的数据流进行转换。

import { of, interval } from "rxjs"
import { mergeMap, map } from "rxjs/operators"of("a", "b", "c").pipe(mergeMap(x => interval(1000).pipe(map(i => x + i)))).subscribe(x => console.log(x))
13.4.15 throttleTime

节流,可观察对象高频次向外部发出数据流,通过 throttleTime 限制在规定时间内每次只向订阅者传递一次数据流。
在这里插入图片描述

import { fromEvent } from "rxjs"
import { throttleTime } from "rxjs/operators"fromEvent(document, "click").pipe(throttleTime(2000)).subscribe(x => console.log(x))
13.4.16 debounceTime

防抖,触发高频事件,只响应最后一次。

在这里插入图片描述

import { fromEvent } from "rxjs"
import { debounceTime } from "rxjs/operators"fromEvent(document, "click").pipe(debounceTime(1000)).subscribe(x => console.log(x))
13.4.17 distinctUntilChanged

检测数据源当前发出的数据流是否和上次发出的相同,如相同,跳过,不相同,发出。

import { of } from "rxjs"
import { distinctUntilChanged } from "rxjs/operators"of(1, 1, 2, 2, 2, 1, 1, 2, 3, 3, 4).pipe(distinctUntilChanged()).subscribe(x => console.log(x)) // 1, 2, 1, 2, 3, 4
13.4.18 groupBy

对数据流进行分组。

import { of } from "rxjs"
import { mergeMap, groupBy, toArray } from "rxjs/operators"of({ name: "Sue", age: 25 },{ name: "Joe", age: 30 },{ name: "Frank", age: 25 },{ name: "Sarah", age: 35 }
).pipe(groupBy(person => person.age),mergeMap(group => group.pipe(toArray()))).subscribe(console.log)// [{name: "Sue", age: 25}, { name: "Frank", age: 25 }]
// [{ name: "Joe", age: 30 }]
// [{ name: "Sarah", age: 35 }]
13.4.19 withLatestFrom

主数据源发出的数据流总是和支数据源中的最新数据流进行结合,返回数组。

在这里插入图片描述

import { fromEvent, interval } from "rxjs"
import { withLatestFrom } from "rxjs/operators"const clicks = fromEvent(document, "click")
const timer = interval(1000)
clicks.pipe(withLatestFrom(timer)).subscribe(console.log)
13.4.20 switchMap

切换可观察对象。

import { fromEvent, interval } from "rxjs"
import { switchMap } from "rxjs/operators"fromEvent(document, "click").pipe(switchMap(ev => interval(1000))).subscribe(x => console.log(x))
13.5 练习
13.5.1 元素拖拽
<style>#box {width: 200px;height: 200px;background: skyblue;position: absolute;left: 0;top: 0;}
</style>
<div id="box"></div>
// 原生 JavaScript
box.onmousedown = function (event) {let distanceX = event.clientX - event.target.offsetLeftlet distanceY = event.clientY - event.target.offsetTopdocument.onmousemove = function (event) {let positionX = event.clientX - distanceXlet positionY = event.clientY - distanceYbox.style.left = positionX + "px"box.style.top = positionY + "px"}box.onmouseup = function () {document.onmousemove = null}
}
// RxJS
import { fromEvent } from "rxjs"
import { map, switchMap, takeUntil } from "rxjs/operators"const box = document.getElementById("box")fromEvent(box, "mousedown").pipe(map(event => ({distanceX: event.clientX - event.target.offsetLeft,distanceY: event.clientY - event.target.offsetTop})),switchMap(({ distanceX, distanceY }) =>fromEvent(document, "mousemove").pipe(map(event => ({positionX: event.clientX - distanceX,positionY: event.clientY - distanceY})),takeUntil(fromEvent(document, "mouseup"))))).subscribe(({ positionX, positionY }) => {box.style.left = positionX + "px"box.style.top = positionY + "px"})
13.5.2 搜索
<input id="search" type="text" placeholder="请输入搜索内容..." />
import { fromEvent, from, throwError } from "rxjs"
import { debounceTime, distinctUntilChanged, map, switchMap, catchError } from "rxjs/operators"
import axios from "axios"const search = document.getElementById("search")fromEvent(search, "keyup").pipe(debounceTime(700),map(event => event.target.value),distinctUntilChanged(),switchMap(keyword =>from(axios.get(`https://j1sonplaceholder.typicode.com/posts?q=${keyword}`)).pipe(map(response => response.data),catchError(error => throwError(`发生了错误: ${error.message}`))))).subscribe({next: value => {console.log(value)},error: error => {console.log(error)}})
13.5.3 串联请求

先获取token,再根据token获取用户信息

<button id="btn">获取用户信息</button>
import axios from "axios"
import { from, fromEvent } from "rxjs"
import { pluck, concatMap } from "rxjs/operators"const button = document.getElementById("btn")fromEvent(button, "click").pipe(concatMap(event =>from(axios.get("http://localhost:3005/token")).pipe(pluck("data", "token"))),concatMap(token =>from(axios.get("http://localhost:3005/userInfo")).pipe(pluck("data")))).subscribe(console.log)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/456352.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经典功率谱估计的原理及MATLAB仿真(自相关函数BT法、周期图法、bartlett法、welch法)

经典功率谱估计的原理及MATLAB仿真&#xff08;自相关函数BT法、周期图法、bartlett法、welch法&#xff09; 文章目录 前言一、BT法二、周期图法三、Bartlett法四、welch法五、MATLAB仿真六、MATLAB详细代码总结 前言 经典功率谱估计方法包括BT法&#xff08;对自相关函数求傅…

基于Java的就业信息管理系统源码带本地搭建教程

技术框架&#xff1a;jQuery MySQL5.7 mybatis shiro Layui HTML CSs JS 运行环境&#xff1a;jdk8 IntelliJ IDEA maven3 宝塔面板 实现了就业信息管理、就业统计、用户管理等功能。有普通用户和管理员两种角色。

开源限流组件分析(三):golang-time/rate

文章目录 本系列前言提供获取令牌的API数据结构基础方法tokensFromDurationdurationFromTokensadvance 获取令牌方法reverseN其他系列API 令人费解的CancelAt是bug吗 取消后无法唤醒其他请求 本系列 开源限流组件分析&#xff08;一&#xff09;&#xff1a;juju/ratelimit开源…

智能AI监测系统燃气安全改造方案的背景及应用价值

随着燃气行业的迅速发展和城市化进程的加快&#xff0c;燃气安全管理成为企业运营和城市管理中不可忽视的关键领域。燃气泄漏、管道破损等事故的发生不仅会造成严重的经济损失&#xff0c;还威胁到人民生命财产安全。传统的安全管理方法往往依赖人工巡检和手动监测&#xff0c;…

如何写一个视频编码器演示篇

先前写过《视频编码原理简介》&#xff0c;有朋友问光代码和文字不太真切&#xff0c;能否补充几张图片&#xff0c;今天我们演示一下&#xff1a; 这是第一帧画面&#xff1a;P1&#xff08;我们的参考帧&#xff09; 这是第二帧画面&#xff1a;P2&#xff08;需要编码的帧&…

C2W4.LAB.Word_Embedding.Part2

理论课&#xff1a;C2W4.Word Embeddings with Neural Networks 文章目录 Training the CBOW modelForward propagationInitialization of the weights and biasesTraining exampleValues of the hidden layerValues of the output layerCross-entropy loss BackpropagationGr…

大家都在用的HR招聘管理工具:国内Top5排名

招聘管理工具是专为HR及招聘团队设计的数字化助手&#xff0c;旨在简化招聘流程&#xff0c;提高效率。众所周知&#xff0c;招聘管理工具通常集成简历收集、筛选、面试安排、候选人跟踪等功能于一体&#xff0c;让招聘过程更加流畅。使用招聘管理工具&#xff0c;不仅能节省时…

高边坡稳定安全监测预警系统解决方案

一、项目背景 高边坡的滑坡和崩塌是一种常见的自然地质灾害&#xff0c;一但发生而没有提前预告将给人民的生命财产和社会危害产生严重影响。对高边坡可能产生的灾害提前预警、必将有利于决策者采取应对措施、减少和降低灾害造成的损失。现有的高边坡监测技术有人工巡查和利用测…

100个候选人,没一个能讲明白什么是自动化框架?

什么是自动化测试框架 01 什么是框架 框架是整个或部分系统的可重用设计&#xff0c;表现为一组抽象构件及构件实例间交互的方法。它规定了应用的体系结构&#xff0c;阐明了整个设计、协作构件之间的依赖关系、责任分配和控制流程&#xff0c;表现为一组抽象类以及其实例之间…

格姗知识圈博客网站开源了!

格姗知识圈博客 一个基于 Spring Boot、Spring Security、Vue3、Element Plus 的前后端分离的博客网站&#xff01;本项目基本上是小格子一个人开发&#xff0c;由于工作和个人能力原因&#xff0c;部分技术都是边学习边开发&#xff0c;特别是前端&#xff08;工作中是后端开…

MySQL~表的操作(创建表,查看表,修改表,删除表)

1.创建表 1.1.创建表 首先要选择需要操作的数据库&#xff0c;USE 数据库名&#xff0c;后续可以根据实际情况操作时添加。 USE fruitsales;建表语法&#xff1a; create table 表名( 字段名1 数据类型, 字段名2 数据类型, ); 实例&#xff1a;创建fruit_bak1表。 create t…

[linux]软件安装

安装方式 二进制发布包安装: 软件已经针对具体平台编译打包发布&#xff0c;只要解压修改配置即可 rpm安装: 软件已经按照redhat的包管理规范进行打包, 使用rpm命令进行安装&#xff0c;不能自行解决库依赖问题 yum安装: 一种在线软件安装方式, 本质上还是rpm安装, 自动下载…

【vim】手动安装 Leader-F

LeaderF 是一个功能强大的 Vim 插件&#xff0c;主要用于快速导航和搜索。它可以帮助用户在 Vim 中高效地查找文件、缓冲区、标签、函数等各种元素&#xff0c;极大地提高了编辑效率。 LeaderF 的安装如果按照仓库中的教程来的话可以很方便的实现安装&#xff0c;这里介绍一下…

【记录】VSCode|自用设置项

文章目录 1 基础配置1.1 自动保存1.2 编辑区自动换行1.3 选项卡换行1.4 空格代替制表符1.5 开启滚轮缩放 2 进阶设置2.1 选项卡不自我覆盖2.2 选项卡限制宽度2.3 选项卡组限制高度2.4 字体设置2.5 字体加粗2.6 侧边栏2.7 沉浸式代码模式 Zen Mode2.8 设置 Zen 模式的选项卡组 3…

家用wifi的ip地址固定吗?换wifi就是换ip地址吗

在探讨家用WiFi的IP地址是否固定&#xff0c;以及换WiFi是否就意味着换IP地址这两个问题时&#xff0c;我们首先需要明确几个关键概念&#xff1a;IP地址、家用WiFi网络、以及它们之间的相互作用。 一、家用WiFi的IP地址固定性 家用WiFi环境中的IP地址通常涉及两类&#xff1a…

文档透明加密系统怎么用?五款透明加密软件汇总!2024热门推荐,实测分享!

数据泄露事件频发&#xff0c;让无数企业谈之色变。 想要自动对存储在计算机上的文档进行加密吗&#xff1f; 怎么在不影响日常工作的前提&#xff0c;确保文档在存储和传输过程中的安全&#xff1f; 透明加密系统来助力&#xff01; 本文&#xff0c;将详细介绍文档透明加密…

解决vue使用pdfdist-mergeofd插件时报错polyfills

pdfdist-mergeofd 该插件主要是为了解决pdf-js和ofd-js共同使用时产生的依赖冲突问题&#xff0c;具体可看这位博主的文章同时使用ofdjs和pdfjs遇到的问题&#xff0c;和解决方法——懒加载 首先看下报错信息 ERROR in ./node_modules/.pnpm/pdfdist-mergeofd2.2.228_webpa…

人工智能算法之双倍体遗传算法(DGA)

人工智能算法之双倍体遗传算法&#xff08;DGA&#xff09; 双倍体遗传算法是一种改进的遗传算法&#xff0c;借鉴了生物中双倍体&#xff08;每个体细胞中具有两套染色体&#xff09;的遗传机制。传统遗传算法中的个体通常是单倍体&#xff08;单套基因&#xff09;&#xff0…

使用 v-html 指令渲染的标签, 标签内绑定的 click 事件不生效

背景 在项目开发中&#xff0c;实现用户友好的输入交互是提升用户体验的关键之一。例如&#xff0c;在客服对话框中&#xff0c;其中有包含多个快捷选项用于快速问答&#xff0c;每个快捷选项都是一个可点击的按钮&#xff0c;并需要绑定点击事件来执行相应操作。然而&#xf…

数据类型【MySQL】

文章目录 建立表查看表删除表数据类型floatcharvarcharchar&&varchar 时间日期类型enum和setenum和set查找 建立表 mysql> create table if not exists user1(-> id int ,-> name varchar (20) comment 用户名 ,-> password char (32) comment 用户名的…