感激相遇 你好 我是阿ken
作者:请叫我阿ken
链接:请叫我阿ken主页链接
来源:CSDN
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
文章部分内容及图片出自网络,如有问题请与我本人联系(主页介绍中有公众号)
本博客暂适用于刚刚接触 JS以及好久不看想要复习的小伙伴。
JavaScript DOM上
Web API 是浏览器提供的一套操作浏览器功能和页面元素的接口。
例如,在前面的学习中,经常使用的 console.log() 就是一个接口。 这里的 console 对象表示浏览器的控制台,调用它的 log() 方法就可以在控制台中输出调试信息。
JavaScript 语言由3部分组成,分别是 ECMAScript ( JavaScript 语法 )、BOM( 页面文档对象模型 ) 和 DOM ( 浏览器对象模型 ) ,其中 ECMAScript 是 JavaScript 语言的核心,它的内容包括前面学习的 JavaScript 基本语法、 数组、函数和对象等,即 JavaScript 基础。而 Web API 包括 BOM 和 DOM 两部分。
在学习 JavaScript 时,基础阶段学习的是 ECMAScript 的基础语法,是为学习 Web API 部分做前期的铺垫;学习 Web API 阶段是 JavaScript 的实战应用。在这一阶段将会大量使用 JavaScript 基础语法来实现网页的交互效果。
_
应用程序编程接口 ( Application Prgramming Interface,API)是一些预先定义的函数,这些函数是由某个软件开放给开发人员使用的,帮助开发者实现某种功能。开发人员无须访问源码、无须理解其内部工作机制细节,只需知道如何使用即可。
_
例如,开发一个美颜相机的手机应用。该应用需要调起手机上的摄像头来拍摄画面,如果没有 API ,则开发这个应用将无从下手。因此,手机的操作系统为了使其他应用具有访同手机摄像头的能力,就开放了一套 API ,然后由手机应用的开发工具将 API 转换成一个可以被直接调用的函数。直接调用函数就能完成调用摄像头,获取摄像头拍摄的画面等功能。开发人员的主要工作是查阅 API 文档,了解 API 如何使用。
_
Web API是主要针对浏览器的 API ,在 JavaScript 语言中被封装成了对象,通过调用对象的属性和方法就可以使用 Web API。在前面的学习中,经常使用 console.log() 在控制台中输出调试信息,这里的 console 对象就是一个 Web API 。
案例:使用 document.title 属性获取或设置页面的标题、使用 document.write 方法写人页面内容,
document.title = '设置新标题';// 设置页面标题
console.log (document.title);// 获取页面标题
document.write ('网页内容
');// 将字符串写入页面
文档对象模型 ( Document Object Model, DOM ),是 W3C 组织推荐的处理可扩展标记语言 ( HTML或者XML ) 的标准编程接口。
W3C 定义了一系列的 DOM 接口,利用 DOM 可完成对 HTML 文档内所有元素的获取、访问、标签属性和样式的设置等操作。在实际开发中,诸如改变盒子的大小、标签栏的切换、购物车功能等带有交互效果的页面,都离不开 DOM。
DOM 中将 HTML 文档视为树结构,所以被称之为文档树模型,把文档映射成树形结构,通过节点对象对其处理,处理的结果可以加人到当前的页面。
树
上图展示了 DOM 树中各节点之间的关系后,接下来我们针对 DOM 中的专有名词进行解释,具体如下:
在开发中,想要操作页面上的某个部分 ( 如控制一个 div 元素的显示或隐藏、修改 div 元素的内容等 ),需要先获取到该部分对应的元素,再对其进行操作。
下面我们将分别介绍获取元素的几种常见方式。
getElementById() 方法是由 document 对象提供的用于查找元素的方法。该方法返回的是拥有指定 id 的元素,如果没有找到指定 id 的元素则返回 null ,如果存在多个指定 id 的元素则返回 undefined 。需要注意的是,JavaScript 中严格区分大小写,所以在书写时一定要遵守书写规范,否则程序会报错。
案例:演示 document.getElementById(‘id’) 方法的使用,
<body>
<div id="box">你好div>
<script>
var Obox = document.getElementById('box');
console.log (Obox);// 结果为: 你好
console.log (typeof Obox);// 结果为: object
console.dir (Obox);// 结果为: div#box
script>
body>
上述代码中,在第2行定义了一个< div>标签,由于文档是从上往下加载的,所以第 3 ~ 8 行的 < script> 标签和 JavaScript 代码要写在第 2 行代码的下面,这样才可以正确获取到 div 元素。第 4 行代码用于获取 HTML 中 id 为 box 的元素,并赋值给变量 Obox 。需要注意的是,id 值不能像 CSS 那样加 “ # ”,如 getElementByld ( “#box” ) 是错误的。第7行的 console.dir() 方法用来在控制台中查看对象的属性和方法。
根据标题名获取元素有两种方式,分别是通过 document 对象获取元素和通过 element 对象获取元素。
代码如下所示,
document.getElementByTagName ('标签名');
element.getElementsByTagName ('标签名');
上述代码中的 element 是元素对象的统称。通过元素对象可以查找该元素的子元素或后代元素,实现局部查找元素的效果,而 document 对象是从整个文档中查找元素。
由于相同标签名的元素可能有多个,上述方法返回的不是单个元素对象,而是一个集合。这个集合是一个类数组对象,或称为伪数组,它可以像数组一样用索引来访问元素, 但不能使用 push() 等方法。使用 Array.isArray() 也可以证明它不是一个数组。
案例:演示,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<ul>
<li>苹果li>
<li>香蕉li>
<li>西瓜li>
<li>樱桃li>
ul>
<ol id="ol">
<li>绿色li>
<li>蓝色li>
<li>白色li>
<li>红色li>
ol>
<script>
var lis = document.getElementsByTagName('li');
// 结果为: HTMLCollection(8) [li, li, li, li, li, li, li, li]
console.log(lis);
// 查看集合中的索引为 0 的元素,结果为: 苹果
console.log(lis[0]);
//遍历集合中的所有元素
for(var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
//通过元素对象获取元素
var ol = document.getElementById('ol');
// 结果为: HTMLCollection(4) [li, li, li, li]
console.log (ol.getElementsByTagName('li'));
script>
body>
html>
上述代码中,
定义了一个 < ul> 无序列表,
定义了一个 id 为 ol 的 < ol> 有序列表。
演示了 document.getElementsByTagName() 的用法,其中返回的是所有 < li> 标签元素对象的集合。
需要注意的是,即使页面中只有一个 li 元素,返回结果仍然是一个集合,如果页面中没有该元素,那么将会返回一个空的集合。
通过代码的输出结果可以看出,lis 是一个包含 8 个 li 元索的集合对象,这个对象的构造函数是 HTMLCollection 。
返回集合中的第 1 个 li 元素。
采用遍历的方式依次打印了集合里面的元素对象。
演示了 element.getElementsByName() 的用法,这里的 element 必须是单个对象,不能是一个集合,所以需要用 document.getElementsById() 获取元素,再调用方法。
使用 getElementsByTagName() 去获取 ol 中的所有 li 元素。
通过 name 属性来获取元素应使用 document.getElementsByName() 方法,一般用于获取表单元素。
name 属性的值不要求必须是唯一的, 多个元素也可以有同样的名字,如表单中的单选框和复选框。
案例:演示复选框,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<p>请选择你最喜欢的水果(多选)p>
<label><input type="checkbox" name="fruit" value="苹果">苹果label>
<label><input type="checkbox" name="fruit" value="香蕉">香蕉label>
<label><input type="checkbox" name="fruit" value="西瓜">西瓜label>
<script>
var fruits = document.getElementsByName('fruit');
fruits[0].checked = true;
script>
body>
html>
在上述代码中,getElementsByName() 方法返回的是一个对象集合, 使用索引获取元素。fruit [0].checked 为 true,表示将 fruits 中的第1个元素的 checked 属性值设置为 true ,表示将这一项勾选。
HTML5 中为 document 对象新增了 getElementsByClassName()、 querySelector() 和 querySelectorAIl() 方法,在使用时需要考虑到浏览器的兼容性问题。
document.ElementsByClassName() 方法,用于通过类名来获得某些元素集合。
下面通过案例代码进行演示,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<span class="one">英语span>
<span class="two">数学span>
<span class="one">语文span>
<span class="two">物理span>
<script>
var Ospan1 = document.getElementsByClassName('one');
var Ospan2 = document.getElementsByClassName('two');
Ospan1[0].style.fontWeight = 'bold';
Ospan2[1].style.background = 'red';
script>
body>
html>
上述代码中,分别使用 getElementsByClassName() 方法获取类名为 one 和 two 的集合,并分别存储在 Ospan1 和 Ospan2 中。使用下标的形式,查找并设置 Ospan1 数组中下标为 0 所对应的第 1 个元素的 fontWeight 属性为 bold,Ospan2 数组中下标为 1 所对应的第 2 个元素的 backgound 属性为 red 。
querySelector() 方法用于返回指定选择器的第一个元素对象。querySelectorAll() 方法用于返回指定选择器的所有元素对象集合。
案例:演示,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<div class="box">盒子1div>
<div class="box">盒子2div>
<div id="nav">
<ul>
<li>首页li>
<li>产品li>
ul>
div>
<script>
var firstBox = document.querySelector('.box');
console.log(firstBox); // 获取class为box的第1个div
var nav = document.querySelector('#nav');
console.log(nav); // 获取id为nav的第1个div
var li = document.querySelector('li');
console.log(li); // 获取匹配到的第1个li
var allBox = document.querySelectorAll('.box');
console.log(allBox); // 获取class为box的所有div
var lis = document.querySelectorAll('li');
console.log(lis); // 获取匹配到的所有li
script>
body>
html>
从上述代码可以看出,在利用 querySelector() 和 querySelectorAlI() 方法获取操作的元素时,直接书写标签名或 CSS 选择器名称即可。 根据类名获取元素时在类名前面加上 “.”,根据 id 获取元素时在 id 前面加上 “#” 。
document 对象提供了一些属性, 可用于获取文档中的元素,例如,获取所有表单标签、图片标签等。
document 对象的属性:
属性 | 说明 |
---|---|
document.body | 返回文档的body元素 |
document.title | 返回文档的title元素 |
document.documentElement | 返回文档的html元素 |
document.forms | 返回对文档中所有Form对象的引用 |
document.images | 返回对文档中所有Image对象的引用 |
document 对象中的 body 属性用于返回 body 元素,而 documentElement 属性用于返回 HTML 文档的根节点 html 元素。
案例:演示 获取 body 元素和 html 元素,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<script>
var bodyEle = document.body;
console.dir(bodyEle);
var htmlEle = document.documentElement;
console.log(htmlEle);
script>
body>
html>
上述代码中,第 3、4 行代码通过 document.body 的方式获取 body 元素,并通过 console.dir() 的方式在控制台打印出结果。第 5、6 行代码通过 document.documentElement 的方式获取 html 元素,并输出结果。
在获取到元素后,如果需要为元素添加交互行为,这就需要用到事件来实现。
例如,当鼠标指针经过导航栏中的某一项时,自动展开二级菜单,或者在阅读文章时,选中文本后自动弹出分享、复制等选项。
在开发中,JavaScript 帮助开发者创建带有交互效果的页面,是依靠事件来实观的。
事件是指可以被 JavaScript 侦测到的行为,是一种 " 触发-响应 " 的机制。
这些行为指的就是页面的加载、鼠标单击页面、鼠标指针滑过某个区域等具体的动作,它对实现网页的交互效果起着重要的作用。
在学习事件时,我们需要对一些非常基本又相当重要的概念有一定的了解。 事件由事件源、事件类型和事件处理程序这 3 部分组成,又称为事件三要素,具体解释如下。
(1) 事件源: 触发事件的元素。
(2) 事件类型: 如 click 单击事件。
(3) 事件处理程序: 事件触发后要执行的代码 ( 函数形式 ),也称事件处理函数。
以上三要素可以简单理解为 " 谁触发了事件 " " 触发了什么事件 " " 触发事件以后要做什么 " 。
在开发中,为了让元素在触发事件时执行特定的代码,需要为元素注册事件,绑定事件处理函数。具体步骤是,首先获取元素,其次注册事件,最后编写事件处理代码。
案例:演示事件的使用 —— 为按钮绑定单击事件,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<button id="btn">单击button>
<script>
// 第1步:获取事件源
var btn = document.getElementById('btn');
// 第2步:注册事件btn.onclick
btn.onclick = function() {
// 第3步:添加事件处理程序(采取函数赋值形式)
alert('弹出');
}
script>
body>
html>
上述代码中,定义了一个 id 为 btn 的 < button>标签。
通过 getElementById() 的方式获取事件源 btn 。
给事件源 btn 注册事件,语法为 " btn.on 事件类型 ",事件类型 click 表示单击事件,这步操作实际上是为 btn 的 onclick 属性赋值一个函数,这个函数就是事件中处理程序。
通过浏览器打开上述案例代码,使用鼠标单击页面中的按钮,就会弹出个警告框, 说明页面中的按钮已经绑定了单击事件。在事件处理函数中,我们可以编写其他想要在事件触发时执行的代码。另外,事件类型除了 click,还有很多其他的类型,具体会在后面的章节进行详细讲解。
在 Javascript 中,DOM 操作可以改变网页内容、结构和样式。
接下来我们将会讲解如何利用 DOM 操作元素的对象属性,改变元素的内容、属性和样式。
操作元素内容的常用属性:
属性 | 说明 |
---|---|
element.innerHTML | 设置或返回元素开始和结束标签之间的 HTML,包括 HTML 标签,同时保留空格和换行 |
element.innerText | 设置或返回元素的文本内容,在返回的时候会去除 HTML 标签和多余的空格、换行,在设置的时候会进行特殊字符转义 |
element.textContent | 设置或者返回指定节点的文本内容,同时保留空格和换行 |
上述表中的属性在使用时有一定的区别,innerHTML 在使用时会保持编写的格式以及标签样式;而 innerTest 则是去掉所有格式以及标签的纯文本内容;textContent 属性在去掉标签后会保留文本格式。
案例:分别利用 innerHTML、innerText、textContent 属性在控制台输出一段 HTML 文本,
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<div id="box">
The first parapraph...
<p>
The second Paragraph...
<a href="#">thirda>
p>
div>
body>
html>
在 DOM 中,HTML 属性操作是指使用 JavaScript 来操作一个元素的 HTML 属性。一个元素包含很多的属性,例如,对于一个 img 图片元素来说,我们可以操作它的 src、title 属性等;或者对于 input 元素来说,我们可以操作它的 disabled 、 checked 、 selected 属性等。
案例:如何操作常用元素属性及表单元素属性。
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<button id="flower">鲜花button>
<button id="grass">四叶草button><br>
<img src="#" alt="" title="四叶草">
<script>
// 1.获取元素
var flower = document.getElementById('flower');
var grass = document.getElementById('grass');
var img = document.getElementById('img');
// 2.注册事件处理程序
flower.onclick = function() {
img.src = '#';
img.title = '鲜花';
}
grass.onclick = function() {
img.src = '#';
img.title = '四叶草';
}
script>
body>
html>
上述代码中,通过 querySelector() 方法获取元素。
为 flower 和 grass 事件源添加 onclick 事件。在处理程序中,通过 " 元素对象.属性名 " 来获取属性的值,通 " 元素对象.属性名 = 值 " 的方式设置图片的 src 和 title 属性。
doctype html>
<html>
<head>
<meta charset="utf-8">
<title>title>
head>
<body>
<button>按钮button>
<input type="text" value="输入内容" />
<script>
// 1.获取元素
var btn = document.querySelector('button');
var input = document.querySelector('input');
// 2.注册事件处理程序
btn.onclick = function() {
input.value = '被点击了!'; // 通过value来修改表单里面的值
this.disabled = true; // this指向的是时间函数的调用者btn
}
script>
body>
html>
上述代码中,通过querySelector() 方法获取元素。
为 btn 添加 onclick 事件。在处理程序中,通过 " 元素对象.属性名 = 值 " 的方式设置 input 文本框的 disabled 和 value 属性。最后结果为,当单击按钮后,input 的文本内容变为 ” 被点击了! " 。
在登录页面,为了优化用户体验,方便用户进行密码输人,在设计密码框时,可添加一个“眼睛”图片,充当按钮功能,单击可以切换按钮的状态,控制密码的显示和隐藏。实现步骤如下。
(1)准备一个父盒子div。
(2)在父盒子中放人两个子元素,一个input元素和一个img元素。
(3)单击眼睛图片切换input的type值(ext和pasword )。
隐藏密码的效果如图6-8所示。
显示密码的效果如图6 -9所示。
1234567
图6-8隐藏密码
图6-9显示密码
我就是天花板 2020/10/18 14:11:34
2代码实现结构,完成页面布局,示侧代码如下号HTIL
dJabolsreminagea/clooe .png" altonn id-"eyo">e/label>
cnputtye-pasverd" name-"" id-"ped">
cscript
11 1.我取元素
war eye”document .getElementById('eye');
↓
var pid - document. getElementById('pwd');
12
11 2.注册事件处理程序
13
var flag = 0;
eye.cnclick”function () (
15
11每次单击,修改flag的值
if (fag 0) (
pid.type = 'text';
1
eye.sre”' images/open.png';
19
flag .1;
20
) else 1
21
pd.type = 'password';
22
eye.src . 'images/close.png';
flag = 0;
2
25
26 </acript>
27 </body>
上述代码中,第10、11 行代码获取了按钮元素和文本框元素。第13行代码声明了一个全局变量fag,来记录lype的状态。第14行代码给eye按钮元素添加了onelick 单击事件。第16~ 24行代码使用if判断语句,根据flag的值来改变type和sre的值,当密码隐藏时,单击“眼睛”图片,密码显示;当密码显示时,单击“眼睛”图片,密码隐藏。
操作元素样式有两种方式,一种是操作 style 属性,另一种是操作 className 属性。下面我们分别进行讲解。
除了前面讲解的元素内容和属性外,对于元素对象的样式,可以直接通过 " 元素对象style. 样式属性名 " 的方式操作。样式属性名对应 CSS 样式名,但需要去掉 CSS 样式名里的半字线 " - " ,并将半字线后面的英文的首字母大写。
例如,设置字体大小的样式名 font-size,对应的样式属性名为 fontSize。
常用 style 属性中 CSS 样式名称:
名称 | 说明 |
---|---|
background | 设置或返同元素的背景属性 |
backgroundColor | 设置或返回元素的背景色 |
display | 设置或返同元素的显示类型 |
fontSize | 设置或返回元素的字体大小 |
height | 设置或返回元素的高度 |
left | 设置或返回定位元素的左部位置 |
listStyleType | 设置或返回列表项标记的类型 |
overflow | 设置或返回如何处理呈现在元素框外面的内容 |
textAlign | 设置或返回文本的水平对齐方式. |
textDecoration | 设置或返回文本的修饰 |
textIndent | 设置成返回文本第一行的缩进 |
transform | 向元素应用2D或3D转换 |
案例:如何对元素的样式进行添加,
<body>
<div id="box">div>
<script>
var ele = document.querySelector('#box');
ele.style.width = '100px';
ele.style.height = '100px';
ele.style.transform = 'rotate(7deg)';
script>
body>
上述第 4 ~ 6 行代码用于为获取的 ele 元素对象添加样式,其效果相当于在 CSS 中添加以下样式。
#box {
width: 100px;
height: 100px;
transform: rotate(7deg);
}
在开发中,如果样式修改较多,可以采取操作类名的方式更改元素样式,语法为 " 元素对象.className " 访问 className 属性的值表示获取元素的类名,为 className 属性赋值表示更改元素类名。如果元素有多个类名,在 className 中以空格分隔。
案例:如何使用 className 更改元素的样式。
(1) 编写 html 结构代码,具体示例如下。
<style>
div {
width: 100px;
height: 100px;
background-color: pink;
}
style>
<body>
<div class="first">文本div>
body>
上述代码中,第 9 行代码给 div 元素添加 first 类,并在 style 中设置了 first 的样式。
(2) 单击 div 元素更改元素的样式,示例代码如下。
<script>
var test = document.querySelector('div');
test.onclick = function() {
this.className = 'change';
};
script>
上述代码中,第 2 行代码获取 div 元素存储在 test 对象中。第 3 ~ 5 行代码为 text 对象添加 onclick 单击事件,第 4 行执行事件处理程序使用 thisclassName 给 test 对象设置 change 类名,其中 this 指的是 test 对象。
(3) 在 style 中添加 change 类,样式代码如下。
.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
(4) 单击 div 盒子,浏览器预览效果如下图所示。
执行上述代码之后,会直接把原先的类名 first 修改为 change ,如果想要保留原先的类名,可以采取多类名选择器的方式,修收第 (2) 步的第 4 行代码,示例代码如下。
this.className = 'first change';
修改之后,在控制台可查看到 div 元素的类已经修改成了 < div class = " first change "> 文本< /div>,保留了之前的类名。
本案例需要为一个文本框添加提示文本。当单击文本框时,里面的默认提示文字会隐藏,鼠标指针离开文本框,里面的文字会显示出来。
具体实现步骤如下:
(1) 为元素绑定获取文本框焦点事件 onfocus 和失去焦点事件 onblur。
(2) 如果获取焦点时,需要判断表单里面的内容是否为默认文字;如果是默认文字,就清空表单内容。
(3) 如果失去焦点,需要判断表单内容是否为空;如果为空,则表单里边的内容改为默认文字。
编写 HTML 结构,完成页面布局,示例代码如下。
<body>
<input type="text" value="手机" style="color:999">
body>
上述代码中,第 2 行代码给 input 文本框设置了 value 值,默认内容为 " 手机 " ,字体颜色为 " #999 " 。
编写实现获取焦点时效果的 JavaScript 代码,示例代码如下。
<script>
var text = document.querySelector('input'); // 获取元素
text.onfocus = function() { // 注册获得焦点事件onfocus
if (this.value === '手机') {
this.value = ' ';
this.style.color = '#333';
};
script>
上述代码中,第 2 行代码获取 input 元素并存储在 text 对象中。第 3 ~ 8 行代码给 text 元素注册 onfocus 获得焦点事件。其中,第 4 ~ 7 行使用 if 判断语句,如果文本框的值为默认的手机,则清空表单内容,否则改变文本框里面的文字颜色。
接下来我们继续编写实现失去焦点时效果的JavaScript代码,示例代码如下。
text.onblur = function() { // 注册失去焦点事件onblur
if (this.value === '') {
this.value = '手机';
}
// 失去焦点需要把文本框里面的文字颜色变浅色
this.style.color = '#999';
};
上述代码用来给 text 元素注册 onblur 失去焦点事件。其中,第 2 ~ 4 行代码使用 if 语句判断如果文本框的值为空,则表单里边的内容改为默认文字 " 手机 " 。然后用第 6 行代码改变文本框里面的文字颜色。
今日入门学习暂时告一段落
Peace
JavaScript学习:
挑战最短时间内带你入门 JavaScript(一)
挑战最短时间内带你入门 JavaScript(二)
挑战最短时间内带你入门 JavaScript(三)
挑战最短时间内带你入门 JavaScript(四)
HTML学习:
阿ken的HTML、CSS的学习笔记_HTML基础(笔记一)
阿ken的HTML、CSS的学习笔记_HTML 页面元素和属性(笔记二)
阿ken的HTML、CSS的学习笔记_文本样式属性(笔记三)
阿ken的HTML、CSS的学习笔记_CSS3选择器(笔记四)
阿ken的HTML、CSS的学习笔记_CSS盒子模型(笔记五)
阿ken的HTML、CSS的学习笔记_浮动与定位(笔记六)
阿ken的HTML、CSS的学习笔记_表单的应用(笔记七)
阿ken的HTML、CSS的学习笔记_多媒体技术(笔记八)
阿ken的HTML、CSS的学习笔记_CSS3高级应用(笔记九)
感谢阅读,希望能对你有所帮助 博文若有瑕疵请在评论区留言或在主页个人介绍中添加联系方式私聊我 感谢每一位小伙伴不吝赐教
原创不易,「点赞」+「关注」+「收藏」 谢谢支持❤