JS 节点 正则表达式

1. 节点操作

基本概念
复制标签,会使用克隆方法
写入标签时,会使用节点操作方法

什么是节点?
整个的HTML文件,其中的所有内容,都视为HTML文件的一个节点对象
可以通过操作这些节点对象,来操作HTML文件
DOM节点:DOM 就是我们 html 结构中一个一个的节点构成的
不光我们的标签是一个节点,我们写的文本内容也是一个节点,注释,包括空格都是节点
DOM 的节点我们一般分为常用的三大类 元素节点 / 文本节点 / 属性节点
比如我们在获取元素的时候,通过各种方法获取到的我们叫做元素节点(标签节点)
比如我们标签里面写的文字,那么就是文本节点
写在每一个标签上的属性,就是属性节点
起始节点操作,就是另一种 DOM 操作,也是获取对象,操作对象

只是节点操作,比 DOM 操作,更加复杂更加丰富

节点的类型
之前的 DOM 操作,只能获取标签对象
现在的 节点 操作,可以获取标签对象,可以获取内容对象,可以获取属性对象,甚至可以获取注释内容

通过节点,获取的对象,和通过 DOM方法获取的对象,实际上,是相同意义上的对象

关键一点: 不管是 DOM方式 还是 节点方式 获取的标签对象,内容可能不同,形式是完全一致的
DOM方式 获取的标签对象,支持节点操作
节点方式 获取的节点对象,支持DOM操作
只要正确的获取对象,之后想怎么操作,怎么操作

2. 节点操作之获取节点对象

获取DOM节点
childNodes:获取某一个节点下 所有的子一级节点
children :获取某一节点下所有的子一级 元素节点
firstChild:获取某一节点下子一级的 第一个节点
lastChild:获取某一节点下子一级的 最后一个节点
firstElementChild:获取某一节点下子一级 第一个元素节点
lastElementChild:获取某一节点下子一级 最后一个元素节点
nextSibling:获取某一个节点的 下一个兄弟节点
previousSibling:获取某一个节点的 上一个兄弟节点
nextElementSibling:获取某一个节点的 下一个元素节点
previousElementSibling:获取某一个节点的 上一个元素节点
parentNode:获取某一个节点的 父节点
attributes:获取某一个 元素节点 的所有 属性节点
节点属性
nodeType:获取节点的节点类型,用数字表示
元素节点:1 属性节点:2 文本节点:3 注释节点:8
nodeName:获取节点的节点名称
元素节点:标签名称 属性节点:属性名 文本节点:#text 注释节点:#comment
nodeValue:获取节点的值
元素节点:null 属性节点:属性值 文本节点:内容 注释节点:内容
操作DOM节点
document.createElement()创建一个元素节点
box.appendChild(node)把node节点插入到box的内部最后的位置
box.insertBefore(newNode, existNode)在box内,把newNode节点插入到exsitNode的前面
box.removeChild(node)删除box内部的子节点
obj.cloneNode()克隆obj节点,可以传一个布尔值为参数,如果参数为true,连同obj子元素一起克隆。

获取节点对象的方法
var oDiv = document.querySelector(‘div’);

  1. 获取当前标签中所有的子级节点
    执行结果,是一个伪数组,可以forEach()
    形式是与 querySelectorAll() 获取的伪数组是一样的
    console.log( oDiv.childNodes );
  2. 获取当前标签中,所有的元素节点/标签节点
    执行结果,是一个伪数组,不能forEach()
    console.log( oDiv.children );
  3. 获取当前标签中,第一个节点
    执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
    console.dir( oDiv.firstChild );
  4. 获取当前标签中,最后一个节点
    执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
    console.dir( oDiv.lastChild );
    console.dir( document.querySelector(‘span’) );
  5. 获取当前标签中,第一个标签节点,其他节点不会获取
    console.log( oDiv.firstElementChild );
  6. 获取当前标签中,最后一个标签节点,其他节点不会获取
    console.log( oDiv.lastElementChild );
  7. 获取当前标签,上一个兄弟节点(找哥哥)
    如果没有执行结果是null
    console.log( oDiv.previousSibling );
  8. 获取当前标签,下一个兄弟节点(找弟弟)
    如果没有执行结果是null
    console.log( oDiv.nextSibling );
  9. 获取当前标签,上一个兄弟元素节点(找标签哥哥)
    console.log( oDiv.previousElementSibling );
  10. 获取当前标签,下一个兄弟元素节点(找标签弟弟)
    console.log( oDiv.nextElementSibling );
  11. 获取当前标签,父级节点
    只获取直接父级节点
    console.log( oDiv.parentNode );
    console.log( document.querySelector(‘span’).parentNode );
  12. 获取当前标签,所有属性节点
    执行结果,是一个伪数组,不能forEach()
    console.log( oDiv.attributes );
    在这里插入图片描述
    <!-- 我是注释1 -->
    
    <div name="div" index="1" href="aaa" checked>我是标签div

        <!-- 我是注释2 -->
        
        <span>我是标签span</span>
    
    </div>

    <!-- 我是注释3 -->
    <p>我是标签p</p>

    <script>
        // 获取节点对象的方法

        var oDiv = document.querySelector('div');

        // 1,获取当前标签中所有的子级节点
        // 执行结果,是一个伪数组,可以forEach()
        // 形式是与 querySelectorAll() 获取的伪数组是一样的
        console.log( oDiv.childNodes );//NodeList(5) [ #text, <!--  我是注释2  -->, #text, span, #text ]

        // 2,获取当前标签中,所有的元素节点/标签节点
        // 执行结果,是一个伪数组,不能forEach()
        console.log( oDiv.children );//HTMLCollection { 0: span, length: 1 }

        // 3,获取当前标签中,第一个节点
        // 执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
        console.dir( oDiv.firstChild );//#text "我是标签div         "

        // 4,获取当前标签中,最后一个节点
        // 执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
         console.dir( oDiv.lastChild );//#text "      "
         console.dir( document.querySelector('span') );//<span>

        // 5,获取当前标签中,第一个标签节点,其他节点不会获取
         console.log( oDiv.firstElementChild );//<span>

        // 6,获取当前标签中,最后一个标签节点,其他节点不会获取
         console.log( oDiv.lastElementChild );//<span>

        // 7,获取当前标签,上一个兄弟节点(找哥哥)
        // 如果没有执行结果是null
         console.log( oDiv.previousSibling );//#text " "

        // 8,获取当前标签,下一个兄弟节点(找弟弟)
        // 如果没有执行结果是null
         console.log( oDiv.nextSibling );//#text " "

        // 9,获取当前标签,上一个兄弟元素节点(找标签哥哥)
        console.log( oDiv.previousElementSibling );//null

        // 10,获取当前标签,下一个兄弟元素节点(找标签弟弟)
         console.log( oDiv.nextElementSibling );//<p>

        // 11,获取当前标签,父级节点
        // 只获取直接父级节点
       console.log( oDiv.parentNode );//<body>
       console.log( document.querySelector('span').parentNode );//<div name="div" index="1" href="aaa" checked="">

        // 12,获取当前标签,所有属性节点
        // 执行结果,是一个伪数组,不能forEach()
      console.log( oDiv.attributes );//NamedNodeMap(4) [ name="div", index="1", href="aaa", checked="" ]

总结

  1. 通过节点操作获取的对象/伪数组与通过 DOM操作的对象/伪数组,形式上是一致的
    可以相互操作,DOM方法可以操作 节点对象
    节点方法可以操作 DOM对象
  2. 执行结果,伪数组/对象
    伪数组有的可以forEach, 有的不能forEach

3. 节点操作之类型名称内容

节点的类型,名称,内容
节点的类型:对象.nodeType 属性中存储,数据是 一个数值
元素节点/标签节点 :1
属性节点 :2
文本节点 :3
注释节点 :8
节点的名称:对象.nodeName
元素节点/标签节点 :大写字母的 标签名称
属性节点 :小写字母的 属性名称
文本节点 :#text
注释节点 :#comment
节点的内容:对象.nodeValue
元素节点/标签节点 :null
属性节点 :属性的属性值
文本节点 :文本内容,包括换行和空格
注释节点 :注释内容,包括换行和空格

4. 节点的操作

  1. 节点的操作
    节点的 新增 删除 克隆 写入
    (1) 删除节点 删除当前标签中的子级节点
    当前标签.removeChild(‘你要删除的节点’)
    (2) 克隆节点 克隆复制当前节点对象
    只克隆标签本身 当前标签.cloneNode();
    克隆标签以及标签内容 当前标签.cloneNode(true);
    (3)写入节点
    当前标签.appendChild(你要写入的标签对象) 在当前标签结束位置写入
    当前标签.insertBefore(你要写入的标签对象 , 在哪个子级标签前) 在当前标签,子级标签之前,写入 一个标签对象,只会出现在最后一次写入的位置
    相对对于将一个标签对象,多次写入,从上一个位置,会移动到下一个位置
    只会出现在最后一个位置
    var d = document.querySelector(‘div’);
    d.appendChild(oText);
    d.insertBefore(oDiv , d.firstChild);
    d.appendChild(oDiv);

  2. 节点的创建
    创建标签节点: document.createElement(‘标签名称’);
    创建的是一个标签对象
    之前是设定字符串,写入HTML文件,浏览器执行为标签效果

创建文本节点: document.createTextNode(‘要创建的文本内容’);

现在创建的是一个对象,要操作标签的内容,属性属性值等,必须要通过对象的方法来设定
var oDiv = document.createElement(‘div’);
使用操作对象的方式,给标签添加设定
oDiv.id = ‘div1’;

setAttribute,来设定自定义属性
oDiv.setAttribute(‘index’ , 1);
console.dir(oDiv); //

var oText = document.createTextNode(‘要创建的文本内容’);
console.log(oText); //#text “要创建的文本内容”

5.正则表达式

什么是正则表达式:
对字符串内容,进行格式和内容的验证
对于正则表达式,我们不用自己去写,所有常用的正则表达式,在网上都可以搜到;我们只需要能看懂,会使用;所有的计算机语言,正则表达式,都是相同的,通用.

正则表达式的基本语法
  1. 字面量(常用)
    使用 // 来包裹表达式内容
    var 变量 = /正则表达式/
  2. 构造函数
    var 变量 = RegExt(‘正则表达式’);

正则表达式的使用方法

  1. 验证
    判断字符串内容是否符合正则表达式的规范
    执行结果是 布尔类型
    语法 : 正则表达式.test(‘字符串内容’);
  2. 捕获
    捕获获取字符串中符合正则表达式规范的内容
    执行结果是捕获获取到的符合规范的字符串内容
    语法 : 正则表达式.exec(‘字符串内容’)

6. 正则表达式的常用语法

正则表达式,常用语法规范
正则表达式中,不要随便写空格,也会作为验证格式的一部分
元字符
使用一些符号,来表示规范

元字符
\d表示数值,数字,
\D表示非数字,
\w表示数字,字母,下划线
\W表示非数字,字母,下划线
\s表示空格
\S表示非空格
.表示非换行(字符串中的换行,使用 转义符 \n 表示)

提示
正则表达式和转义符,都是 \内容的形式 ; JavaScript会自动识别,如果是 \内容 符合正则表达式,就按照正则表达式来执行 ; 符合转义符,就按照转义符的形式执行 ; 正则表达式和转义符不会冲突

   // 只要有数字即可,不用都是数字
    var reg1 = /\d/ ; 
      console.log(reg1.test('123456')) ;	//true
      console.log(reg1.test('abcd')) ;	//false
      console.log(reg1.test('1234abcd')) ;	//true 

    var reg2 = /\D/; 
      console.log(reg2.test('123456')) ;	//false
      console.log(reg2.test('abcd')) ;	//true
      console.log(reg2.test('1234abcd')) ;	//true

    var reg3 = /\w/; 
      console.log( reg3.test('123avbc_') );	//true
      console.log( reg3.test('!@#$%^') );	//false
      console.log( reg3.test('1234!@#$%^') );	//true

    var reg4 = /\W/; 
      console.log( reg4.test('123avbc_') );	//false
      console.log( reg4.test('!@#$%^') );	//true
      console.log( reg4.test('1234!@#$%^') );	//true 
    
    var reg5 = /\s/;
      console.log( reg5.test('      ') );	//true
      console.log( reg5.test('312斤kfjisa') );	//false
      console.log( reg5.test('312斤 kfjisa') );	//true

    var reg6 = /\S/;
      console.log( reg6.test('      ') );	//false
      console.log( reg6.test('312斤kfjisa') );	//true
      console.log( reg6.test('312斤 kfjisa') );	//true


    var reg7 = /./; 
    console.log( reg7.test('\n') );	//true

7.限定符号 限定符号

边界符
^ 表示开头
$ 表示结尾

   以数字开头即可,之后的内容,不做限定 
 var reg1 = /^\d/; 
         console.log(reg1.test('123'));	//true
         console.log(reg1.test('123abc'));	//true
         console.log(reg1.test('abc123'));	//false

         //以数字结尾,就看结尾,之前有什么内容不管
        var reg2 = /\d$/; 
          console.log(reg2.test('123'));	//true
          console.log(reg2.test('123abc'));	//false
          console.log(reg2.test('abc123'));	//true

        // 如果开头结尾都加上了,限定效果就不同了
        // 只能有一个字符串,并且这个字符是数字   只能有一个数字字符
        // 字符个数,内容,不符合都不行
        var reg3 = /^\d$/;
          console.log(reg3.test('1'));	//true
          console.log(reg3.test('-1'));	//false
          console.log(reg3.test('a'));	//false
          console.log(reg3.test('123'));	//false
          console.log(reg3.test('123abc'));	//false
          console.log(reg3.test('abc123'));	//false
          console.log(reg3.test('123abc123')); 	//false

限定符 限定出现次数
一般都要和边界符配合使用,否则执行效果有问题

*表示允许的次数是 0 至 正无穷次 有没有都行
+表示允许的次数是 1 至 正无穷次 至少有一个
?表示允许的次数是 0 至 1 最多有一次
{n}表示允许的次数是 n 次 n的数值,是自定义数值
{n,}表示允许的次数是 n 次以上,包括n次 最少是n次,多个不管;也就是 n 至 正无穷 次
{n,m}表示允许的次数是 n 至 m 次 包括n和m
        // 只能是数字字符,字符个数没有要求
        var reg4 = /^\d*$/;
          console.log( reg4.test('1') );	//true
          console.log( reg4.test('') );	//true
          console.log( reg4.test('123') );	//true
          console.log( reg4.test('123abc') );  //false
          console.log( reg4.test('123abc123') );  //false

         // 必须是数字字符,至少出现1个数字字符
          var reg5 = /^\d+$/;   
          console.log( reg5.test('1') );	//true
          console.log( reg5.test('') );  //false
          console.log( reg5.test('123') );	//true
          console.log( reg5.test('123abc') );  //false
          console.log( reg5.test('123abc123') );  //false

        // 必须是数字字符,最多只能有0个或者1个字符
        var reg6 = /^\d?$/;
          console.log( reg6.test('1') );	//true
          console.log( reg6.test('') );	//true
          console.log( reg6.test('123') );  //false
          console.log( reg6.test('123abc') );  //false
          console.log( reg6.test('123abc123') );  //false

        // 只能是3个数字字符
        var reg7 = /^\d{3}$/;
          console.log( reg7.test('1') );  //false
          console.log( reg7.test('') );  //false
          console.log( reg7.test('123') );	//true
          console.log( reg7.test('123abc') );  //false
          console.log( reg7.test('123abc123') );	//false

         // 必须都是数字字符,并且至少有一个数字字符
        var reg8 = /^\d{1,}$/;
          console.log( reg8.test('1') );	//true
          console.log( reg8.test('') );	//false
          console.log( reg8.test('123') );	//true
          console.log( reg8.test('123abc') );	//false
          console.log( reg8.test('123abc123') );	//false

        // 都是数字,1至3次
        var reg9 = /^\d{1,3}$/;
          console.log( reg9.test('1') );	//true
          console.log( reg9.test('') );	//false
          console.log( reg9.test('123') );	//true
          console.log( reg9.test('123abc') );	//false
          console.log( reg9.test('123abc123') );	//false

8.正则表达式之特殊符号

正则表达式的特殊符号

  1. \ 可以表示正则表达式的规范,或者是转义符
    设定是不冲突的,符合哪个就执行哪个
  2. | 表示逻辑或的关系
    表示两个规范,满足哪个都可以
    如果要表示多种内容,并且限定字符个数
    公式 : (内容1|内容2|内容3…){次数限定}
  3. ( ) 将( )中的内容作为一个整体,来执行,确保执行正确
  4. [ ] 在[ ]中设定的内容,任意满足其中一个就可以 abcd
  5. - 表示在这个范围内的就可以 a-d
  6. [^内容] 表示 非内容
  7. i 忽略大小写
    g 全局匹配

    必须写在 / / 之外 /正则表达式/i /正则表达式/g
    一般是与其他的函数配合使用

逻辑或的判定

  1. 内容的判断,正常的判断
  2. 个数的判断,只要是包含个数就可以
 //内容,可以是数字,字母,下划线,字符只要是3个就行,不能少,可以多
// 实际上是一种错误的语法形式
        // var  reg1 = /^\d{3}|\w{3}$/;

        // 数字或者数字字符下划线,并且个数只能是三个
        // var  reg1 = /^(\d|\w){3}$/;

        // 也可以
        var reg1 = /^\d{3}$|^\w{3}$/; 
          console.log( reg1.test( '123' ) );		//true
          console.log( reg1.test( 'abc' ) );		//true
          console.log( reg1.test( '1234' ) );	//false
          console.log( reg1.test( 'abcd' ) );	//false
          console.log( reg1.test( '1!1' ) );	//false
          console.log( reg1.test( 'a&b' ) );	//false
          console.log( reg1.test( 'ab' ) );	//false
          console.log( reg1.test( '12' ) );	//false
          console.log( reg1.test( '12&12' ) );	//false
          console.log( reg1.test( 'ab&ab' ) );	//false

        // 内容只能是 a b c d 4个字符,多了不可以
        var reg2 = /^[abcd]$/; 
          console.log( reg2.test('a') );		//true
          console.log( reg2.test('b') );		//true
          console.log( reg2.test('c') );		//true
          console.log( reg2.test('d') );		//true
          console.log( reg2.test('ab') );	//false
          console.log( reg2.test('abc') );	//false
          console.log( reg2.test('abcd') );	//false
          console.log( reg2.test('bc') );	//false
          console.log( reg2.test('bcd') );	//false
          console.log( reg2.test('cd') );	//false

        // a-d之间的字符,只能是一个
        var reg3 = /^[a-d]$/; 
          console.log( reg3.test('a') );		//true
          console.log( reg3.test('b') );		//true
          console.log( reg3.test('c') );		//true
          console.log( reg3.test('d') );		//true
          console.log( reg3.test('ab') );	//false
          console.log( reg3.test('abc') );	//false
          console.log( reg3.test('abcd') );	//false
          console.log( reg3.test('bc') );	//false
          console.log( reg3.test('bcd') );	//false
          console.log( reg3.test('cd') );	//false

        //  字符范围不再 a-d 之间,并且是一个字符
        var reg4 = /^[^(a-d)]$/; 
        console.log( reg4.test('a') );	//false
        console.log( reg4.test('b') );	//false
        console.log( reg4.test('c') );	//false
        console.log( reg4.test('d') );	//false
        console.log( reg4.test('ab') );	//false
        console.log( reg4.test('abc') );	//false
        console.log( reg4.test('abcd') );	//false
        console.log( reg4.test('bc') );	//false
        console.log( reg4.test('bcd') );	//false
        console.log( reg4.test('cd') );	//false
        console.log( reg4.test('z') );	//true

9.正则表达式之其他配合函数

  1. search()
    字符串查找函数,在字符串中,查找是否有符合的内容,如果有,返回下标,没有返回-1
    返回的是第一个符合内容的索引下标
    indexOf() 也是查找,也返回索引下标,但是不支持正则表达式

     var str1 = 'abcdefgab';
     // 默认是区分大小写的
     console.log( str1.search('ab') );	//0
     console.log( str1.search('B') );	//-1
     // 正则表达式,不区分大小写
      console.log( str1.search(/B/i) );	//1
    
     console.log( str1.indexOf('b') );	//1
     // indexOf() 不支持正则表达式
     console.log( str1.indexOf(/B/i) );	//-1
    
  2. match()
    找到符合规范的字符串,并且返回内容
    默认只会执行一次,并且返回第一次符合规范的内容

     var str2 = 'abcdefgabcdefg'; 
     var arr1 = str2.match('ab');
     // 正则表达式,匹配全局
     var arr2 = str2.match(/ab/g);
    
     console.log(arr1);	// Array [ "ab" ]
     console.log(arr2);	// Array [ "ab", "ab" ]
    
  3. replace()
    字符串替换,默认只替换第一个符合的内容

     var str3 = 'abcd曹abcd曹abcd曹abcd'; 
     // 默认值替换第一个
     // str3 = str3.replace('曹' , '*'); 
     // 正则表达式,替换全局
     str3 = str3.replace( /曹/g , '*'); 
     console.log(str3);	//abcd*abcd*abcd*abcd
    

10.获取元素的非行间样式

我们在操作 DOM 的时候,很重要的一点就是要操作元素的 css 样式
那么在操作 css 样式的时候,我们避免不了就要获取元素的样式
之前我们说过可以用 元素.style.xxx 来获取
但是这个方法只能获取到元素 行间样式,也就是写在行内的样式 不管是外链式还是内嵌式,我们都获取不到该元素的样式
这里我们就要使用方法来获取了 getComputedStyle 和 currentStyle
这两个方法的作用是一样的,只不过一个在 非 IE 浏览器,一个在 IE 浏览器

11.获取元素的偏移量等属性词

offsetLeft 和 offsetTop
获取的是元左边的偏移量和上边的偏移量
分成两个情况来看

  • 没有定位的情况下
    获取元素边框外侧到页面内侧的距离
  • 有定位的情况下
    获取元素边框外侧到定位父级边框内侧的距离(其实就是我们写的 left 和 top 值)

offsetWidth 和 offsetHeight

  • 获取元素 内容宽高 + padding宽高 + border宽高 的和

12.认识ECMA6语法

我们所说的 ES5 和 ES6 其实就是在 js 语法的发展过程中的一个版本而已。
比如我们使用的微信
<1>最早的版本是没有支付功能的
<2>随着时间的流逝,后来出现了一个版本,这个版本里面有支付功能了ECMAScript 就是 js 的语法
<1>以前的版本没有某些功能
<2>在 ES5 这个版本的时候增加了一些功能
<3>在 ES6/ECMA2015 这个版本的时候增加了一些功能(ES6是2015年颁布)
因为浏览器是浏览器厂商生产的
<1>ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能。
<2>这个过程是需要时间的。
<3>所以到现在,基本上大部分浏览器都可以比较完善的支持了。
<4>只不过有些浏览器还是不能全部支持。
<5>这就出现了兼容性问题。
<6>所以我们写代码的时候就要考虑哪些方法是 ES5 或者 ES6 的,看看是不是浏览器都支持。
网址:http://www.ecma-internation

之前声明变量 使用 var 关键字
ECMA6新增关键字 let 声明变量

let和const关键字和var的区别
  1. let 和 const 不允许重复声明变量
    在这里插入图片描述
  2. let 和 const 声明的变量不会在预解析的时候解析,也就是没有声明提升.
    在这里插入图片描述
  3. let 和 const 声明的变量会被所有代码块限制作用范围
    在这里插入图片描述
let和const的区别
  1. let 声明的变量的值可以改变,const 声明的变量的值不可以改变
    在这里插入图片描述
  2. let 声明的时候可以不赋值,const 声明的时候必须赋值
    在这里插入图片描述
箭头函数

箭头函数是 ES6 里面一个简写函数的语法方式
语法: (函数的行参) => { 函数体内要执行的代码 }
【注】小技巧:适当省略function 和 return关键字。
箭头函数只能简写函数表达式,不能简写声明式函数
在这里插入图片描述
语法: (函数的行参) => { 函数体内要执行的代码 }
在这里插入图片描述
在这里插入图片描述
箭头函数—箭头函数的特殊性

  1. 箭头函数内部没有 this,箭头函数的 this 是上一层上下文的
    在这里插入图片描述
  2. 箭头函数内部没有 arguments 这个参数集合
    在这里插入图片描述
  3. 函数的行参只有一个的时候可以不写 () 其余情况必须写
    在这里插入图片描述
  4. 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值