JS第二部分

一、DOM

DOM:文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可拓展标记语言的标准编程接口。通过DOM提供的接口可以对页面上的各种元素进行操作(大小、位置、颜色等)。
文档:一个页面就是一个文档,在DOM中用document表示
元素:页面中的所有标签都是元素,在DOM中用element表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

1.操作元素

1)改变元素内容

语法:
element.innerText
// 从起始位置到终止位置的内容,但它去除html标签,同时空格和换行也会去掉
element.innerHTML
// 起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div id="div1"></div>
    <div id="div2"></div>
    <p>
        段落
        <span>123</span>
    </p>
    <script>
        var div1 = document.getElementById('div1');
        var div2 = document.getElementById('div2');
        div1.innerText = '<strong>你好</strong>,明天';
        // innerText 不识别html标签,去除空格和换行
        div2.innerHTML = '<strong>你好</strong>,明天';
        // innerHTML 识别html标签,保留空格和换行
        var p = document.querySelector('p');
        console.log(p.innerText);
        console.log(p.innerHTML);
        // 这个两个属性可以获取元素里面的内容
    </script>
</body>
</html>

效果图:
在这里插入图片描述

2)常用元素的属性操作

  1. innerText、innerHTML改变元素内容
  2. src、herf
  3. id、alt、title
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <div><img src="#"></div>
    <script>
        var img = document.querySelector('img')
        img.onmouseover = function() {
            img.src = 'https://uploadstatic.mihoyo.com/contentweb/20211103/2021110322064026502.png'
        }
    </script>
</body>
</html>

效果图:
在这里插入图片描述
在这里插入图片描述

3)表单元素的属性操作

利用DOM可以操作的表单元素属性:type、value、checked、selected、disabled

4)样式属性操作

语法:
1. element.style
// 行内样式操作
// js修改style样式操作,产生的是行内样式,css权重比较高
2. element.className
// 类名样式操作
// className会直接更改元素的类名,会覆盖原先的类名

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
    <style>
        .one {
            width: 400px;
            height: 400px;
            background-color: aqua;
        }
        .two {
            width: 20px;
            height: 50px;
            background-color: blueviolet;
        }
    </style>
</head>
<body>
    <div class="one"></div>
    <script>
        var div = document.querySelector('div')
        div.onmouseover = function() {
            div.className = 'two'
        }
    </script>
</body>
</html>

效果图:
在这里插入图片描述
鼠标放上去后
在这里插入图片描述

5)自定义属性的操作

5.1 获取属性值

语法:
element.属性
// 获取内置属性值(元素本身自带的属性)
element.getAttribute(‘属性’);
// 主要获得自定义的属性(程序员自定义的属性)

5.2 设置属性值

语法:
element.属性 = ‘值’
// 设置内置属性值
element. getAttribute(‘属性’, ‘值’);
// 设置自定义的属性

6)H5自定义属性

自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中。
H5规定自定义属性date-开头作为属性名并且赋值。
例:
< div data-index = “1” >< / div >
element.setAttribute( ‘data-index’ , 1 );

获取H5自定义属性

语法:
1. element.setAttribute( ‘data-index’);
//兼容性获取
2. element.dataset.index 或者 element.dataset[ ‘index’ ]
//H5新增,ie11才开始支持

2.节点操作

节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

1)节点概述

获取元素通常使用两种方式:利用DOM提供的方法获取元素;利用节点层级关系获取元素
但是用DOM提供的方法获取元素,逻辑性不强且繁琐
利用系欸但那层级关系获取元素,可以通过父子兄节点关系获取元素,逻辑性强,但是兼容性稍差

节点至少拥有三个基本属性:nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)

  • 元素节点 nodeType 为1
  • 属性节点 nodeType 为2
  • 文本节点 nodeType 为3(文本系欸但包含文字、空格、换行等)

// 在实际开发中,节点操作主要操作的是元素节点

2)节点层级

父级节点

语法:node.parentNode
parentNode属性可返回某节点的父节点,注意是最近的一个父节点
如果指定的系欸但没有父节点则返回null

子节点

语法:
1. parentNode.childNodes(标准)
// 返回值里面包含了所有的子节点,如:元素节点,文本节点等
// 如果只想要获得里面的元素节点,需要专门处理
2. parentNode.children(非标准)
// parentNode.children是一个只读属性。它只返回子元素节点,其余节点不返回
3. parentNode.firstChild
// 返回第一个子节点,找不到则返回null,包含所有的节点
4. parentNode.lastChild
// 返回最后一个子节点,找不到则返回null,包含所有的节点
5. parentNode.firstElementChild
// 返回第一个子节点,找不到则返回null
6. parentNode.lastElementChild
// 返回最后一个子节点,找不到则返回null
// 5.6都有兼容性问题,ie9以上支持

兼容性解决:
1. parentNode.chilren[0]
2. parentNode.chilren[parentNode.chilren.length - 1]

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <ol>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ol>
    <script>
        
        var ol = document.querySelector('ol')
        console.log(ol.childNodes)
        console.log(ol.children)
        for(var i = 0; i < ol.childNodes.length; i++) {
            if(ol.childNodes[i].nodeType == 1) {
                console.log(ol.childNodes[i])
            }
        }
        console.log(ol.firstChild)
        console.log(ol.lastElementChild)
        console.log(ol.children[0])
        console.log(ol.children[ol.children.length - 1])
    </script>
</body>
</html>

效果图:
在这里插入图片描述

兄弟节点

语法:
1. node.nextSibling
// 返回当前元素的下一个兄弟节点,找不到则返回null,包含所有节点
2. node.previousSibling
// 返回当前元素的上一个兄弟节点,找不到则返回null,包含所有节点
3. node.nextElementSibling
// 返回当前元素下一个兄弟节点,找不到则返回null
4. node.previousElementSibling
// 返回当前元素的上一个兄弟节点,找不到则返回null
// 3.4都有兼容性问题,ie9以上支持

兼容性解决(封装一个兼容性的函数)

<script>
	function getNextElementSibling(element) {
		var el =element
		while(el =el.nextSibling) {
			if(el.nodeType == 1) {
				return el;
			}
		}
		return null;
	}
</script>

3)创建节点

语法:document.createElement( ‘tagName’ )
// 由tagName指定html元素,这些元素本不存在,根据需求动态生成的,所有称为动态创建元素节点

三种动态创建元素的区别
  • document.write()
  • element.innerHTML
  • document.createElement()

区别:

  1. document.write是直接将内容写入页面的内容流,但是文本流执行完毕,则会导致页面全部覆盖
  2. innerHTML是将内容写入某个DOM节点,不会导致页面全部重绘
  3. innerHTML创建多个元素效率更高(不要拼接字符串,采取数组形式拼接),结构稍微复杂
  4. createElement()创建多个元素效率稍微低一点点,但是结构更清晰

4)增加节点

语法:
1.node.appendChild(child)
// 将一个节点添加到指定父节点的子节点列表末尾。类似css中的after伪元素
2.node.insertBefore(child, 指定元素)
// 将一个节点添加到指定父节点的子节点前面。类似css中的before伪元素

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <ul></ul>
    <script>
        var ul = document.querySelector('ul')
        var li = document.createElement('li')
        ul.appendChild(li)
    </script>
</body>
</html>

效果图:
在这里插入图片描述

5)删除节点

语法:node.removeChild(child)
// 从DOM中删除一个子节点,返回删除的节点

6)复制节点

语法:node.cloneNode()
// 调用该方法的节点的一个副本 //
如果括号参数为空或者为false,则是浅拷贝,即只复制节点本身,不复制里面的子节点 //
如果括号参数为true,则是深度拷贝,会复制节点本身以及里面所有的子节点

7)DOM操作总结

DOM针对元素的操作,主要由创建、增、删、改、查、属性操作、事件操作。

7.1 创建
  1. document.write
  2. innerHTML
  3. createElement
7.2 增
  1. appendChild
  2. insertBefore
7.3 删
  1. removeChild
7.4 改
  1. 修改元素属性:scr、herf、title
  2. 修改普通元素内容:innerHTML、innerText
  3. 修改表单元素:value、type、disabled
  4. 修改元素样式:style、className
7.5 查
  1. DOM提供的API方法:getElementById、getElementsByTagName
  2. H5提供的新方法:querySelector、querySelectorAll
  3. 利用节点操作获取元素:父(parentNode)、子(children)、兄(previousElementSibling、nextElementSibling)
7.6 属性操作

主要针对自定义属性

  1. setAttribute:设置dom的属性值
  2. getAttribute:得到dom的属性值
  3. removeAttribute移除属性
7.7 事件操作
鼠标事件触发条件
onclick鼠标点击左键触发
onmouseover鼠标经过触发
onmouseout鼠标离开触发
onfocus获得鼠标焦点触发
onblur失去鼠标焦点触发
onmousemove鼠标移动触发
onmouseup鼠标弹起触发
onmousedown鼠标按下触发

二、事件高级

1.注册事件

给元素添加事件称为注册事件或者绑定事件。
注册事件由两种方式:传统方式和方法监听注册方式

传统注册方式

  • 利用on开头的事件
  • < button onclick = “alert(‘hi’)” >< / botton >
  • btn.onclick = function() {}
  • 特点:注册事件的唯一性
  • 同一个元素同一个事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数

方法监听注册方式

  • W3C推荐
  • addEventListener()它是一个方法
  • IE9之前的IE不支持此方法,可使用attachEvent() 代替
  • 特点:同一个元素同一个事件可以注册多个监听器

2.事件监听方式

1)addEventListener

语法:eventTarget.addEventListener( type, listener[ , useCapture ] )
该方法接受三个参数:

  • type:事件类型字符串,比如:click,mouseover,注意不要带on
  • listener:事件处理函数,事件发生时,会调用该监听函数
  • useCapture:可选参数,是一个布尔值,默认是false
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <button>1</button>
    <button>2</button>
    <script>
        var buts = document.querySelectorAll('button')
        buts[0].onclick = function() {
            alert('hi')
        }
        buts[0].onclick = function() {
            alert('nihao')
        }
        // 只会显示你好
        buts[1].addEventListener('click', function() {
            alert(22)
        })
        buts[1].addEventListener('click', function() {
            alert(33)
        })
        // 显示22然后显示33
    </script>
</body>
</html>

效果图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2)attachEvent

语法:eventTarget.attachEvent( eventNameWithOn, callback )
该方法接受两个参数:

  • evenNameWithOn:事件类型字符串,比如 onclick、onmouseover、这里要带on
  • callback:事件处理函数,当目标触发事件时回调函数被调用

3)兼容性

<script>
	function addEventListener(element,eventName,fn) {
		//判断当前浏览器是否支持addEventListener方法
		if(element.addEventListener) {
			element.addEventListener(eventName,fn);//第三个参数,默认是false
		} else if (element.attachEvent) {
			element.attachEvent('on' + eventName, fn );
		} else {
		//相当于element.onclick = fn;
			element['on' + eventName] = fn;
		}
	}
</script>

3.删除事件方式

  1. 传统注册方式删除
    eventTarget.onclick = null;
  2. 方法监听注册方式删除
    1)eventTarget.removeEventListener( type, listener[ , useCapture] );
    2)eventTarget.detachEvent(eventNameWithOn, callback);

删除事件兼容性解决

<script>
	function removeEventListener(element,eventName,fn) {
		//判断当前浏览器是否支持addEventListener方法
		if(element.removeEventListener) {
			element.removeEventListener(eventName,fn);//第三个参数,默认是false
		} else if (element.detachEvent) {
			element.detachEvent('on' + eventName, fn );
		} else {
			element['on' + eventName] = null;
		}
	}
</script>

4.事件流

事件流描述的是从页面中接受事件的顺序。
事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即DOM事件流
DOM事件流分为3个阶段:1.捕获阶段;2.当前目标阶段;3.冒泡阶段
在这里插入图片描述
注意:

  1. js代码中只能执行捕获或者冒泡其中的一个阶段
  2. onclick和attachEvent只能得到冒泡阶段
  3. addEventListener( type, listener[ , useCapture ] )第三个参数如果是ture,表示在事件捕获阶段调用事件处理程序;如果是false(不写默认就是false),表示在事件冒泡阶段调用事件处理程序
  4. 实际开发中我们很少使用事件捕获,我们更关注事件冒泡
  5. 有些事件是没有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave

5.事件对象

1)事件对象

语法:
eventTarget.onclick = function( event ) { }
eventTarget.addEventListener( ‘click’ , function (event) { } )
// 这个event是事件对象,还可以写成e或者evt
// 事件发生后,跟事件相关的一系列信息数据的集合都放到这个对象event里面

2)兼容性方案

事件对象本身的获取存在兼容问题:
1.标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到
2.在IE6~8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找

兼容性解决: e = e || window.event;

3)事件对象常见属性和方法

事件对象属性方法说明
e.target返回触发事件的对象(标准)
e.srcElement返回触发事件的对象(非标准id6~8使用)
e.type返回事件的类型,比如:click(不带on)
e.cancelBubble该属性阻止冒泡(非标准id6~8使用)
e.returnValue该属性阻止默认事件(默认行为)非标准ie6~8使用,比如不让连接跳转
e.prebentDefault()该方法阻止默认事件(默认行为)标准,比如不让链接跳转
e.stopPropagation()阻止冒泡,标准

6.e.target和this的区别

e.target返回的是触发事件的对象(元素)
this返回的是绑定事件的对象(元素)

7.阻止默认行为

阻止默认行为就是让连接不能跳转,或者提交按钮不能提交

语法:
e.prebentDefault() // 普通浏览器
e.returnValue() // 低版本浏览器
return false // 也能阻止默认行为,但是return后面的代码就不会执行了

8.阻止事件冒泡

  • 标准写法:e.stopPropagation()
  • 非标准写法:IE6-8利用事件对象cancelBubble属性

9.事件委托

事件委托也称为事件代理,在JQuery里面称为事件委派
事件委托的原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,然后利用冒泡原理影响设置每个子节点
事件委托的作用:只操作了一次DOM,提高了程序的性能

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>
    <script>
        var ul = document.querySelector('ul')
        ul.addEventListener('click',function(e) {
            alert("弹出")
            // 不论是点击哪个li都会出现弹框
        })
    </script>
</body>
</html>

10.常用鼠标事件

1)禁止鼠标右键菜单

<script>
	document.addEventListener('contextmenu',function(e) {
	//contextmenu主要控制应该合适显示上下文菜单,主要用于程序员取消默认的上下文菜单
		e.preventDefault();
	})
</script>

2)禁止鼠标选中

<script>
	document.addEventListener('selectstart',function(e) {
	//selectstart开始选中
		e.preventDefault();
	})
</script>

3)鼠标事件对象

鼠标事件对象说明
e.clientX返回鼠标相对于浏览器窗口可视区的X坐标
e.clientY返回鼠标相对于浏览器窗口可视区的Y坐标
e.pageX返回鼠标相对于文档页面的X坐标,IE9+支持
e.pageY返回鼠标相对于文档页面的Y坐标,IE9+支持
e.screenX返回鼠标相对于电脑屏幕的X坐标
e.screenY返回鼠标相对于电脑屏幕的Y坐标

11.常用键盘事件

键盘事件触发条件
onkeyup某个键盘按键被松开时触发
onkeydown某个键盘按键被按下时触发
onkeypress某个键盘按键被按下时触发(但它不识别功能键,比如:ctrl shift 箭头等)

注意:

  1. 使用addEventListener不需要加on
  2. 三个事件的执行顺序是:keydown,keypress,keyup

键盘事件对象属性keyCode,返回该键的ASCII值
其中onkeyup和onkeydown不区分字母大小写,onkeypress区分字母大小写

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <script>
        document.addEventListener('keyup',function() {
            console.log(1);
        })
        document.addEventListener('keydown',function() {
            console.log(2);
        })
        document.addEventListener('keypress',function() {
            console.log(3);
        })
    </script>
</body>
</html>

在这里插入图片描述

三、BOM

BOM:浏览器对象模型(Browser Object Model,简称BOM),它提供了独立于内容的、可以与浏览器窗口进行互动的对象结构。通过BOM可以操作浏览器窗口,比如弹出框、控制浏览器跳转、获取分辨率等。

DOM:文档对象模型,把[文档]当作一个[对象]来看待,DOM的顶级对象是document,主要学习的是操作页面元素,是W3C标准规范
BOM:浏览器对象模型,把[浏览器]当作一个[对象]来看待,BOM的顶级对象是window,主要学习的是浏览器窗口交互的一些对象,BOM是浏览器厂商在各自浏览器上定义的,兼容性较差

1.window对象的常见事件

window对象是浏览器的顶级对象

  1. 它是js访问浏览器窗口的一个接口
  2. 它是一个全部对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法。在调用的时候可以省略window,前面学习的对话框都属于window对象方法,如alert()、prompt()等
  3. window下的一个特殊属性window.name
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <script>
        var num = 10
        console.log(num);
        console.log(window.num);
        function fn() {
            console.log(11);
        }
        fn()
        window.fn()
    </script>
</body>
</html>

效果图:
在这里插入图片描述

1)窗口加载事件

语法:
window.onload = function () {} ;
// 窗口(页面)加载事件,当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS文件等),就调用处理函数,这样就可以把js放在页面元素的上方了
// window.onload 只能写一次,如果有多个,会以最后一个window。onload为准
window.addEventListener( “load”, function() {} ) ;
// 使用没有限制
document.addEventListener(‘DOMContentLoaded’, function() {} )
// 事件触发时,仅当DOM加载完成,不包括样式表,图片,flash等(ie9以上支持)
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的事件,交互效果就不能实现,必然影响用户的体验,此时用DOMContentLoaded事件比较合适

2)调整窗口大小事件

语法:
window.onresize = function() { }
// 调整窗口大小加载事件,当触发时就调用的处理函数
window.addEventListener( “resize” , function() { } )
注意:

  1. 只要窗口大小发生像素变化,就会触发这个事件
  2. 我们经常利用这个事件完成响应式布局。window.inner.Width当前屏幕的宽度

2.定时器

setTimeout() 定时器

语法:window.setTimeout( 调用函数,[延迟的毫秒数] );
注意:

  1. window可以省略
  2. 延迟的毫秒数省略默认是0,如果写,必须是毫秒
  3. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符
  4. setTimeout() 这个调用函数我们也称为回调函数 callback(上一个事情做完,再回头调用这个函数,如click)

clearTimeout() 清除定时器

语法:window.clearTimeout( timeoutID )
// 取消先前通过调用setTimeout()建立的定时器
// 里面的参数就是定时器的标识符

setInterval() 计时器

语法:window.setInterval( 回调函数, [间隔的毫秒数] );
// 重复调用一个函数,每隔这个时间,就去调用一次回调函数
注意:

  1. window可以省略
  2. 延迟的毫秒数省略默认是0,如果写,必须是毫秒
  3. 因为定时器可能有很多,所以我们经常给定时器赋值一个标识符

claerInterval() 停止计时器

语法:window.clearInterval( intervalID )
// 取消先前通过调用setInterval()建立的定时器
// 里面的参数就是定时器的标识符

this

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <script>
        // 全局作用域或者普通函数中的this指向全局对象window
        console.log(this);
        function fn() {
            console.log(this);
        }
        window.fn();
        // 方法调用中的this指向被调用的对象
        var a = {
            one: function() {
                console.log(this);
            }
        }
        a.one()
        // 构造函数中的this指向构造函数的实例
        function fun() {
            console.log(this)
        }
        var b = new fun()
        // 定时器里面的this指向window
        window.setTimeout(function() {
            console.log(this)
        },1000)
    </script>
</body>
</html>

效果图:
在这里插入图片描述

3.JS执行机制

js有一个特点就是单线程,同一时间只能做一件事,于是就出现了同步和异步。

  • 同步:前一个任务结束后执行下一个人物,程序的执行顺序与任务的排列顺序是一致的。
  • 异步:在做一件花费时间很长的任务同时去做其他的任务。(通过回调函数实现,如:click,resize,load,error,定时器)异步任务会添加到任务队列(消息队列)中,先执行执行栈中的同步任务,然后再按次序读取、执行任务队列中的异步任务
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <script>
        window.setTimeout(function() {
            console.log(this)
        },1000)
        // 无论把定时器放在哪里,都是最后执行的
        console.log(this);
        function fn() {
            console.log(this);
        }
        window.fn();
        var a = {
            one: function() {
                console.log(this);
            }
        }
        a.one()
        function fun() {
            console.log(this)
        }
        var b = new fun()
    </script>
</body>
</html>

在这里插入图片描述

4.location对象

location属性用于获取或则会之窗体的url,并且可以用于解析url。

location对象属性返回值
location.href获取或者设置整个url
location.host返回主机(域名)
location.port返回端口号,如果未写返回空字符串
location.pathname返回路径
location.search返回参数
location.hash返回片段,#后面内容,常见于连接,锚点
location对象方法返回值
location.assign()跟herf一样,可以跳转页面(也称为重定向页面)
location.replace()替换当前页面,因为不记录历史,所以不能后退页面
location.reload()重新加载页面,相当于刷新按钮或者f5,如果参数为true强制刷新ctrl+f5

5.navigator对象

navigator对象包含浏览器的信息,它有很多属性,我们最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值

<script>
//判断用户使用哪个终端打开,实现转跳
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|Webos|Symbian|Windows Phone)/i))) {
	window.location.href = ""; //手机
} else {
	window.location.href = ""; //电脑
}
</script>

6.history对象

history对象与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的url

history对象方法作用
back()可以后退功能
forward()前进功能
go(参数)前进后退功能,参数如果是1,则前进一个页面;如果是-1,后退一个页面
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值