Jquery使用技巧与规范

 

1.   jquery 简介

1.1. 概述

随着 WEB2.0ajax 思想在互联网上的快速发展传播,陆续出现了一些优秀的 Js 框架,其中比较著名的有 PrototypeYUIjQuerymootoolsBindows 以及国内的 JSVM 框架等,通过将这些 JS 框架应用到我们的项目中能够使程序员从设计和书写繁杂的 JS 应用中解脱出来,将关注点转向功能需求而非实现细节上,从而提高项目的开发速度。

jQuery 是继 prototype 之后的又一个优秀的 Javascript 框架。它是由 John Resig 2006 年初创建的,它有助于简化 JavaScript? 以及 Ajax 编程。有人使用这样的一比喻来比较 prototypejQueryprototype 就像 Java ,而 jQuery 就像 ruby. 它是一个简洁快速灵活的 JavaScript 框架,它能让你在你的网页上简单的操作文档、处理事件、实现特效并为 Web 页面添加 Ajax 交互。

2.   jQuery 常用技巧

2.1. 关于页面元素的引用

通过 jquery$() 引用元素包括通过 idclass 、元素名以及元素的层级关系及 dom 或者 xpath 条件等方法,且返回的对象为 jquery 对象 ( 集合对象 ) ,不能直接调用 dom 定义的方法。

2.2. jQuery 对象与 dom 对象的转换

只有 jquery 对象才能使用 jquery 定义的方法。注意 dom 对象和 jquery 对象是有区别的,调用方法时要注意操作的是 dom 对象还是 jquery 对象。

普通的 dom 对象一般可以通过 $() 转换成 jquery 对象。

如: $(document.getElementById(msg)) 则为 jquery 对象,可以使用 jquery 的方法。

由于 jquery 对象本身是一个集合。所以如果 jquery 对象要转换为 dom 对象则必须取出其中的某一项,一般可通过索引取出。

如: $(#msg)[0]$(div).eq(1)[0]$(div).get()[1]$(td)[5] 这些都是 dom 对象,可以使用 dom 中的方法,但不能再使用 Jquery 的方法。

以下几种写法都是正确的:

$(”#msg”).html();

$(”#msg”)[0].innerHTML;

$(”#msg”).eq(0)[0].innerHTML;

$(”#msg”).get(0).innerHTML;

2.3. 如何获取 jQuery 集合的某一项

 

对于获取的元素集合,获取其中的某一项 ( 通过索引指定 ) 可以使用 eqget(n) 方法或者索引号获取,要注意, eq 返回的是 jquery 对象,而 get(n) 和索引返回的是 dom 元素对象。对于 jquery 对象只能使用 jquery 的方法,而 dom 对象只能使用 dom 的方法,如要获取第三个 <div> 元素的内容。有如下两种方法:

 

$(div).eq(2).html();// 调用 jquery 对象的方法

$(div).get(2).innerHTML;// 调用 dom 的方法属性

2.4. 同一函数实现 set get

 

jQuery 中的很多方法都是如此,主要包括如下几个:

 

$(#msg).html();// 返回 idmsg 的元素节点的 html 内容。

$(”#msg”).html(”<b>new content</b>”);

// 将“ <b>new content</b> ” 作为 html 串写入 idmsg 的元素节点内容中 , 页面显示粗体的 new content

 

$(#msg).text();// 返回 idmsg 的元素节点的文本内容。

$(”#msg”).text(”<b>new content</b>”);

// 将“ <b>new content</b> ” 作为普通文本串写入 idmsg 的元素节点内容中 , 页面显示 <b>new content</b>

 

$(#msg).height();// 返回 idmsg 的元素的高度

$(#msg).height(300);//idmsg 的元素的高度设为 300

$(#msg).width();// 返回 idmsg 的元素的宽度

$(#msg).width(300);//idmsg 的元素的宽度设为 300

 

$(input).val();// 返回表单输入框的 value

$(input).val(test);// 将表单输入框的 value 值设为 test

 

$(#msg).click();// 触发 idmsg 的元素的单击事件

$(#msg).click(fn);//idmsg 的元素单击事件添加函数

同样 blur,focus,select,submit 事件都可以有着两种调用方法。

 

2.5. 集合处理功能

对于 jquery 返回的集合内容无需我们自己循环遍历并对每个对象分别做处理, jquery 已经为我们提供的很方便的方法进行集合的处理。

包括两种形式:

 

$(”p”).each(function(i){this.style.color=['#f00','#0f0','#00f'][ i ]})

// 为索引分别为 012p 元素分别设定不同的字体颜色。

 

$(”tr”).each(function(i){this.style.backgroundColor=['#ccc','#fff'][i%2]})

// 实现表格的隔行换色效果

 

$(”p”).click(function(){alert($(this).html())})

// 为每个 p 元素增加了 click 事件,单击某个 p 元素则弹出其内容

2.6. 扩展我们需要的功能

 

 

$.extend({

min:function(a, b){return a< b?a:b; },

max:function(a, b){return a> b?a:b; }

});//jquery 扩展了 min,max 两个方法

使用扩展的方法 ( 通过“ $. 方法名”调用 )

 

 

alert(”a=10,b=20,max=”+$.max(10,20)+”,min=”+$.min(10,20));

2.7. 支持方法的连写

 

所谓连写,即可以对一个 jquery 对象连续调用各种不同的方法。例如:

 

$(”p”).click(function(){alert($(this).html())})

.mouseover(function(){alert(’mouse over event’)})

.each(function(i){this.style.color=['#f00','#0f0','#00f'][ i ]});

2.8. 操作元素的样式

 

主要包括以下几种方式:

 

$(#msg).css(background);// 返回元素的背景颜色

$(#msg).css(background,#ccc)// 设定元素背景为灰色

$(#msg).height(300); $(#msg).width(200);// 设定宽高

$(#msg).css({ color: red, background: blue });// 以名值对的形式设定样式

$(#msg).addClass(select);// 为元素增加名称为 selectclass

$(#msg).removeClass(select);// 删除元素名称为 selectclass

$(#msg).toggleClass(select);// 如果存在 ( 不存在 ) 就删除 ( 添加 ) 名称为 selectclass

2.9. 完善的事件处理功能

 

jQuery 已经为我们提供了各种事件处理方法,我们无需在 html 元素上直接写事件,而可以直接为通过 jquery 获取的对象添加事件。

 

$(#msg).click(function(){alert(good)})// 为元素添加了单击事件

$(”p”).click(function(i){this.style.color=['#f00','#0f0','#00f'][ i ]})

// 为三个不同的 p 元素单击事件分别设定不同的处理

jQuery 中几个自定义的事件:

 

(1)hover(fn1,fn2) :一个模仿悬停事件 ( 鼠标移动到一个对象上面及移出这个对象 ) 的方法。

当鼠标移动到一个匹配的元素上面时,会触发指定的第一个函数。当鼠标移出这个元素时,会触发指定的第二个函数。

// 当鼠标放在表格的某行上时将 class 置为 over ,离开时置为 out

$(”tr”).hover(function(){

$(this).addClass(”over”);

},

function(){

$(this).addClass(”out”);

});

(2)ready(fn):DOM 载入就绪可以查询及操纵时绑定一个要执行的函数。

 

 

$(document).ready(function(){alert(”Load Success”)})

// 页面加载完毕提示“ Load Success, 相当于 onload 事件。与 $(fn) 等价

(3)toggle(evenFn,oddFn): 每次点击时切换要调用的函数。

如果点击了一个匹配的元素,则触发指定的第一个函数,当再次点击同一元素时,则触发指定的第二个函数。随后的每次点击都重复对这两个函数的轮番调用。

 

 

// 每次点击时轮换添加和删除名为 selectedclass

$(”p”).toggle(function(){

$(this).addClass(”selected”);

},function(){

$(this).removeClass(”selected”);

});

(4)trigger(eventtype): 在每一个匹配的元素上触发某类事件。

例如:

 

 

$(p).trigger(click);// 触发所有 p 元素的 click 事件

(5)bind(eventtype,fn)unbind(eventtype): 事件的绑定与反绑定

从每一个匹配的元素中 ( 添加 ) 删除绑定的事件。例如:

 

 

$(p).bind(click,function(){alert($(this).text());});// 为每个 p 元素添加单击事件

$(p).unbind();// 删除所有 p 元素上的所有事件

$(p).unbind(click)// 删除所有 p 元素上的单击事件

2.10.   几个实用特效功能

 

其中 toggle()slidetoggle() 方法提供了状态切换功能。

toggle() 方法包括了 hide()show() 方法。

slideToggle() 方法包括了 slideDown()slideUp 方法。

2.11.   几个有用的 jQuery 方法

$.browser. 浏览器类型:检测浏览器类型。有效参数: safari, opera, msie, mozilla 。如检测是否 ie$.browser.isie ,是 ie 浏览器则返回 true

$.each(obj, fn) :通用的迭代函数。可用于近似地迭代对象和数组 ( 代替循环 ) 。如

 

$.each( [0,1,2],function(i, n){ alert( “Item #”+ i+ “: ”+ n ); });

等价于:

 

 

var tempArr=[0,1,2];

for(var i=0;i<tempArr.length;i++){

alert(”Item #”+i+”: “+tempArr[ i ]);

}

也可以处理 json 数据,如

 

 

$.each( { name: “John”, lang: “JS” },function(i, n){ alert( “Name: ”+ i+ “, Value: ”

  + n ); });

结果为:

 

 

Name:name, Value:John

Name:lang, Value:JS

$.extend(target,prop1,propN) :用一个或多个其他对象来扩展一个对象,返回这个被扩展的对象。这是 jquery 实现的继承方式

如:

代码

$.extend(settings, options);

// 合并 settingsoptions ,并将合并结果返回 settings 中,相当于 options 继承 setting 并将继承结果保存在

setting 中。

var settings= $.extend({}, defaults, options);

// 合并 defaultsoptions ,并将合并结果返回到 setting 中而不覆盖 default 内容。

可以有多个参数 ( 合并多项并返回 )

 

 

$.map(array, fn) :数组映射。把一个数组中的项目 ( 处理转换后 ) 保存到到另一个新数组中,并返回生成的新数组。

如:

 

 

var tempArr=$.map( [0,1,2],function(i){return i+ 4; });

tempArr 内容为: [4,5,6]

var tempArr=$.map( [0,1,2],function(i){return i> 0 ? i+ 1 :null; });

tempArr 内容为: [2,3]

$.merge(arr1,arr2): 合并两个数组并删除其中重复的项目。

如: $.merge( [0,1,2], [2,3,4] ) // 返回 [0,1,2,3,4]

$.trim(str) :删除字符串两端的空白字符。

如: $.trim(   hello, how are you? ); // 返回” hello,how are you?

2.12.   解决自定义方法或其他类库与 jQuery 的冲突

 

很多时候我们自己定义了 $(id) 方法来获取一个元素,或者其他的一些 js 类库如 prototype 也都定义了 $ 方法,如果同时把这些内容放在一起就会引起变量方法定义冲突, Jquery 对此专门提供了方法用于解决此问题。

使用 jquery 中的 jQuery.noConflict(); 方法即可把变量 $ 的控制权让渡给第一个实现它的那个库或之前自定义的 $ 方法。之后应用 Jquery 的时候只要将所有的 $ 换成 jQuery 即可,如原来引用对象方法 $(#msg) 改为 jQuery(#msg)

如:

 

jQuery.noConflict();

// 开始使用 jQuery

jQuery(”div p”).hide();

// 使用其他库的 $()

$(”content”).style.display= ‘none’;

 

2.13.   测试 jQuery 包装集是否包含某些元素

  如果你想测试一下某个 jQuery 包装集中是否包含某些元素,你首先可以尝试使用验证首个元素是否存在:

if($(selector)[0]){}

// 或者这样

if($(selector).length){}

来看看这个例子:

  // 例子 . 如果你的页面有以下 html 代码

<ulid="shopping_cart_items">

<li><inputclass="in_stock" name="item" type="radio" value="Item-X" />Item X</li>

<li><inputclass="unknown" name="item" type="radio" value="Item-Y" />Item Y</li>

<li><inputclass="in_stock" name="item" type="radio" value="Item-Z" />Item Z</li>

</ul>

<preescaped="true" lang="javascript">

// 这个 if 条件将返回 true ,因为我们有两个

// input 域匹配了选择器,所以 <statement> 代码将会执行

if($('#shopping_cart_items input.in_stock')[0]){<statement>}

2.14.   jquery.org 读取 jQuery 最新版本

  你可以使用这句代码读取 jQuery 的最新版本的代码文件。

<script src="http://code.jquery.com/jquery-latest.js"></script>

  你可以使用这个方法来调用最近版本的 jQuery 框架,当然,你还可以使用下面这个代码从 ajax.googleapis.com 调用同样的最新版本 jQuery

<scriptsrc="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"

type="text/javascript"></script>

2.15.   存储数据

  使用 data 方法可以避免在 DOM 中存储数据,有些前端开发 er 喜欢使用 HTML 的属性来存储数据:

$('selector').attr('alt','data being stored');

// 之后可以这样读取数据 :

$('selector').attr('alt');

  使用” alt ”属性来作为参数名存储数据其实对于 HTML 来说是不符合语义的,我们可以使用 jQuerydata 方法来为页面中的某个元素存储数据

$('selector').data(' 参数名 ',' 要存储的数据 ');

  // 之后这样取得数据 :

$('selector').data(' 参数 ');

  这个 data 方法能让你自己明明数据的参数,更语义更灵活,你可以在页面上的任何元素存储数据信息。如果想了解更多关于 data()removeData() 方法的介绍,可以看看 jQuery 官方讲解。

  这个方法的经典应用是给 input 域一个默认值,然后在聚焦的时候清空它 :

   HTML 部分 :

<formid="testform">

<inputtype="text" class="clear" value="Always cleared" />

<inputtype="text" class="clear once" value="Cleared only once" />

<inputtype="text" value="Normal text" />

</form>

   JavaSript 部分:

$(function() {

// 取出有 clear 类的 input

  //(: "clear once" 是两个 class clear once)

  $('#testform input.clear').each(function(){

// 使用 data 方法存储数据

  $(this).data("txt", $.trim($(this).val()) );

  }).focus(function(){

// 获得焦点时判断域内的值是否和默认值相同,如果相同则清空

  if ( $.trim($(this).val())=== $(this).data("txt") ) {

  $(this).val("");

  }

  }).blur(function(){

// 为有 class clear 的域添加 blur 时间来恢复默认值

  // 但如果 classonce 则忽略

  if ( $.trim($(this).val())=== "" && !$(this).hasClass("once") ) {

//Restore saved data

  $(this).val( $(this).data("txt") );

  }

  });

});

查看 Demo

2.16.   FireBug 控制台记录 jQuery

   FireBug 是我最喜欢用的一个浏览器扩展工具之一,这个工具可以让你快速的在可视化界面中了解当前页面的 HTML+CSS+JavaScript ,并在该工具下完成即时开发。作为 jQueryJavaScript 开发人员, FireFox 对于 记录你的 JavaScript 代码 也得到支持。

  写入 FireBug 控制台的最简单方式如下 :

 

console.log("hello world")

  你也可以按照你希望的方式写一些参数:

console.log(2,4,6,8,"foo",bar)

  你也可以编写一个小扩展来记录 jQuery 对象到控制台:

jQuery.fn.log= function(msg) {

console.log("%s: %o", msg,this);

return this;

};

  对于这个扩展,你可以直接使用 .log() 方法来记录当前对象到控制台。

$('#some_div').find('li.source > input:checkbox')

  .log("sources to uncheck")

  .removeAttr("checked");

2.17.   尽可能使用 ID 选择器

  在使用 jQuery 之后,你会发现利用 class 属性来选择 DOM 元素变得相当简单。尽管如此,还是推荐大家尽量少用 class 选择器取而代之尽量多使用运行更快的 ID 选择器 (IE 浏览器下使用 class 选择器会在遍历整个 DOM 树之后返回相符的 class 包装集 ) 。而 ID 选择器更快是因为 DOM 本身就有”天然的” getElementById 这个方法,而 class 并没有。所以如果使用 class 选择器的话,浏览器会遍历整个 DOM ,如果你的网页 DOM 结构足够复杂,这些 class 选择器足矣把页面拖得越来越慢。让我们看看这段简单的 HTML 代码 :

<divid="main">

<formmethod="post" action="/">

<h2>Selectors in jQuery</h2>

  ...

<inputclass="button" id="main_button" type="submit" value="Submit" />

</form>

</div>

 

 

  // 使用 class 来调用 submit 按钮要比使用绝对的 ID 选择器慢很多

var main_button= $('#main .button');

var main_button= $('#main_button');

2.18.   善于利用 jQuery

   jQuery 链不但允许以简洁的方式写出强大的操作,而且提高了开发效率,因为它能够把多个命令应用到包装集,而不必重新计算包装集。从而你不用再这样写了:

<li>Description:<inputtype="text" name="description" value="" /></li>

 

$('#shopping_cart_items input.text').css('border','3px dashed yellow');

$('#shopping_cart_items input.text').css('background-color','red');

$('#shopping_cart_items input.text').val("text updated");

  取而代之你可以使用 jQuery 链来完成简便的操作:

var input_text= $('#shopping_cart_items input.text');

input_text.css('border','3px dashed yellow');

input_text.css('background-color','red');

input_text.val("text updated");

 

//same with chaining:

var input_text= $('#shopping_cart_items input.text');

input_text

  .css('border','3px dashed yellow')

  .css('background-color','red')

  .val("text updated");

2.19.   绑定 jQuery 函数到 $(window).load 事件

  大多数 jQuery 实例或教程都告诉我们绑定我们的 jQuery 代码到 $(document).ready 事件。虽然 $(document).ready 事件在大多数情况下都 OK ,但是它的解析顺序是在文档准备就绪,单文档中的图片等对象正在下载的时候开始运行的。所以在某些时候使用 $(document).ready 事件并不一定能达到我们预期的效果,比如一些视觉效果和动画、拖拽、预读取隐藏图片等…通过使用 $(window).load 事件便可以安全的在整个文档都准备就绪之后再开始运行你期望的代码。

$(window).load(function(){

// 将你希望在页面完全就绪之后运行的代码放在这里

});

2.20.   使用 jQuery 链来限定选择器,让你的代码更简洁更优雅

  由于 JavaScript 支持链结构而且支持断行,所以你的代码可以写成下面这样,这个例子先在元素上移除一个 class 然后在同一个元素上添加另一个 class

$('#shopping_cart_items input.in_stock')

  .removeClass('in_stock')

  .addClass('3-5_days');

  如果想让它更简单实用,你可以创建一个支持链结构的 jQuery 函数:

$.fn.makeNotInStock= function() {

return $(this).removeClass('in_stock').addClass('3-5_days');

}

 

  $('#shopping_cart_items input.in_stock').makeNotInStock().log();

2.21.   使用回调函数同步效果

  如果你想确保某个事件或动画效果要在另一个事件运行之后再调用,那你就要使用回调函数了。你可以在这些动画效果后面绑定回调函数: slideDown( speed, [ 回调 ] ) ie. $(#sliding).slideDown(slow, function(){ … 点击这里预览这个例子。

<style>

  div.button{ background:#cfd; margin:3px; width:50px;

  text-align:center; float:left; cursor:pointer;

  border:2px outset black; font-weight:bolder; }

  #sliding{ display:none; }

</style>

 

$(document).ready(function(){

// 使用 jQueryclick 事件改变视觉效果,并开启滑动效果

  $("div.button").click(function () {

//div.button 现在看上去是按下的效果

  $(this).css({ borderStyle:"inset", cursor:"wait" });

//#sliding 现在将渐隐并在完成动作之后开启渐显效果

  //slideup once it completes

  $('#sliding').slideDown('slow',function(){

  $('#sliding').slideUp('slow',function(){

// 渐显效果完成后将会改变按钮的 CSS 属性

  $('div.button').css({ borderStyle:"outset", cursor:"auto" });

  });

  });

  });

});

2.22.   学会使用自定义选择器

   jQuery 允许我们在 css 选择器的基础上定义自定义选择器来让我们的代码更简洁 :

$.expr[':'].mycustomselector= function(element, index, meta, stack){

// element- DOM 元素

  // index - 堆栈中当前遍历的索引值

  // meta - 关于你的选择器的数据元

  // stack - 用于遍历所有元素的堆栈

 

// 包含当前元素则返回 true

  // 不包含当前元素则返回 false

};

 

// 自定义选择器的应用 :

$('.someClasses:test').doSomething();

  下面让我们来看看一个小例子,我们通过使用自定义选择器来锁定含有” rel ”属性的元素集:

$.expr[':'].withRel= function(element){

var $this = $(element);

// 仅返回 rel 属性不为空的元素

  return ($this.attr('rel')!= '');

};

 

  $(document).ready(function(){

// 自定义选择器的使用很简单,它和其他选择器一样,返回一个元素包装集

// 你可以为他使用格式方法,比如下面这样修改它的 css 样式

  $('a:withRel').css('background-color','green');

});

 

<ul>

<li>

<ahref="#">without rel</a>

</li>

<li>

<arel="somerel" href="#">with rel</a>

</li>

<li>

<arel="" href="#">without rel</a>

</li>

<li>

<arel="nofollow" href="#">a link with rel</a>

</li>

</ul>

2.23.   将你的代码测试完好

   jQuery 有一个名为 QUnit 单元测试框架。编写测试很容易,它能让您可以放心地修改您的代码,并确保它仍然按预期工作。下面是如何工作的:

// 将测试分成若干模块 .

module("Module B");

  test("some other test",function() {

// 指定多少个判断语句需要加入测试中 .

  expect(2);

  equals(true,false,"failing test" );

  equals(true,true,"passing test" );

});

 

 

3.   jQuery 编码规范  

jQuery 核心模块的编码规范 , 也遵循 javascript 的语言语法。

3.1. 空格

2.1.1 使用 tab 进行缩进

2.1.2 代码中多用点空格

         错误写法 :

         if(blah==="foo"){

           foo("bar","baz",{zoo:1});

         }       

         正确写法 :

         if ( blah   ===   "foo" ) {

           foo( "bar", "baz", {zoo: 1} );

         }

2.1.3 左花括号前面一定要有空格

2.1.4 行内不要使用 tab

var a = true,

           c = false, // yay

           b   = false; // grrr

2.1.5 空行不要有空格

2.1.6 行尾不要有空格

 

3.2. 等价判断

尽量使用严格的等价判断符      = = =   ,尽量不用 = =

3.3. 代码块

2.3.1 if/else/for/while/try 要使用花括号,且要换行。

2.3.2 代码块一定要用花括号括起来:

错误写法 :

if ( true )

   blah();

 

正确写法 :

if ( true ) {

   blah();

}

2.3.3 不要把语句和判断条件放在同一行:

错误写法 :

if ( true ) return;

if ( true ) blah();

正确写法 :

if ( true ) {

   return;

}

if ( true ) {

   blah();

}

2.3.4 else/else if/catch 要和花括号在同一行:

             if ( blah ) {

                         baz();

            } else {

                    baz2();

            }

例外: else if 的情况, else 就不要加花括号了:

} else if ( test ) {

  blah();

}

// 没必要:

} else {

  if ( test ) {

    blah();

  }

}

2.3.5 不要使用三元操作符取代 if/else 语句。

2.3.6 不要使用 object && object.method() 取代 if/else 语句,除非在条件判断中。

3.4. 函数调用

2.4.1 参数两边要加一个空格

         foo( true );

           foo( "blah" );

例外:如果已经在函数调用中的话,里面的函数调用可以不加空格:

       foo( bar(true) );

例外:函数,对象,数组字面量,如果是唯一参数的话,可以紧贴括号:

foo(function() { });

foo([   ]);

foo({   });

2.4.2 空函数调用不需要加空格: foo();

2.4.3 逗号和冒号后面一定要跟空格

3.5. 数组和对象

2.5.1 空对象和数组不需要填入空格: []{}

2.5.2 逗号和冒号后面一定要跟空格

3.6. 赋值

2.6.1 赋值语句一定要跟分号。

2.6.2 分号后面一定要换行。

3.7. 类型检查

Global Variables: typeof variable === "undefined"

Local Variables: variable === undefined

Properties: object.prop === undefined

3.8. 正则表达式

只准用 .test() .exec() 。不准用 "string".match()

3.9. 字符串

字符串一定要用双引号,不能用单引号。

3.10.   节点

2.10.1 使用 .nodeName 而非 .tagName

2.10.2 使用 .nodeType 来判断节点的类型(不要用 .nodeName )。

2.10.3 不要手动往节点上挂自定义的属性,一定要使用 .data()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值