JavaScript 基础4 BOM和DOM

BOM

1、BOM的概念和定义 (browser object model浏览器对象模型)

  • Bom 就是浏览器的对象【模型】,我们如何操控这个对象模型?
    在这里插入图片描述
    提起BOM就不得不提起JavaScript的构成。
  • ECMAScript为JavaScript的核心,但是要是在浏览器中使用JavaScript,那么JavaScript需要听从BOM的调遣。

2、系统对话框

  • window 方法 (一般情况下window可以省略)
    浏览器可以通过alert()、confirm()和prompt()方法可以调用系统对话框向用户显示信息。
  • alert() 弹出警告框
  • confirm() 弹出一个带确定和取消的提示框
    返回值:如果点击确定,返回true
    如果点击取消,返回false
  • prompt() 弹出一个带输入框的提示框
    第一个参数:面板上显示的内容
    第二个参数:输入框里面的默认(可以不传入)
    返回值:点击确定,返回输入框中的内容
    点击取消,返回null。
       //弹出警告
        alert(“Lee”);            //直接弹出警告框  window.alert()  window可省略
       //提示框
       //确定和取消
          confirm(“请确定或者取消”);
          if(confirm((“请确定或者取消”)){
    		  alert(“您按了确定!”);      //按确定返回true
		  }else{
     		  alert(“您按了取消!”)       //按取消返回false
		  }
        //输入带输入提示框
        var num = prompt(“请输入一个数字”, 0); //两个参数,一个提示,一个值
        alert(num);     //得到输入的值

3、open方法

  • window.open() 方法可以导航到一个特定的URL,也可以打开一个新的浏览器窗口,一般可以接受三个参数:
    1. 要加载的URL
    2. 窗口的名称或者窗口的目标
    3. 一个特性的字符串
open(“http://www.baidu.com”);              //新建页面并打开百度
open(“http://www.baidu.com”, “baidu”);       //新建页面并命名窗口并打开百度
open(“http://www.baidu.com”, “_parent”);     //在本页窗口打开,_blank是新建

【注】不命名会每次打开新窗口,命名的第一次打开新窗口,之后在这个窗口中加载。
第三个参数字符串中的参数说明:

open('http://www.baidu.com','baidu','width=400,height=400,top=200,left=200’); 
//open本身返回子窗口的window对象
var box = open();
box.alert(''); //可以指定弹出的窗口执行 alert();

4、延时器

  • setTimeout() 指定的时间过后执行代码
function box(){
alert(“Lee”);
}
setTimeout(box, 1000); //直接传入函数名即可
setTimeout(function(){   //推荐做法,匿名函数
alert(“Lee”);
}, 1000);
  • 【注】直接使用函数传入的方法,扩展性好,性能更佳。
    上述方法会返回唯一标识符,可以通过它来取消超时调用。
    要取消尚未执行的超时调用计划,可以调用**clearTimeout()**方法并将相应的超时调用ID作为参数传递给它。
    clearTimeout(timer);

5、location对象(地址栏)

location是BOM对象之一,它提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能

  • location对象是window对象的属性,也是document对象的属性;
  • 所以window.location和document.location等效

5.1.location对象的属性

  • url:统一资源定位符。

  • 协议://IP(域名)/:端口号/路径/?查询字符串#锚点

location.hash = ‘#1’;             //设置#后的字符串,并跳转
alert(location.hash);              //获取#后的字符串
location.port = 8888;            //设置端口号,并跳转
alert(location.port);                //获取当前端口号
location.hostname = ‘Lee’ ;  //设置主机名,并跳转
alert(location.hostname);       //获取主机名
location.pathname = ‘Lee’;   //设置当前路径,并跳转
alert(location.pathname);       //获取当前路径
location.protocal = “ftp:”;      //设置协议,没有跳转
alert(location.protocal);          //获取当前协议
location.search = “?id=5”;     //设置?后面的字符串,并跳转
alert(location.search);            //获取?后面的字符串
location.href = “http://www.baidu.com”;    //设置跳转的URL,并跳转
alert(location.href);                //获取当前的URL

5.2.location对象的方法

  • location.assign(‘http://www.baidu.com’); //跳转到指定的URL,在当前窗口跳转带这个url
  • location.reload(); //最有效的重新加载,有可能缓存加载
  • location.reload(true); //强制加载,从服务器源头重新加载
  • location.replace(“http://www.baidu.com”); //在当前窗口替换成新的url。不会产生历史记录。

6、history对象:掌管当前窗口历史记录

  • 【history对象】
    history对象是window对象的属性,它保存这用户上网的记录,从窗口被打开的那一刻算起。

  • 属性
    history.length; //history对象中的记录数

  • 方法
    history.back(); //前往浏览器历史条目前一个URL,类似后退
    history.forward(); //前往浏览器历史条目下一个URL,类似前进
    history.go(num); //浏览器在history对象中向前或向后

    • 参数: 0 刷新当前页面
      正整数 前进n条记录
      负整数 后退n条记录

DOM

1.文档对象模型DOM(document Object Model)

  • DOM 是 W3C(万维网联盟)的标准。DOM 定义了访问 HTML 和 XML 文档的标准:

  • “W3C 文档对象模型 (DOM) 是中立于平台和语言的接口,它允许程序和脚本动态地访问和更新文档的内容、结构和样式。”

    • HTML-页面结构
    • css-页面样式
    • javascript –页面行为操作
  • DOM 中的三个字母,

  1. D(文档)可以理解为整个 Web 加载的网页文档;
  2. O(对象)可 以理解为类似 window 对象之类的东西,可以调用属性和方法,这里我们说的是 document 对象;
  3. M(模型)可以理解为网页文档的树型结构。
    在这里插入图片描述
    所谓DOM就是以家族的形式描述HTML 节点有 父子 兄弟
    注:在JavaScript里真的这么叫!!!只不过加上了节点两个字称作父子节点,兄弟节点。
  • 加载 HTML 页面时,Web 浏览器生成一个树型结构,用来表示页面内部结构。DOM 将 这种树型结构称为节点组成的节点树。

2、节点的种类

测试 Div

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

3、查找元素节点

  1. document.getElementById(id);

  2. node.getElementsByTagName(标签名);

    • 功能:从node节点开始,通过标签名获取符合条件的元素节点。
    • 返回值:伪数组/类数组
  3. node.getElementsByClassName(class名字) (IE8以下不兼容)

    • 功能:通过class名字获取符合条件的元素节点。
  4. document.getElementsByName(name属性的值);

    • 功能:通过name属性的值获取符合条件的元素节点。
    • 【注】一般使用在表单元素里。

3.1.getElementById方法

  • getElementById()方法,接受一个参数:获取元素的 ID。
  • 如果找到相应的元素则返回该 元素的 HTMLDivElement 对象,如果不存在,则返回 null。
	document.getElementById('box'); //获取 id 为 box 的元素节点
  • PS:上面的例子,默认情况返回 null,这无关是否存在 id="box"的标签,而是执行顺序 问题。解决方法:
    1. 把 script 调用标签移到 html 末尾即可;
    2. 使用 onload 事件来处理 JS,等 待 html 加载完毕再加载 onload 事件里的 JS。
			window.onload=function() { //预加载 html 后执行         
			        document.getElementById('box');     //id具有唯一性
			};
			//可以通过 if(document.getElementById) //来判断是否支持

3.2.元素节点属性

当我们通过 getElementById()获取到特定元素节点时,这个节点对象就被我们获取到了, 而通过这个节点对象,我们可以访问它的一系列属性。

document.getElementById(‘box’).tagName; //DIV
document.getElementById(‘box’).innerHTML; //测试 Div

3.3.元素节点的HTML属性

  • document.getElementById(‘box’).id; //获取 id
  • document.getElementById(‘box’).id=‘person’; //设置 id
  • document.getElementById(‘box’).title; //获取 title
  • document.getElementById(‘box’).title=‘标题’ //设置 title
  • document.getElementById(‘box’).style; //获取 CSSStyleDeclaration 对象
  • document.getElementById(‘box’).style.color; //获取 style 对象中 color 的值
  • document.getElementById(‘box’).style.color=‘red’; //设置 style 对象中 color 的值
  • document.getElementById(‘box’).className; //获取 class
  • document.getElementById(‘box’).className=‘box’; //设置 class
  • alert(document.getElementById(‘box’).bbb); //获取自定义属性的值,不支持

4、getElementsByTagName()方法(标签名)

  • getElementsByTagName()方法将返回 一个数组(伪、类数组)HTMLCollection(NodeList),这个数组保存着所有相同元素名的节点列表。
	document.getElementsByTagName('li'); //获取所有 li 元素,返回数组 
	document.getElementsByTagName('li')[0]; //获取第一个 li 元素
	document.getElementsByTagName('li').item(0) //获取第一个 li 元素,HTMLLIElement
	document.getElementsByTagName('li').length; //获取所有 li 元素的数目

PS:不管是 getElementById 还是 getElementsByTagName,在传递参数的时候,并不是 所有浏览器都必须区分大小写,为了防止不必要的错误和麻烦,我们必须坚持养成区分大小 写的习惯。

5、getElementsByName()方法

  • getElementsByName()方法可以获取相同名称(name)的元素,返回一个对象数组 HTMLCollection(NodeList)。
  • 一般使用在表单元素里
 document.getElementsByName('add') //获取 input 元素 
 document.getElementsByName('add')[0].value //获取 input 元素的 value 值
  • PS:可以获取到具有属性name并name相同的不同元素节点,但是一定要注意该元素节点是否支持name属性。

6、getElementsByClassName()方法

IE8以下该方法无法使用。
在这里插入图片描述
在这里插入图片描述

7、querySelector

document.querySelector()

  • 返回值:一个元素节点,找到符合条件的第一个元素节点。
  • 参数:字符串 CSS选择器格式字符串。对于多个选择器,使用逗号隔开,返回一个匹配的元素。
	var node = document.querySelector("ol .box");	
	var node = document.querySelector("[name=hello]");
	node.style.backgroundColor = 'red'; 

document.querySelectorAll()

  • 返回值:返回值,是一个伪数组。
  • 参数:字符串 CSS选择器格式字符串。
    // var nodes = document.querySelectorAll('#ul1');
    // var nodes = document.querySelectorAll('ol li');
    // var nodes = document.querySelectorAll('ol .box');
    var nodes = document.querySelectorAll('ul [name=hello]');
    alert(nodes.length);
    for(var i = 0; i < nodes.length; i++){
        nodes[i].style.backgroundColor = 'red';
    }

7.1、获取当前有效样式

  1. getStyle(elem, “attr”)
  2. getComputedStyle(elem)[“attr”]
  • return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
    这里做了浏览器兼容处理
    • 查找指定元素指定CSS属性的值
      • @param elem 指定的元素
      • @param attr 指定的CSS属性
      • @return 返回对指定元素查找到的CSS属性值
        在这里插入图片描述
	function getStyle(elem, attr) {
	    return elem.currentStyle ? elem.currentStyle[attr] : getComputedStyle(elem)[attr];
	}
	window.onload = function(){
	var box = document.getElementById("div_id");
	//alert(box.currentStyle["color"]);
	alert(getComputedStyle(box)["color"]); //火狐支持 谷歌safari
	}

7.2 设置样式

  • style.xxx方式设置css样式。
	 var oBtn = document.getElementById("btn1");
	                oBtn.onclick = function(){
	                    oDiv.style.backgroundColor = 'orange';
	                    oDiv.style.height = '500px';

7.3 跨浏览器的兼容

    function getStyle(node, cssStyle){
        return node.currentStyle ? node.currentStyle[cssStyle] : getComputedStyle(node)[cssStyle];
    }

8、setAttribute、getAttribute、removeAttribute方法

  1. getAttribute
    • getAttribute()方法将获取元素中某个属性的值。它和直接使用.属性获取属性值的方法有 一定区别。
    • document.getElementById(‘box’).getAttribute(‘id’);//获取元素的 id 值
    • document.getElementById(‘box’).id; //获取元素的 id 值
    • document.getElementById(‘box’).getAttribute(‘mydiv’);//获取元素的自定义属性值
    • document.getElementById(‘box’).mydiv; //获取元素的自定义属性值
    • document.getElementById(‘box’).getAttribute(‘class’);//获取元素的 class 值
    • document.getElementById(‘box’).getAttribute(‘className’);
    • 1、class的访问
    • 2、支持自定义属性
  •           /* alert(oDiv.className);
              alert(oDiv.getAttribute("class")); */
    
              /* alert(oDiv.xxx);
              alert(oDiv.getAttribute("xxx")); */
    
    
              // oDiv.className = 'box4';
              /* oDiv.zzz = 'ooo';
              alert(oDiv.zzz); */
    
              /* oDiv.setAttribute("class", 'box5');
              oDiv.setAttribute("zzz", 'ooo'); */
    
              oDiv.className = '';
              oDiv.removeAttribute("title");`
    
  1. setAttribute
    • setAttribute()方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。
    • document.getElementById(‘box’).setAttribute(‘align’,‘center’);//设置属性和值
    • document.getElementById(‘box’).setAttribute(‘bbb’,‘ccc’);//设置自定义的属性和值
  2. removeAttribute
    • removeAttribute() 可以移除 HTML 属性
    • document.getElementById(‘box’).removeAttribute(‘style’);//移除属性

9、firstChild和lastChild属性

firstChild 用于获取当前元素节点的第一个子节点,相当于 childNodes[0];
lastChild 用于获取当前元素节点的最后一个子节点,相当于

	childNodes[box.childNodes.length- 1]
	alert(box.firstChild.nodeValue); //获取第一个子节点的文本内容
	alert(box.lastChild.nodeValue);  //获取最后一个子节点的文本内容

10、DOM节点(节点属性)

  • 节点可以分为元素节点、属性节点和文本节点
  • 节点又有三个非常有用的属性, 分别为:nodeName、nodeType 和 nodeValue
    document.getElementById(‘box’).nodeType; //1,元素节点

11、childNodes

  • childNodes 访问当前节点下所有的子节点

  • firstChild 访问子节点中的首位

  • lastChild 访问子节点中的最后一位

  • nextSibling 访问当前节点兄弟节点中的下一个节点

  • previousSibling 访问当前节点兄弟节点中的上一个节点

  • 【注】上述这些属性都包含文本节点

  • 【注】下述这些方法获取子节点中的元素节点。(IE8以下不兼容)

    • children
    • firstElementChild
    • lastElementChild
    • nextElementtSibling
    • previousElementSibling
  • nodeType nodeName nodeValue

  • 元素节点 1 标签名 null

  • 属性节点 2 属性名 属性值

  • 文本节点 3 #text 文本内容
    childeNodes 属性可以获取某一个元素节点的所有子节点,这些子节点包含元素子节点 和文本子节点

	var box=document.getElementById(‘box'); //获取一个元素节点 
	alert(box.childNodes.length);           //获取这个元素节点的**所有子节点**
	alert(box.childNodes[0]);               //获取第一个子节点对象 

PS:使用 childNodes[n]返回子节点对象的时候,
有可能返回的是元素子节点,比如 HTMLElement;
也有可能返回的是文本子节点,比如 Text。

  • 元素子节点可以使用 nodeName 或者 tagName 获取标签名称
  • 文本子节点可以使用 nodeValue 获取
	for(vari=0;i<box.childNodes.length;i++){
		//判断是元素节点,输出元素标签名
		        if(box.childNodes[i].nodeType===1){
		    alert('元素节点:'+ box.childNodes[i].nodeName);
		//判断是文本节点,输出文本内容
		  }else if(box.childNodes[i].nodeType===3){
		alert('文本节点:'+ box.childNodes[i].nodeValue);
		}
	}
  • 空格、回车、换行 看不见,是字符。
  • 【注】获取当前节点的父节点通过parentNode获取。
  • 【注】获取当前整个页面的根节点 document

11.1.innerHTML和nodeValue的区别

  • innerHTML 获取标签间内容 会解析标签
  • innerText 获取标签间纯文本 不会解析标签,设置纯文本
  • outerHTML 从外标签开始到外标签结束 会解析标签
  • 在这里插入图片描述

PS:在获取到文本节点的时候,是无法使用 innerHTML 这个属性输出文本内容的。这个非标准的属性必须在获取元素节点的时候,才能输出里面包含的文本

  • alert(box.innerHTML); //innerHTML 和 nodeValue 第一个区别
  • box.childNodes[0].nodeValue; //innerHTML 和 nodeValue 第一个区别
  • PS:innerHTML 和 nodeValue 第一个区别,就是取值的。那么第二个区别就是赋值的时 候,nodeValue 会把包含在文本里的 HTML 转义成特殊字符,从而达到形成单纯文本的效果。
  • box.childNodes[0].nodeValue=‘abc’;
    //结果为:abc
  • box.innerHTML=‘abc’;
    //结果为:abc 加粗

12、parentNode、previousSibling、nextSibling和ownerDocument属性

  • ownerDocument 属性返回该节点的文档对象根节点,返回的对象相当于 document
  • alert(box.ownerDocument=== document); //true,根节点
  • parentNode、previousSibling、nextSibling 属性
  • parentNode //属性返回该节点的父节点,
  • previousSibling //属性返回该节点的前一个同级节点,
  • nextSibling //属性返回该节点的后一个同级节点。
  • alert(box.parentNode.nodeName); //获取父节点的标签名
  • alert(box.lastChild.previousSibling); //获取前一个同级节点
  • alert(box.firstChild.nextSibling); //获取后一个同级节点

父子节点:

兄弟节点:

13、一些补充

IE6-8IE9-10 Chrome FireFox
firstChild 第一个节点firstElementChild 第一个节点
lastChild最后一个节点、lastElementChild 最后一个节点
nextSibling 下一同级节点nextElementtSibling 下一同级节点
previousSibling 上一同级节点previousElementSibling 上一同级节点

14、attributes属性(了解)

attributes 属性返回该节点的属性节点集合。

box.attributes //NamedNodeMap
box.attributes.length; //返回属性节点个数
box.attributes[0]; //Attr,返回最后一个属性节点
box.attributes[0].nodeType; //2,节点类型
box.attributes[0].nodeValue; //属性值
box.attributes[‘id’]; //Attr,返回属性为 id 的节点
box.attributes.getNamedItem(‘id’); //Attr

       alert(oDiv.attributes.getNamedItem("title").nodeName);
       alert(oDiv.attributes.getNamedItem("title").nodeType);
       alert(oDiv.attributes.getNamedItem("title").nodeValue);

       alert(oDiv.attributes["title"].nodeName);
       alert(oDiv.attributes["title"].nodeType);
       alert(oDiv.attributes["title"].nodeValue);

15、忽略空白节点

	var body= document.getElementsByTagName('body')[0];//获取 body 元素节点
	alert(body.childNodes.length); //得到子节点个数,

PS:在非 IE 中,标准的 DOM 具有识别空白文本节点的功能,所以在火狐浏览器是 7 个,而 IE 自动忽略了,如果要保持一致的子元素节点,需要手工忽略掉它。

  • 方法1:
		function filterSpaceNode(nodes){
		var ret=[]; //新数组
		for(vari=0;i<nodes.length;i++) {
		//如果识别到空白文本节点,就不添加数组
		if(nodes[i].nodeType== 3&&/^\s+$/.test(nodes[i].nodeValue))
		continue; //把每次的元素节点,添加到数组里 ret.push(nodes[i]);
		}
		return ret;
		}

PS:上面的方法,采用的忽略空白文件节点的方法,把得到元素节点累加到数组里返 回。那么还有一种做法是,直接删除空位文件节点即可

  • 方法2:
		function filterSpaceNode(nodes){
		for(vari=0;i<nodes.length;i++) {
		      if(nodes[i].nodeType== 3&&/^\s+$/.test(nodes[i].nodeValue)){
		      //得到空白节点之后,移到父节点上,删除子节点           nodes[i].parentNode.removeChild(nodes[i]);
		     }
		}
		    return nodes;
		}

16、节点操作

DOM 不单单可以查找节点,也可以创建节点、复制节点、插入节点、删除节点和替换 节点。

  • write()

    write()方法可以把任意字符串插入到文档中去。

	document.write('<p>这是一个段落!</p>')'; //输出任意字符串
  • createElement()方法
    createElement() 方法可以创建一个元素节点。

  • document.createElement(‘p’); //创建一个元素节
    document.write()【注】会覆盖页面上原有的内容。

  • createElement()
    格式:document.createElement()
    参数:标签名
    返回值:创建好的这个节点

  • appendChild()
    格式:node1.appendChild(node2);
    功能:将node2节点插入到node1节点子节点的末尾

  • createTextNode()
    格式:document.createTextNode(文本);
    功能:创建文本节点(纯文本)

  • insertBefore()
    格式:box1.parentNode.insertBefore(box2, box1);
    功能:将box2添加到box1的前面

  • replaceChild()
    格式:box1.parentNode.replaceChild(box2, box1);
    功能:用box2节点将box1节点替换掉。

  • cloneNode()
    格式:node.cloneNode() 克隆节点本身
    格式2:node.cloneNode(true); 克隆节点本身和子节点
    返回值:克隆出来的新节点

  • removeChild()
    格式:box.parentNode.removeChild(box);
    功能:将box节点从页面上删除,用父节点调用删除

  • appendChild()

	appendChild()方法讲一个新节点添加到某个节点的子节点列表的末尾上。
	var box=document.getElementById(‘box’); //获取某一个元素节点
	var p=document.createElement('p'); //创建一个新元素节点<p>
	box.appendChild(p); //把新元素节点<p>添加子节点末尾

17. this

  • this概念:只要封装函数,任何一个函数系统都会内置一个叫做this的变量,
  • this变量存储的是地址,是当前函数主人的地址。

【注】this永远指向当前函数的主人。函数的主人要通过当前上下文去判断。

this类似于现实生活中,用到的"我"。
在这里插入图片描述

18. offset系列

  • 眼睛能看到的实际的宽高
    • offsetWidth
    • offsetHeight
      window.onload = function(){
          var oDiv = document.getElementById("div1");
          // alert(getStyle(oDiv, "width"));

          // alert(oDiv.offsetWidth); //width + border + padding (眼睛能看到的实际的宽)
          
      }
  • 眼睛能看到实际距离第一个有定位的父节点的距离。
    • offsetLeft
    • offsetTop
       window.onload = function(){
           var oDiv2 = document.getElementById("div2");

           // alert(getStyle(oDiv2, "left")); //auto

           alert(oDiv2.offsetLeft); //眼睛能看到实际距离第一个有定位的父节点的距离。
       }

19.文档碎片问题

  • 先创建好10W个节点,将10W节点查入到一个节点上,最后将这1个节点添加到页面上,这样速度快。
    在这里插入图片描述
	            /* 
                创建10W个节点,添加到页面上
            */
            window.onload = function(){
                console.time("test1");
                //test1:120 毫秒 - 倒计时结束
                for(var i = 0; i < 100000; i++){
                    var newDiv = document.createElement("div");
                    document.body.appendChild(newDiv);
                }

                console.timeEnd("test1");


                /* 
                    先创建好10W个节点,将10W节点查入到一个节点上,最后将这1个节点添加到页面上
                */

                //test2:78 毫秒 - 倒计时结束   文档碎片
                console.time("test2");
                var node = document.createElement("div");
                for(var i = 0; i < 100000; i++){
                    var newDiv = document.createElement("div");
                    node.appendChild(newDiv);
                }
                document.body.appendChild(node);
                console.timeEnd("test2");
            }

20. 遍历

  • 数组:
    • for循环
    • for…in快速遍历
    • forEach
        var arr = [10, 20, 30, 40, 50];
        for(var i = 0; i < arr.length; i++){
            document.write("for, " + i + ", " + arr[i] + "<br/>");
        }

        for(var i in arr){
            document.write("forin, " + i + ", " + arr[i] + "<br/>");
        }


        arr.forEach(function(item, index, arr){
            document.write("forEach, " + index + ", " + item + "<br/>");
        });
  • 对象遍历
         //对象遍历
         var person = {
             username: "钢铁侠",
             age: 18,
             sex: "男"
         };

         //对象遍历  for...in

         for(var i in person){
             // i  是当前遍历到的属性
             document.write("对象遍历:" + i + ", " + person[i] + "<br/>");
         }
  1. 延时器
		/* 
           延迟对应毫秒数以后,有且仅执行一次
       */
       var timer = setTimeout(function(){
           alert("hello world");
       }, 4000);

       window.onload = function(){
           var oBtn = document.getElementById("btn1");
           oBtn.onclick = function(){
               clearTimeout(timer);
           }
       }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值