3_JavaScript
一. 介绍
- JavaScript语言诞生主要是完成页面的数据验证, 因此它运行在客户端, 需要运行浏览器来解析执行JavaScript代码
- JS是弱类型, Java是强类型
- 特点
- 交互性(它可以做的就是信息的动态交互)
- 安全性(不允许直接访问本地硬盘)
- 跨平台性(只要是解释JS的浏览器都可以执行, 与平台无关)
二. JavaScript与HTML代码结合的方式
2.1 第一种方式
- 只需在head标签中, 或者在body标签中, 使用script标签来书写JavaScript代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//alert是JavaScript语言提供的一个警告框函数
//它可以接收任何类型的参数, 这个参数就是警告框的提示信息
alert("hello JavaScript!")
</script>
</head>
<body>
</body>
</html>
2.2 第二种方式
- 使用script标签引入单独的JavaScript代码文件
//1.js
alert("hello javascript")
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--现在需要使用script引入外部的js文件来执行
src属性专门用来引入js文件路径(相对路径和绝对路径都可以)
script标签可以用来定义js代码, 也可以用来引入js文件
但是, 上面两种引入js外部文件的方式二选一使用即可, 不可同时使用
-->
<script type="text/javascript" src="1.js"></script>
<script type="text/javascript">
alert("abc")
</script>
</head>
<body>
</body>
</html>
三. 变量
- 什么是变量?
- 变量是可以存放某些值的内存的命名
- js的变量类型
- 数值类型 number
- 字符串类型 string
- 对象类型 object
- 布尔类型 boolean
- 函数类型 function
- js里特殊的值:
- undefined 未定义,所有js变量未赋予初始值时, 都是undefined
- null 空值
- NAN 全称是 Not A Number 非数字,非数值
- js中定义变量格式
- var 变量名;
- var 变量名 = 值;
<script type="text/javascript">
var i;
//alert(i);//undefined
i = 12;
//typeof()是js语言提供的一个函数
//它可以取变量的数据类型并返回
alert(i);
alert(typeof i)
i = "abc";
alert(typeof i)
var a = 12;
var b = "abc";
alert(a*b);//NaN 非数字,非数值
</script>
四. 运算
4.1 关系(比较)运算
- 等于: == 等于是简单的做字面值的比较
- 全等于: === 除了字面值的比较之外, 还会比较两个变量的数据类型
<script type="text/javascript">
var a = "12";
var b = 12;
alert(a == b);//true
alert(a === b);//false
</script>
4.2 逻辑运算
- 与运算: &&
- 或运算: ||
- 取反运算: !
- 在js语言中, 所有的变量, 都可以作为一个boolean类型的变量去使用
- 0, null, undefined, ""(空串) 都认为是false
- && 与运算 有两种情况
- 当表达式全为真的时候, 返回最后一个表达式的值
- 当表达式中, 有一个为假的时候, 返回第一个为假的表达式的值
- || 或运算 也有两种情况
- 当表达式全为假的时候, 返回最后一个表达式的值
- 当表达式中, 有一个为真的时候, 返回第一个为真的表达式的值
- 与运算和或运算 有短路
- 短路就是当这个表达式有结果了以后, 后面的表达式不再执行
<script type="text/javascript">
var a = "abc";
var b = true;
var c = false;
var d = null;
// && 与运算 有两种情况
//
// 1. 当表达式全为真的时候, 返回最后一个表达式的值
// 2. 当表达式中, 有一个为假的时候, 返回第一个为假的表达式的值
alert(a && b);//true
alert(b && a);//abc
alert(a && c);//false
alert(a && c);//false
alert(a && d && c)//null
// || 或运算 也有两种情况
//
// 1. 当表达式全为假的时候, 返回最后一个表达式的值
// 2. 当表达式中, 有一个为真的时候, 返回第一个为真的表达式的值
alert(c || d);//null
alert(a || c);//abc
</script>
五. 数组[重点]
5.1 数组定义方式
- js中数组的定义:
- 格式
- var 数组名 = []; //空数组
- var 数组名 = [1,'abc',true]; //定义数组同时赋值元素
- 格式
<script type="text/javascript">
var arr = [];//定义一个空数组
//alert(arr.length);//0
arr[0] = 12;
//alert(arr[0]);
alert(arr.length)//1
//js语言中的数组, 只要我们通过数组下标赋值,那么最大的下标值就会自动给数组进行扩容
arr[2] = 'abc';
alert(arr[1]);//undefined
alert(arr.length);//3
//数组的遍历
for (var i = 0; i < arr.length; i++){
alert(arr[i]);
}
</script>
六. 函数[重点]
6.1 函数的两种定义方式
6.1.1 第一种: 使用function关键字来定义函数
- function 函数名(形参列表){
函数体
}
在js语言中, 如何定义带有返回值的函数?
只需在函数体内直接使用return语句返回值即可
<script type="text/javascript">
//定义一个无参函数
function f() {
alert("无参函数f()被调用了")
}
//函数被调用才会执行
//f();
//定义一个有参函数
function f1(a,b) {
alert("有参函数f1()被调用了 a=>" + a + ",b=>" + b);
}
//f1(3,"abc")
//定义带有返回值的函数
function f2(num1,num2) {
return num1 + num2;
}
alert(f2(100,50));
</script>
6.1.2 第二种 var 函数名 = function(形参列表){函数体}
<script type="text/javascript">
var f = function () {
alert("无参函数");
}
f();
var f2 = function (a,b) {
alert("有参函数a=" + a + ",b=" + b);
}
f2(1,"aaa");
var f3 = function (num1,num2) {
return num1 + num2;
}
alert(f3(1,5));
</script>
- 注: 在Java中允许重载, 但js中函数的重载会覆盖掉上一次的定义
<script type="text/javascript">
function f() {
alert("无参函数")
}
function f(a,b) {
alert("有参函数")
}
f();//有参函数
</script>
6.2 函数的arguments隐形参数(只在function函数内)
- 就是在function函数中不需要定义, 但却可以直接用来获取所有参数的变量, 我们管它叫隐形参数
- js中的隐形参数类似于Java中的可变长参数
- public void fun(Object... args);
- 可变长参数其实是一个数组
<title>隐形参数</title>
<script type="text/javascript">
function f() {
// alert(arguments[0]);
// alert(arguments[1]);
// alert(arguments[2]);
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i]);
}
alert("无参函数")
}
//f(1,"aaa",true);
//计算所有参数的和并返回
function sum() {
var sum = 0;
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == "number"){
sum = sum + arguments[i];
}
}
return sum;
}
alert(sum(1,2,3,4,"aaa",5));
</script>
七. js中的自定义对象[扩展内容]
7.1 Object形式的自定义对象
- 对象的定义:
- var 变量名 = new Object(); //对象实例(空对象)
- 变量名.属性名 = 值; //定义一个属性
- 变量名.函数名 = function(){} //定义一个函数
- 对象的访问:
- 变量名.属性/函数名();
<script type="text/javascript">
// 对象的定义:
// var 变量名 = new Object(); //对象实例(空对象)
//
// 变量名.属性名 = 值; //定义一个属性
//
// 变量名.函数名 = function(){} //定义一个函数
var obj = new Object();
obj.name = "张三";
obj.age = 18;
obj.fun = function () {
alert("姓名: " + this.name + ", 年龄: " + this.age);
}
// 对象的访问:
//
// 变量名.属性/函数名();
alert(obj.name);
alert(obj.age);
obj.fun();
</script>
7.2 {} 花括号形式的自定义对象
- 对象的定义:
var 变量名 = { //空对象
属性名: 值, //定义一个属性
属性名: 值, //定义一个属性
函数名: function(){} //定义一个函数
};
- 对象的访问:
变量名.属性/函数名();
<script type="text/javascript">
var obj = {
name: "张三",
age: 18,
fun: function () {
alert("姓名: " + this.name + ", 年龄: " + this.age);
}
};
alert(obj.name);
alert(obj.age);
obj.fun();
</script>
八. js中的事件
- 什么是事件?
- 事件是电脑输入设备与页面进行交互的响应. 我们称之为事件
- 常用的事件:
- onload 加载完成事件
- 页面加载完成后, 常用于做页面js代码初始化操作
- onclick 单击事件
- 常用于按钮的点击响应操作
- onblur 失去焦点事件
- 常用于输入框失去焦点后验证其输入内容是否合法
- onchange 内容发生改变事件
- 常用于下拉列表和输入框内容发生改变后操作
- onsubmit 表单提交事件
- 常用于表单提交前, 验证所有表单项是否合法
- onload 加载完成事件
- 事件的注册又分为静态注册和动态注册两种:
- 什么是事件的注册(绑定)? 其实就是告诉浏览器, 当事件响应后要执行哪些操作代码, 叫事件注册或绑定
- 静态注册事件: 通过html标签的事件属性直接赋予事件响应后的代码
- 动态注册事件: 是指先通过js代码得到标签的dom对象, 然后再通过dom对象.事件名 = function(){} 这种形式赋予事件响应后的代码,动态注册基本步骤
- 获取标签对象
- 标签对象.事件名 = function(){}
8.1 onload事件
<script type="text/javascript">
function onloadFun() {
alert("静态注册onload事件,所有代码");
}
//onload事件动态注册, 是固定写法
window.onload = function () {
alert("动态注册的onload事件");
}
</script>
<!--静态注册onload事件
onload事件是浏览器解析完页面之后就会自动触发的事件
<body onload="onloadFun()">
-->
8.2 onclick事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//静态注册的onclick事件
function onclickFun() {
alert("静态注册的onclick事件");
}
//动态注册onclick事件
window.onclick = function () {
//1. 获取标签对象
//document 是js语言提供的一个对象(文档)
//getElementById 通过html中标签的id属性获取标签对象
var btnObj = document.getElementById("btn2");
//2. 通过标签对象.事件名 = function(){}
btnObj.onclick = function () {
alert("动态注册的onclick事件");
}
}
</script>
</head>
<body>
<!--静态注册onclick事件-->
<button onclick="onclickFun()">按钮1</button>
<button id="btn2">按钮2</button>
</body>
</html>
8.3 onblur事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//onblur的静态注册事件
function onblurFun() {
//console是控制台对象, 是由js语言提供, 专门用来向浏览器的控制器打印输出, 用于测试使用
//log是打印的方法
console.log('onblur的静态注册事件');
}
//onblur的动态注册事件
window.onblur = function () {
var pwdObj = document.getElementById("pwd");
pwdObj.onblur = function () {
console.log("onblur的动态注册事件");
}
}
</script>
</head>
<body>
<p>用户名: <input type="text" onblur="onblurFun()"></p>
<p>密码: <input type="text" id="pwd"></p>
</body>
</html>
8.4 onchange事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
function onchangeFun() {
alert("英雄已选择完毕");
}
window.onchange = function () {
var selObj = document.getElementById("sel");
selObj.onchange = function () {
alert("铭文已选择完毕")
}
}
</script>
</head>
<body>
<p>请选择你的出场英雄: </p>
<select onchange="onchangeFun()">
<option>孙斌</option>
<option>廉颇</option>
<option>诸葛亮</option>
<option>李白</option>
<option>马可波罗</option>
</select>
<p>请选择你的铭文: </p>
<select id="sel">
<option>通用</option>
<option>坦克</option>
<option>法穿</option>
<option>百穿</option>
<option>攻速</option>
</select>
</body>
</html>
8.5 onsubmit事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//onsubmit静态注册
function onsubmitFun() {
alert("onsubmit静态注册---发现不合法");
return false;
}
//onsubmit动态注册
window.onsubmit = function () {
var formObj = document.getElementById("form");
formObj.onsubmit = function () {
alert("onsubmit动态注册---发现不合法");
return false;
}
}
</script>
</head>
<body>
<!--return false 可以阻止表单提交-->
<form action="http://localhost:8080" method="get" onsubmit="return onsubmitFun()">
<input type="submit" value="静态注册">
</form>
<form action="http://localhost:8080" id="form">
<input type="submit" value="动态注册">
</form>
</body>
</html>
九. DOM模型
- DOM全称是Document Object Model 文档对象模型
- 其实就是把文档中的标签, 属性, 文本, 转换成对象来管理, 我们主要学习它们是如何转换的
9.1 Document对象[重点]
- Document对象的理解
- 第一点: Document它管理了所有的HTML文档的内容
- 第二点: Document它是一种树结构的文档. 有层级关系
- 第三点: 它让我们把所有的标签都对象化
- 第四点: 我们可以通过document访问所有的标签对象
9.2 Document对象中的方法介绍[重点]
- document.getElementById(elementId)
- 通过标签的id属性查找标签的dom对象, elementId是标签的id属性值
- document.getElementByName(elementName)
- 通过标签的name属性查找标签的dom对象, elementId是标签的name属性值
- document.getElementByTagName(tagName)
- 通过标签名查找标签的dom对象, tagName是标签名
- document.createElement(tagName)
- 通过给定的标签名, 创建一个标签对象, tagName是要创建的标签名
9.2.1 getElementById
- 根据元素标签id属性得到某元素标签
- 示例: 校验输入的用户名是否合法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
function onclickFun() {
var username = document.getElementById("username");
var usernameText = username.value;
var reg = /^\w{5,12}$/;
if (reg.test(usernameText)){
alert("用户名合法");
}else {
alert("用户名不合法");
}
}
</script>
</head>
<body>
<!--要求: 当用户点击了校验按钮时, 要获取输入框中的内容并验证其是否合法
验证的规则是: 必须由数字字母下划线组成, 并且长度时5到12位
-->
<p>用户名: <input type="text" id="username"></p>
<button onclick="onclickFun()">校验</button>
</body>
</html>
9.2.2 正则表达式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>正则</title>
<script type="text/javascript">
//var pattern = new RegExp("e");//表示字符串中, 是否包含字母e
//var pattern = /e/; //也是正则表达式对象,和上面表达的意思一样,只是写法不同
//var pattern = /[abc]/; //表示字符串中,是否包含字母a或b或c
//var pattern = /[a-z]/; //表示字符串中,是否包含小写字母
//var pattern = /[A-Z]/; //表示字符串中,是否包含大写字母
//var pattern = /[0-9]/; //表示字符串中,是否包含数字
//var pattern = /\w/; //表示字符串中,是否包含字母,数字,下划线
//var pattern = /a+/; //表示字符串中,是否包含至少一个a
//var pattern = /a*/; //表示字符串中,是否包含0个或多个a
//var pattern = /a?/; //表示字符串中,是否包含0个或1个a
//var pattern = /a{3}/; //表示字符串中,是否包含连续3个a
//var pattern = /a{3,5}/; //表示字符串中,是否包含至少3个至多5个连续的a
//var pattern = /a{3,}/; //表示字符串中,是否包含至少3个连续的a
//var pattern = /a$/; //表示字符串中,是否以a结尾
//var pattern = /^a/; //表示字符串中,是否以a开头
//var pattern = /^a{3,5}$/; //表示字符串中,从头到尾都必须完全匹配至少3个至多5个连续的a
var pattern = /^\w{5,12}$/; //表示字符串中,从头到尾都必须完全匹配5至12位数的字母数字下划线组合
alert(pattern);
var str = "aaa1231231231";
alert(pattern.test(str));
</script>
</head>
<body>
</body>
</html>
9.2.3 两种常见的校验提示
- innerHTML 表示起始标签和结束标签中的内容
- 第一种: 文字提示, innerHTML 后写上想要显示的文字
- usernameSpanObj.innerHTML = "用户名合法";
- 第二种: 图片提示,, innerHTML 后写上要显示的图片位置
- usernameSpanObj.innerHTML = "";
- 第一种: 文字提示, innerHTML 后写上想要显示的文字
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
function onclickFun() {
var username = document.getElementById("username");
var usernameText = username.value;
var reg = /^\w{5,12}$/;
var usernameSpanObj = document.getElementById("usernameSpan");
//innerHTML 表示起始标签和结束标签中的内容
//innerHTML 这个属性可读,可写
//usernameSpanObj.innerHTML = "可以自定义内容";
if (reg.test(usernameText)){
usernameSpanObj.innerHTML = "用户名合法";
//usernameSpanObj.innerHTML = "<img src=\"right.png\" width=\"18\" height=\"18\">";
}else {
usernameSpanObj.innerHTML = "用户名不合法";
//usernameSpanObj.innerHTML = "<img src=\"wrong.png\" width=\"18\" height=\"18\">";
}
}
</script>
</head>
<body>
<!--要求: 当用户点击了校验按钮时, 要获取输入框中的内容并验证其是否合法
验证的规则是: 必须由数字字母下划线组成, 并且长度时5到12位
-->
<p>用户名: <input type="text" id="username">
<span id="usernameSpan" style="color: red"></span>
</p>
<button onclick="onclickFun()">校验</button>
</body>
</html>
<!--<img src="right.png" width="18" height="18">-->
9.2.4 getElementsByName
- 根据元素标签name属性得到元素标签集合
- 示例: 选择框全选,全不选, 反选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//全选
function checkAll() {
//document.getElementsByName();是根据指定的name属性查询返回多个标签对象集合
//这个集合和操作和数组一样
//集合中每个元素都是dom对象
//这个集合中的元素顺序是他们在html页面中从上到下的顺序
var hobbies = document.getElementsByName("hobby");
//checked表示复选框的选中状态, 如果选中为true,不选中为false
//这个属性可读,可写
for (var i = 0; i < hobbies.length; i++) {
hobbies[i].checked = true;
}
}
//全不选
function checkNo() {
var hobbies = document.getElementsByName("hobby");
for (var i = 0; i < hobbies.length; i++) {
hobbies[i].checked = false;
}
}
//反选
function checkReverse() {
var hobbies = document.getElementsByName("hobby");
for (var i = 0; i < hobbies.length; i++) {
hobbies[i].checked = !hobbies[i].checked;
// if (hobbies[i].checked){
// hobbies[i].checked = false;
// }else {
// hobbies[i].checked = true;
// }
}
}
</script>
</head>
<body>
兴趣爱好:
<input type="checkbox" name="hobby" value="cpp" checked="checked">C++
<input type="checkbox" name="hobby" value="java">Java
<input type="checkbox" name="hobby" value="js">JavaScript
<br/>
<button onclick="checkAll()">全选</button>
<button onclick="checkNo()">全不选</button>
<button onclick="checkReverse()">反选</button>
</body>
</html>
9.2.5 getElementsByTagName
- 根据标签元素的标签名得到标签元素集合
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//全选
function checkAll() {
//document.getElementsByTagName();是按照指定的标签名来进行查询并返回集合
//这个集合和操作和数组一样
//集合中每个元素都是dom对象
//这个集合中的元素顺序是他们在html页面中从上到下的顺序
var inputs = document.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++) {
inputs[i].checked = true;
}
}
</script>
</head>
<body>
兴趣爱好:
<input type="checkbox" value="cpp" checked="checked">C++
<input type="checkbox" value="java">Java
<input type="checkbox" value="js">JavaScript
<br/>
<button onclick="checkAll()">全选</button>
</body>
</html>
9.2.6 document对象的三个查询方法总结
- document对象的三个查询方法
- 如果标签中有id属性,优先使用getElementById方法来进行查询
- 如果标签中没有有id属性,有name属性, 则优先使用getElementByName方法来进行查询
- 如果标签中没有有id和name属性,那么使用getElementsByTagName方法来进行查询
- 以上三个查询方法, 一定要在页面加载完成后执行, 才能查询到标签对象
9.3 节点的常用属性和方法
- 节点就是标签对象
- 方法
- getElementsByTagName(): 获取当前节点的指定标签名孩子节点
- appendChild(oChildNode): 可以添加一个子节点, oChildNode是要添加的孩子节点
- 属性:
- childNodes: 获取当前节点的所有子节点
- firstChild: 获取当前节点的第一个子节点
- lastChild: 获取当前节点的最后一个子节点
- parentNode: 获取当前节点的父节点
- nextSibling: 获取当前节点的下一个节点
- previousSibling: 获取当前节点的上一个节点
- className: 用于获取或设置标签的class属性值
- innerHTML: 表示获取或设置起始标签和结束标签中的内容
- innerText: 表示获取或设置起始标签和结束标签中的文本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
//要求用js代码来创建html标签, 并显示在页面上
//内容为JavaScript 很牛
window.onload = function () {
var divObj = document.createElement("div");
divObj.innerHTML = "JavaScript 很牛";
document.body.appendChild(divObj);
}
</script>
</head>
<body>
</body>
</html>
3_JavaScript的更多相关文章
- 100本最棒的web前端图书推荐
前端技术,要学习的内容太多了,当你不知道从哪里开始的时候,你就先从看书开始,边看书边码代码,这个是学习编程必须的过程,因为你看一百遍,还不如自己写一遍,写一遍,第一可以加印象,第二便于更好的理解. 熟 ...
随机推荐
- Note -「Dijkstra 求解 MCMF」
食用前请先了解 SPFA + Dinic/EK 求解 MCMF. Sol. 总所周知,SPFA 牺牲了.于是我们寻求一些更稳定的算法求解 MCMF. 网络流算法的时间属于玄学,暂且判定为混乱中的稳定. ...
- ArrayList的操作和对象数组
ArrayList是List接口的一个实现类,它是程序中最常见的一种集合. ArrayList内部的数据存储结构时候数组形式,在增加或删除指定位置的元素时,会创建新的数组,效率比较低,因此不适合做大量 ...
- 发布自己的npm组件库
发布自己的npm组件库 前期准备 **git上建立自己的仓库,这样子是为了在本地初始化时,可以直接生成对应的 package.json ** 克隆仓库 创建仓库成功后,gitbush本地,执行 git ...
- 2507-AOP- springboot中使用-使用注解方式
Springboot中使用aop,与SSM中使用AOP,整体配置与编写方式都是类似的.但是Springboot简化了很多xml配置,切点的表达式可以直接进行javaconfig. 记录一些示例 spr ...
- 使用Docker-compose搭建nginx-keepalived双机热备来实现高可用nginx集群
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_117 最近同学出去面试经常会被问到一个问题. 面试官:你说你们公司使用nginx反向代理tornado,部署了多少多少台机器,好像 ...
- Odoo env.ref()函数
python env.ref()函数作用是获取xml id记录. 1 action = self.env.ref('base.res_company_action').read()[0] 2 acti ...
- Apache SeaTunnel (Incubating) 2.1.0 发布,内核重构、全面支持 Flink
2021 年 12 月 9 日,SeaTunnel (原名 Waterdrop) 成功加入 Apache 孵化器,进入孵化器后,SeaTunnel 社区花费了大量时间来梳理整个项目的外部依赖以确保整个 ...
- jQuery基础入门(一)
jQuery是什么? jQuery是一个JavaScript常用的工具函数库.jQuery是一个轻量级的"写的少,做的多"的JavaScript库. jQuery当中包含有以下一些 ...
- Luogu3398 仓鼠找sugar (LCA)
第一发lg[]没开够RE了,下了数据本地一直停止运行,还以为是dfs死了,绝望一交,A了... 判断\(x\)是否在路径\(s-t\)上,只需满足 \(dep_{x} >= dep_{LCA(s ...
- Redis 19 整合SpringBoot
参考源 https://www.bilibili.com/video/BV1S54y1R7SB?spm_id_from=333.999.0.0 版本 本文章基于 Redis 6.2.6 概述 Spri ...