JS DOM

DOM

文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言(HTML 或者XML)的标准编程接口。
W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。

DOM 树
在这里插入图片描述
文档:一个页面就是一个文档,DOM 中使用 document 表示
元素:页面中的所有标签都是元素,DOM 中使用 element 表示
节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM 中使用 node 表示

获取元素
获取页面中的元素可以使用以下几种方式:
 根据ID获取
 根据标签名获取
 通过 HTML5 新增的方法获取
 特殊元素获取

根据 ID 获取
使用 getElementById() 方法可以获取带有 ID 的元素对象。
document.getElementById('id');
返回的是元素对象
使用 console.dir() 可以打印我们获取的元素对象,更好的查看对象里面的属性和方法。

    <div id = 'abc'>ID</div>
<script>
    let a = document.getElementById('abc');
    console.log(a);
    console.dir(a);
</script>

根据标签名获取
使用 getElementsByTagName() 方法可以返回带有指定标签名的对象的集合。
document.getElementsByTagName(‘标签名’);
注意:

  1. 因为得到的是一个对象的集合,所以我们想要操作里面的元素就需要遍历。
  2. 得到元素对象是动态的
    <div>ID</div>
    <div>ID</div>
    <div>ID</div>
    <div>ID</div>
<script>
    let a = document.getElementsByTagName('div');
    console.log(a[0]);
    console.dir(a);
</script>

element.getElementsByTageName();
返回指定的确定的一个父元素里的字元素

通过 HTML5 新增的方法获取

  1. document.getElementsByClassName(‘类名’);// 根据类名返回元素对象集合
  2. document.querySelector(‘选择器’); // 根据指定选择器返回第一个元素对象
  3. document.querySelectorAll(‘选择器’); // 根据指定选择器返回
    <div class="box">ID</div>
    <div class="box">ID</div>
<script>
    let a = document.getElementsByClassName('box');
    console.log(a);

注意:
querySelector 和 querySelectorAll里面的选择器需要加符号,比如:document.querySelector(’#nav’);

获取特殊元素(body,html)
doucument.body // 返回body元素对象

获取html元素
document.documentElement // 返回html元素对象

事件基础

事件概述
JavaScript 使我们有能力创建动态页面,而事件是可以被 JavaScript 侦测到的行为。 简单理解: 触发— 响应机制。
网页中的每个元素都可以产生某些可以触发 JavaScript 的事件,例如,我们可以在用户点击某按钮时产生一个 事件,然后去执行某些操作。

事件三要素

  1. 事件源 (谁)
  2. 事件类型 (什么事件)
    1. 事件处理程序 (做啥)

案例:点击按钮弹出警示框
页面中有一个按钮,当鼠标点击按钮的时候,弹出“你好”警示框。
案例分析
1 获取事件源(按钮)
2 注册事件(绑定事件),使用 onclick
3 编写事件处理程序,写一个函数弹出 alert 警示框

实现代码

var btn = document.getElementById('btn');
btn.onclick = function() {
alert('你好吗'); };

执行事件的步骤

  1. 获取事件源
  2. 注册事件(绑定事件)
  3. 添加事件处理程序(采取函数赋值形式)

常见的鼠标事件
在这里插入图片描述

操作元素
JavaScript 的 DOM 操作可以改变网页内容、结构和样式,我们可以利用 DOM 操作元素来改变元素里面的内 容 、属性等。注意以下都是属性

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

    <button>Click</button>
    <div>Change</div>
<script>
    let btn = document.querySelector('button');
    let div = document.querySelector('div');
    btn.onclick = function () {
        div.innerText = '2000'
    }
</script>

ps:这两个是可以进行读写操作的

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

    <button>Click</button>
    <label>
        <input value="Start">
    </label>
    <script>
    let a = document.querySelector('button');
    let b = document.querySelector('input');
    a.onclick = function () {
        b.value = 'End';
    }
</script>

样式属性操作

我们可以通过 JS 修改元素的大小、颜色、位置等样式。

  1. element.style 行内样式操作
  2. element.className 类名样式操作
    注意:
    1.JS 里面的样式采取驼峰命名法 比如 fontSize、 backgroundColor
    2.JS 修改 style 样式操作,产生的是行内样式,CSS 权重比较高
    <style>
        div{
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        let div = document.querySelector('div');
        div.onclick = function () {
            this.style.backgroundColor = 'red'
        }
    </script>

案例: 淘宝点击关闭二维码
当鼠标点击二维码关闭按钮的时候,则关闭整个二维码。

案例分析
1 核心思路: 利用样式的显示和隐藏完成, display:none 隐藏元素 display:block 显示元素
2 点击按钮,就让这个二维码盒子隐藏起来即可

var btn = document.querySelector('.close-btn'); 
var box = document.querySelector('.box');
// 2.注册事件 程序处理
btn.onclick = function() {
box.style.display = 'none';

案例:显示隐藏文本框内容
当鼠标点击文本框时,里面的默认文字隐藏,当鼠标离开文本框时,里面的文字显示。

案例分析
1 首先表单需要2个新事件,获得焦点 onfocus 失去焦点 onblur
2 如果获得焦点, 判断表单里面内容是否为默认文字,如果是默认文字,就清空表单内容
3 如果失去焦点, 判断表单内容是否为空,如果为空,则表单内容改为默认文字

样式属性操作
我们可以通过 JS 修改元素的大小、颜色、位置等样式。

  1. element.style 行内样式操作
  2. element.className 类名样式操作
    注意:
  3. 如果样式修改较多,可以采取操作类名方式更改元素样式。
  4. class因为是个保留字,因此使用className来操作元素类名属性
  5. className 会直接更改元素的类名,会覆盖原先的类名。
    <style>
        div{
            width: 100px;
            height: 100px;
            background-color: aqua;
        }
        .change{
            margin: 200px;
            width: 100px;
            height: 100px;
            background-color: antiquewhite;
        }
    </style>
</head>
<body>
    <div></div>
    <script>
        let div = document.querySelector('div');
        div.onclick = function () {
            this.className = 'change';
        }
    </script>

操作元素总结
操作元素是 DOM 核心内容
在这里插入图片描述
排他思想
在这里插入图片描述

如果有同一组元素,我们想要某一个元素实现某种样式, 需要用到循环的排他思想算法:

  1. 所有元素全部清除样式(干掉其他人)
  2. 给当前元素设置样式 (留下我自己)
  3. 注意顺序不能颠倒,首先干掉其他人,再设置自己
    <button>Button</button>
    <button>Button</button>
    <button>Button</button>
    <button>Button</button>
    <button>Button</button>

    <script>
        let btns = document.getElementsByTagName('button');
        for(let i =0;i<btns.length;i++){
                btns[i].onclick = function () {
                    for(let j =0;j<btns.length;j++) {
                        btns[j].style.backgroundColor = 'white';
                    }
                    this.style.backgroundColor = 'red';
            }
        }
    </script>

案例:百度换肤
案例分析
1 这个案例练习的是给一组元素注册事件
2 给4个小图片利用循环注册点击事件
3 当我们点击了这个图片,让我们页面背景改为当前的图片
4 核心算法: 把当前图片的src 路径取过来,给 body 做为背景即可

// 1. 获取元素
var imgs = document.querySelector('.baidu').querySelectorAll('img'); // 2. 循环注册事件
for (var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function() { document.body.style.backgroundImage = 'url(' + this.src + ')';
}
}

表格隔行变色
案例分析
1 用到新的鼠标事件 鼠标经过 onmouseover 鼠标离开 onmouseout
2 核心思路:鼠标经过 tr 行,当前的行变背景颜色, 鼠标离开去掉当前的背景颜色
3 注意: 第一行(thead里面的行)不需要变换颜色,因此我们获取的是 tbody 里面的行

        table{
        }
        tbody tr{
            height: 30px;
        }

        tbody td{
            border-bottom: 1px wheat;
            font-size: 12px;
            color: blue;
        }
        .bg{
            background-color: palegoldenrod;
        }
    </style>
</head>
<body>
    <table>
        <thead>lalalala</thead>
        <tbody>
            <tr>
                <td>123</td>
                <td>123</td>
                <td>123</td>
                <td>123</td>
            </tr>
            <tr>
                <td>123</td>
                <td>123</td>
                <td>123</td>
                <td>123</td>
            </tr>
            <tr>
                <td>123</td>
                <td>123</td>
                <td>123</td>
                <td>123</td>
            </tr>
        </tbody>
    </table>
<script>
    let tbody = document.querySelector('tbody').querySelectorAll('tr');
    for(let i =0;i<tbody.length;i++){
        tbody[i].onmousemove = function () {
            console.log('1234');
        this.className = 'bg';
        };
        tbody[i].onmouseout = function () {
            this.className = '';

        }
    }
</script>

案例:
表单全选取消全选案例

业务需求:

  1. 点击上面全选复选框,下面所有的复选框都选中(全选)
  2. 再次点击全选复选框,下面所有的复选框都不中选(取消全选)
  3. 如果下面复选框全部选中,上面全选按钮就自动选中
  4. 如果下面复选框有一个没有选中,上面全选按钮就不选中
  5. 所有复选框一开始默认都没选中状态
    在这里插入图片描述
    案例分析
    1 全选和取消全选做法: 让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
    2 下面复选框需要全部选中, 上面全选才能选中做法: 给下面所有复选框绑定点击事件,每次点击,都要循环查看下面所有的复选框是否有没选中的,如果有一个没选中的, 上面全选就不选中。
    3 可以设置一个变量,来控制全选是否选中
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style>
    table{
        border-collapse: collapse;
    }
    table,table tr td {
        border:1px solid #ccc;
    }
    table tr td{
        padding: 5px 10px;
        width: 50px;
    }
    table tr th{
        padding: 5px 10px;
        width: 50px;
    }
    table,table tr th {
        border:1px solid #ccc;
    }
    table th{
        background-color: cornflowerblue;
    }
</style>
<body>
<table>
    <tr>
        <th>
            <input type="checkbox" id='chooseAll'>
        </th>
        <th>内容</th>
        <th>内容</th>
        <th>内容</th>
    </tr>
    <tbody id = 'choose'>
    <tr>
        <td>
            <input type="checkbox" >
        </td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <td>
            <input type="checkbox"/>
        </td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    <tr>
        <td>
            <input type="checkbox"/>
        </td>
        <td>内容</td>
        <td>内容</td>
        <td>内容</td>
    </tr>
    </tbody>
</table>
<script>
    let chooseAll = document.getElementById('chooseAll');
    let choose = document.getElementById('choose').getElementsByTagName('input');
    chooseAll.onclick =function () {
        for (let i=0;i<choose.length;i++){
            //this.checked被选中时就是true,没被选中时就是false
            choose[i].checked = this.checked;
        }
    };
    for (let i=0;i<choose.length;i++){
        choose[i].onclick = function () {
            for(let i=0;i<choose.length;i++){
                if(choose[i].checked === false){
                    chooseAll.checked = false;
                    break;
                }
                chooseAll.checked = true;
            }
        }
    }
</script>
</body>
</html>

自定义属性的操作

获取属性值
element.属性 获取属性值。
element.getAttribute(‘属性’);

区别:
element.属性 获取内置属性值(元素本身自带的属性)
element.getAttribute(‘属性’); 主要获得自定义的属性 (标准) 我们程序员自定义的属性

自定义属性的操作

设置属性值
element.属性 = ‘值’ 设置内置属性值。
element.setAttribute(‘属性’, ‘值’);

区别:
element.属性 设置内置属性值
element.setAttribute(‘属性’); 主要设置自定义的属性 (标准)

移除属性
element.removeAttribute(‘属性’);

tab 栏切换(重点案例)
当鼠标点击上面相应的选项卡(tab),下面内容跟随变化
在这里插入图片描述
案例分析
1 Tab栏切换有2个大的模块
2 上的模块选项卡,点击某一个,当前这一个底色会是红色,其余不变(排他思想) 修改类名的方式
3 下面的模块内容,会跟随上面的选项卡变化。所以下面模块变化写到点击事件里面。
4 规律:下面的模块显示内容和上面的选项卡一一对应,相匹配。
5 核心思路: 给上面的tab_list 里面的所有小li 添加自定义属性,属性值从0开始编号。
6 当我们点击tab_list 里面的某个小li,让tab_con 里面对应序号的 内容显示,其余隐藏(排他思想)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<style>
    li{
        float: left;
        height: 40px;
        line-height: 40px;
        padding: 0 20px;
        text-align: center;
        cursor: pointer;
        list-style: none;
    }
    .tabList .current{
        background-color: red;
        color: white;
    }
    .item{
        display: none;
    }
    .container{
        flex-direction: column;
        display: flex;
    }

</style>
<body>
<div class="container">
<div class="tab">
    <div class="tabList">
        <ul>
            <li class="current">商品介绍</li>
            <li>规格与包装</li>
            <li>售后保障</li>
            <li>商品评价</li>
            <li>手机社区</li>
        </ul>
    </div>
</div>

<div class="tabContent">
    <div  class="item">
       内容1</div>
    <div class="item">
        内容2</div>
    <div class="item">
       内容3</div>
    <div class="item">
       内容4</div>
    <div class="item">
       内容5</div>
</div>
</div>
<script>
    //注意class名字前要加个点
    let tableList = document.querySelector('.tabList');
    let list =tableList.querySelectorAll('li');
        for (let i = 0; i < list.length; i++) {
            list[i].setAttribute('index', i);
            list[i].onclick = function () {
                for (let i = 0; i < list.length; i++) {
                    list[i].className = '';
                }
                this.className = 'current';
                let index = this.getAttribute('index');
                console.log(index);

                let item = document.querySelectorAll('.item');
                for(let i=0;i<item.length;i++){
                    item[i].style.display = 'none';
                }
                item[index].style.display = 'block';
            }
        }
</script>
</body>
</html>

H5自定义属性
自定义属性目的:是为了保存并使用数据。有些数据可以保存到页面中而不用保存到数据库中。
自定义属性获取是通过getAttribute(‘属性’) 获取。 但是有些自定义属性很容易引起歧义,不容易判断是元素的内置属性还是自定义属性。 H5给我们新增了自定义属性:
设置H5自定义属性
H5规定自定义属性data-开头做为属性名并且赋值。
比如
<div data-index=“1”></div>
或者使用 JS 设置 element.setAttribute(‘data-index’, 2)

节点操作
获取元素通常使用两种方式:
在这里插入图片描述
节点概述
网页中的所有内容都是节点(标签、属性、文本、注释等),在DOM 中,节点使用 node 来表示。
HTML DOM 树中的所有节点均可通过 JavaScript 进行访问,所有 HTML 元素(节点)均可被修改,也可以 创建或删除。
在这里插入图片描述
节点概述
一般地,节点至少拥有nodeType(节点类型)、nodeName(节点名称)和nodeValue(节点值)这三个 基本属性。

元素节点 nodeType 为1
属性节点 nodeType 为2
文本节点 nodeType 为 3 (文本节点包含文字、空格、换行等)
我们在实际开发中,节点操作主要操作的是元素节点

节点层级
利用 DOM 树可以把节点划分为不同的层级关系,常见的是父子兄层级关系。

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

子节点
parentNode.childNodes(标准)
parentNode.childNodes 返回包含指定节点的子节点的集合,该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点等。 如果只想要获得里面的元素节点,则需要专门处理。 所以我们一般不提倡使用childNodes

var ul = document. querySelector(‘ul’); for(var i = 0; i < ul.childNodes.length;i++) {
if (ul.childNodes[i].nodeType == 1) { // ul.childNodes[i] 是元素节点 console.log(ul.childNodes[i]);
}
 }

子节点
parentNode.children(非标准)
parentNode.children 是一个只读属性,返回所有的子元素节点。它只返回子元素节点,其余节点不返
回 (这个是我们重点掌握的)。
虽然children 是一个非标准,但是得到了各个浏览器的支持,因此我们可以放心使用

子节点
parentNode.firstChild
firstChild 返回第一个子节点,找不到则返回null。同样,也是包含所有的节点。
parentNode.lastChild
lastChild 返回最后一个子节点,找不到则返回null。同样,也是包含所有的节点。

parentNode.firstElementChild
firstElementChild 返回第一个子元素节点,找不到则返回null。
parentNode.lastElementChild
lastElementChild 返回最后一个子元素节点,找不到则返回null。
注意:这两个方法有兼容性问题,IE9 以上才支持。

实际开发中,firstChild 和 lastChild 包含其他节点,操作不方便,而 firstElementChild 和 lastElementChild 又有兼容性问题,那么我们如何获取第一个子元素节点或最后一个子元素节点呢?
解决方案:

  1. 如果想要第一个子元素节点,可以使用 parentNode.chilren[0]
  2. 如果想要最后一个子元素节点,可以使用 parentNode.chilren[parentNode.chilren.length - 1]

案例:下拉菜单
在这里插入图片描述
案例分析
1 导航栏里面的li 都要有鼠标经过效果,所以需要循环注册鼠标事件
2 核心原理: 当鼠标经过li 里面的 第二个孩子 ul 显示, 当鼠标离开,则ul 隐藏

var nav = document.querySelector('.nav'); 
var lis = nav.children; // 得到4个小li
for (var i = 0; i < lis.length; i++) { 
lis[i].onmouseover = function() { 
this.children[1].style.display = 'block'; 
}
lis[i].onmouseout = function() { 
this.children[1].style.display = 'none';
 }
}

兄弟节点
node.nextSibling
nextSibling 返回当前元素的下一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。
node.previousSibling
previousSibling 返回当前元素上一个兄弟元素节点,找不到则返回null。同样,也是包含所有的节点。

node.nextElementSibling
nextElementSibling 返回当前元素下一个兄弟元素节点,找不到则返回null。
node.previousElementSibling
previousElementSibling 返回当前元素上一个兄弟节点,找不到则返回null。

问:如何解决兼容性问题 ?
答:自己封装一个兼容性的函数

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

创建节点
document.createElement('tagName')
document.createElement() 方法创建由 tagName 指定的 HTML 元素。因为这些元素原先不存在, 是根据我们的需求动态生成的,所以我们也称为动态创建元素节点。

添加节点
node.appendChild(child)
node.appendChild() 方法将一个节点添加到指定父节点的子节点列表末尾。类似于 CSS 里面的 after 伪元素
node.insertBefore(child, 指定元素)
node.insertBefore() 方法将一个节点添加到父节点的指定子节点前面。类似于 CSS 里面的 before 伪元素。

<ul></ul>
<script>
    let li = document.createElement('li');
    let ul = document.querySelector('ul');
    ul.appendChild(li);
</script>

案例:简单版发布留言案例

案例分析
1 核心思路: 点击按钮之后,就动态创建一个li,添加到ul 里面。
2 创建li 的同时,把文本域里面的值通过li.innerHTML 赋值给 li
3 如果想要新的留言后面显示就用 appendChild 如果想要前面显示就用insertBefore

<label>
<textarea rows="" cols="">
    123
</textarea>
    <button>发布</button>
    <ul>
        <li>123</li>
    </ul>
</label>
<script>
    let button = document.querySelector('button');
    let text = document.querySelector('textarea');
    let ul  = document.querySelector('ul');
    button.onclick = function () {
        let li = document.createElement('li');
        li.innerText = text.value;
        ul.appendChild(li);
    }
</script>

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

案例:删除留言案例
1 当我们把文本域里面的值赋值给li 的时候,多添加一个删除的链接
2 需要把所有的链接获取过来,当我们点击当前的链接的时候,删除当前链接所在的li
3 阻止链接跳转需要添加 javascript:void(0); 或者 javascript:;

复制节点(克隆节点)
node.cloneNode()
node.cloneNode() 方法返回调用该方法的节点的一个副本。 也称为克隆节点/拷贝节点
注意:

  1. 如果括号参数为空或者为 false ,则是浅拷贝,即只克隆复制节点本身,不克隆里面的子节点。
  2. 如果括号参数为 true ,则是深度拷贝,会复制节点本身以及里面所有的子节点。

案例:动态生成表格
在这里插入图片描述
案例分析
1 因为里面的学生数据都是动态的,我们需要js 动态生成。 这里我们模拟数据,自己定义好 数据。 数据我们采取对象形式存储。
2 所有的数据都是放到tbody里面的行里面。
3 因为行很多,我们需要循环创建多个行(对应多少人)
4 每个行里面又有很多单元格(对应里面的数据),我们还继续使用循环创建多个单元格,
并且把数据存入里面(双重for循环)
5 最后一列单元格是删除,需要单独创建单元格。 6 最后添加删除操作,单击删除,可以删除当前行。

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

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

DOM 重点核心
文档对象模型(Document Object Model,简称 DOM),是 W3C 组织推荐的处理可扩展标记语言 (HTML或者XML)的标准编程接口。
W3C 已经定义了一系列的 DOM 接口,通过这些 DOM 接口可以改变网页的内容、结构和样式。

  1. 对于JavaScript,为了能够使JavaScript操作HTML,JavaScript就有了一套自己的dom编程接口。
  2. 对于HTML,dom使得html形成一棵dom树. 包含 文档、元素、节点
    我们获取过来的DOM元素是 一个对象(object),所以称 为 文档对象模型

关于dom操作,我们主要针对于元素的操作。主要有创建、增、删、改、查、属性操作、事件操作。

创建
1.document.write
2. innerHTML
3. createElement

4. appendChild
5. insertBefore

6. removeChild

主要修改dom的元素属性,dom元素的内容、属性, 表单的值等
7. 修改元素属性: src、href、title等
8. 修改普通元素内容: innerHTML 、innerText
9. 修改表单元素: value、type、disabled等
10. 修改元素样式: style、className

主要获取查询dom的元素
11. DOM提供的API 方法: getElementByIdgetElementsByTagName 古老用法 不太推荐
12. H5提供的新方法: querySelectorquerySelectorAll 提倡
13. 利用节点操作获取元素: 父(parentNode)、子(children)、兄(previousElementSibling、 nextElementSibling) 提倡
属性操作
主要针对于自定义属性。
14. setAttribute:设置dom的属性值
15. 2. getAttribute:得到dom的属性值
16. 3. removeAttribute移除属性
事件操作
给元素注册事件, 采取 事件源.事件类型 = 事件处理程序
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值