第二章 jQuery技术解密 (二)

2.2.6 延续 -- 迭代器

在 jQuery 框架中,jQuery 对象是一个很奇怪的概念,具有多重身份,所以很多初学者一听说 jQuery 对象就感觉很是不解,误以为它是 John Resig 制造的新概念。我们可以对jQuery 对象进行如下分解。

第一,jQuery 对象是一个数据集合,它不是一个个体对象。因此,你无法直接使用 JavaScript 的方法来操作它。

第二,jQuery 对象实际上就是一个普通的对象,因为它是通过 new 运算符创建的一个新的实例对象。它可以继承原型方法或属性,同时也拥有 Object 类型的方法和属性。

第三,jQuery 对象包含数组特性,因为它赋值了数组元素,以数组结构存储返回的数据。我们可以以 JavaScript 的概念理解 jQuery 对象,例如下面的示例。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. varjquery={//定义对象直接量
  3. name:"jQuery",//以属性方式存储信息
  4. value:"1.3.2"
  5. };
  6. jquery[0]="jQuery";//以数组方式存储信息
  7. jquery[1]="1.3.2";
  8. alert(jquery.name);//返回"jQuery"
  9. alert(jquery[0]);//返回"jQuery"
  10. </script>

上面的 jQuery 对象就是一个典型的 jQuery 对象,jQuery 对象的结构就是按这种形式设计的。可以说,jQuery
对象就是对象和数组的混合体,但是它不拥有数组的方法,因为它的数组结构是人为附加的,也就是说它不是 Array 类型数据,而是 Object 类型数据。

第四,jQuery 对象包含的数据都是 DOM 元素,是通过数组形式存储的,即通过 jQuery[n] 形式获取。同时 jQuery 对象又定义了几个模仿 Array 基本特性的属性,如 length 等。

所以,jQuery 对象是不允许直接操作的,只有分别读取它包含的每一个 DOM 元素,才能实现各种操作,如插入、删除、嵌套、赋值和读写 DOM 元素属性等。

那么如何实现直接操作 jQuery 对象中的 DOM 元素呢?

在实际应用中,我们可以看到类似下面的 jQuery 用法。

$("div").html()

也就是直接在 jQuery 对象上调用 html(),并实现操作 jQuery 包含的所有 DOM 元素。那么这个功能是怎么实现的呢?

jQuery 定义了一个工具函数 each(),利用这个工具可以遍历 jQuery 对象中所有的 DOM 元素,并把需要操作的内容封装到一个回调函数中,然后通过在每个 DOM 元素上调用这个回调函数即可。实现代码如下所示,演示效果如图 2.2 所示。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. var$=jQuery=function(selector,context){//定义类
  3. returnnewjQuery.fn.init(selector,context);//返回选择器的实例
  4. };
  5. jQuery.fn=jQuery.prototype={//jQuery类的原型对象
  6. init:function(selector,context){//定义选择器构造器
  7. selector=selector||document;//设置默认值为document
  8. context=context||document;//设置默认值为document
  9. if(selector.nodeType){//如果选择符为节点对象
  10. this[0]=selector;//把参数节点传递给实例对象的数组
  11. this.length=1;//并设置实例对象的length属性,定义包含的元素个数
  12. this.context=selector;//设置实例的属性,返回选择范围
  13. returnthis;//返回当前实例
  14. }
  15. if(typeofselector==="string"){//如果选择符是字符串
  16. vare=context.getElementsByTagName(selector);//获取指定名称的元素
  17. for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
  18. this[i]=e[i];
  19. }
  20. this.length=e.length;//设置实例的length属性,即定义包含的元素个数
  21. this.context=context;//设置实例的属性,返回选择范围
  22. returnthis;//返回当前实例
  23. }else{
  24. this.length=0;//否则,设置实例的length属性值为0
  25. this.context=context;//设置实例的属性,返回选择范围
  26. returnthis;//返回当前实例
  27. }
  28. },
  29. html:function(val){//模仿jQuery框架中的html()方法,为匹配的每一个DOM元素插入html代码
  30. jQuery.each(this,function(val){//调用jQuery.each()工具函数,为每一个DOM元素执行回调函数
  31. this.innerHTML=val;
  32. },val);
  33. },
  34. jquery:"1.3.2",//原型属性
  35. size:function(){//原型方法
  36. returnthis.length;
  37. }
  38. };
  39. jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
  40. //扩展jQuery工具函数
  41. jQuery.each=function(object,callback,args){
  42. for(vari=0;i<object.length;i++){
  43. callback.call(object[i],args);
  44. }
  45. returnobject;
  46. };
  47. $("div").html("测试代码");
  48. </script>

在上面的示例中,通过先为自己的 jQuery 对象绑定 html() 方法,然后利用 jQuery() 选择器获取页面中所有的 div 元素,再调用 html() 方法,为所有匹配的元素插入 HTML 源码。

注意,在上面的代码中,each() 函数的当前作用对象是 jQuery 对象,故 this 指向当前 jQuery 对象,即 this 表示一个集合对象;而在 html() 方法中,由于 each() 函数是在指定 DOM 元素上执行的,所以该函数内的 this 指针指向的是当前 DOM 元素对象,即 this 表示一个元素。

2.2.7 延续 -- 功能扩展

根据一般设计习惯,如果要为 jQuery 或者 jQuery.prototype 添加函数或方法,可以直接通过点语法实现,或者在 jQuery.prototype 对象结构中增加一个属性即可。但是,如果分析 jQuery 框架的源代码,你会发现它是通过 extend() 函数来实现功能扩展的。例如,下面两段代码都是 jQuery 框架通过 extend() 函数来扩展功能的。

jQuery.extend({ // 扩展工具函数

noConflict: function(deep){},

isFunction: function(obj){},

isArray: function(obj){},

isXMLDoc: function(elem){},

globalEval: function(data){}

});

或者

jQuery.fn.extend({ // 扩展 jQuery 对象方法

show: function(speed, callback){},

hide: function(speed, callback){},

toggle: function(fn, fn2){},

fadeTo: function(speed, to, callback){},

animate: function(prop, speed, easing, callback){},

stop: function(clearQueue, gotoEnd){}

});

这样做的好处是什么呢?

extend() 函数能够方便用户快速扩展 jQuery 框架的功能,但是不会破坏 jQuery 框架的原型结构,从而避免后期人工手动添加工具函数或者方法破坏 jQuery 框架的单纯性,同时也方便管理。如果不需要某个插件,只需要简单地删除即可,而不需要在 jQuery 框架源代码中去筛选和删除。

extend() 函数的功能实现起来也很简单,它只是把指定对象的方法复制给 jQuery 对象或者 jQuery.prototype 对象。例如,在下面的示例中,我们为 jQuery 类和原型定义了一个扩展功能的函数 extend() ,该函数的功能很简单,它能够把指定参数对象包含的所有属性复制给 jQuery 或者 jQuery.prototype 对象,这样就可以在应用中随时调用它,并动态扩展 jQuery 对象的方法。

[html]view
plain
copy

  1. <div></div>
  2. <div></div>
  3. <div></div>
  4. <scripttype="text/javascript">
  5. var$=jQuery=function(selector,context){//定义类
  6. returnnewjQuery.fn.init(selector,context);//返回选择器的实例
  7. };
  8. jQuery.fn=jQuery.prototype={//jQuery类的原型对象
  9. init:function(selector,context){//定义选择器构造器
  10. selector=selector||document;//设置默认值为document
  11. context=context||document;//设置默认值为document
  12. if(selector.nodeType){//如果选择符为节点对象
  13. this[0]=selector;//把参数节点传递给实例对象的数组
  14. this.length=1;//并设置实例对象的length属性,定义包含的元素个数
  15. this.context=selector;//设置实例的属性,返回选择范围
  16. returnthis;//返回当前实例
  17. }
  18. if(typeofselector==="string"){//如果选择符是字符串
  19. vare=context.getElementsByTagName(selector);//获取指定名称的元素
  20. for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
  21. this[i]=e[i];
  22. }
  23. this.length=e.length;//设置实例的length属性,即定义包含的元素个数
  24. this.context=context;//设置实例的属性,返回选择范围
  25. returnthis;//返回当前实例
  26. }else{
  27. this.length=0;//否则,设置实例的length属性值为0
  28. this.context=context;//设置实例的属性,返回选择范围
  29. returnthis;//返回当前实例
  30. }
  31. },
  32. jquery:"1.3.2",//原型属性
  33. size:function(){//原型方法
  34. returnthis.length;
  35. }
  36. };
  37. jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
  38. //jQuery功能扩展函数
  39. jQuery.extend=jQuery.fn.extend=function(obj){
  40. for(varpropinobj){
  41. this[prop]=obj[prop];
  42. }
  43. returnthis;
  44. };
  45. //扩展jQuery对象方法
  46. jQuery.fn.extend({
  47. test:function(){
  48. alert("测试扩展功能");
  49. }
  50. });
  51. //测试代码
  52. $("div").test();
  53. </script>

在上面的示例中,先定义了一个功能扩展函数 extend(),然后为 jQuery.fn 原型对象调用 extend() 函数,为其添加一个测试方法 test()。这样就可以在实践中应用,如 $("div").test() 。

jQuery 框架定义的 extend() 函数的功能要强大很多,它不仅能够完成基本的功能扩展,还可以实现对象合并等功能。

2.2.8 延续 -- 参数处理

在很多时候,你会发现 jQuery 的方法都要求传递的参数为对象结构,例如:

$.ajax({

type: "GET",

url: "test.js",

dataType: "script"

});

使用对象直接量作为参数进行传递,方便参数管理。当方法或者函数的参数长度不固定时,使用对象直接量作为参数存在很多优势。例如,对于下面的用法,ajax()函数就需要进行更加复杂的参数排查和过滤。

$.ajax("GET", "test.js", "script");

如果 ajax() 函数的参数长度是固定的,且是必须的,那么通过这种方式进行传递也就无所谓了,但是如果参数的个数和排序是动态的,那么使用 $.ajax("GET", "test.js", "script"); 这种方法是无法处理的。而 jQuery 框架的很多方法都包含大量的参数,且都是可选的,位置也没有固定要求,所以使用对象直接量是惟一的解决方法。

使用对象直接量作为参数传递的载体,这里就涉及参数处理问题。如何解析并提出参数?如何处理参数和默认值?我们可以通过下面的方法来实现。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. var$=jQuery=function(selector,context){//定义类
  3. returnnewjQuery.fn.init(selector,context);//返回选择器的实例
  4. };
  5. jQuery.fn=jQuery.prototype={//jQuery类的原型对象
  6. init:function(selector,context){//定义选择器构造器
  7. selector=selector||document;//设置默认值为document
  8. context=context||document;//设置默认值为document
  9. if(selector.nodeType){//如果选择符为节点对象
  10. this[0]=selector;//把参数节点传递给实例对象的数组
  11. this.length=1;//并设置实例对象的length属性,定义包含的元素个数
  12. this.context=selector;//设置实例的属性,返回选择范围
  13. returnthis;//返回当前实例
  14. }
  15. if(typeofselector==="string"){//如果选择符是字符串
  16. vare=context.getElementsByTagName(selector);//获取指定名称的元素
  17. for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
  18. this[i]=e[i];
  19. }
  20. this.length=e.length;//设置实例的length属性,即定义包含的元素个数
  21. this.context=context;//设置实例的属性,返回选择范围
  22. returnthis;//返回当前实例
  23. }else{
  24. this.length=0;//否则,设置实例的length属性值为0
  25. this.context=context;//设置实例的属性,返回选择范围
  26. returnthis;//返回当前实例
  27. }
  28. },
  29. setOptions:function(options){
  30. this.options={//方法的默认值,可以扩展
  31. StartColor:"#000",
  32. EndColor:"#DDC",
  33. Step:20,
  34. Speed:10
  35. };
  36. jQuery.extend(this.options,options||{});//如果传递参数,则覆盖原默认参数
  37. },
  38. jquery:"1.3.2",//原型属性
  39. size:function(){//原型方法
  40. returnthis.length;
  41. }
  42. };
  43. jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
  44. jQuery.extend=jQuery.fn.extend=function(destination,source){//重新定义extend()函数
  45. for(varpropertyinsource){
  46. destination[property]=source[property];
  47. }
  48. returndestination;
  49. };
  50. </script>

在上面的示例中,定义了一个原型方法 setOptions(),该方法能够对传递的参数对象进行处理,并覆盖默认值。这种用法在本书插件部分还将进行讲解。

在 jQuery 框架中, extend() 函数包含了所有功能,它既能够为当前对象扩展方法,也能够处理参数对象,并覆盖默认值。

2.2.9 涅槃 -- 名字空间

现在,我们终于模拟出了 jQuery 框架的雏形,虽然它还比较稚嫩,经不起风雨,但至少能够保证读者理解 jQuery 框架构成的初期状态。不过对于一个成熟的框架来说,需要设计者考虑的问题还是很多的,其中最核心的问题就是名字空间冲突问题。

当一个页面中存在多个框架,或者自己写了很多 JavaScript 代码,我们是很难确保这些代码不发生冲突的,因为任何人都无法确保自己非常熟悉 jQuery 框架中的每一行代码,所以难免会出现名字冲突,或者功能覆盖现象。为了解决这个问题,我们必须把 jQuery 封装在一个孤立的环境中,避免其他代码的干扰。

在详细讲解名字空间之前,我们先来温习两个 JavaScript 概念。首先,请看下面的代码。

var jQuery = function(){};

jQuery = function(){};

上面所示的代码是两种不同的写法,且都是合法的,但是它们的语义完全不同。第一行代码声明了一个变量,而第二行代码定义了 Window 对象的一个属性,也就是说它等同于下面的语句。

window.jQuery = function();

在全局作用域中,变量和 Window 对象的属性是可以相等的,也可以是互通的,但是当在其他环境中 (如局部作用域中),则它们是不相等的,也是无法互通的。

因此如果希望 jQuery 具有类似 $.method(); 调用方式的能力,就需要将 jQuery 设置为 Window 对象的一个属性,所以你就会看到 jQuery 框架中是这样定义的。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. varjQuery=window.jQuery=window.$=function(selector,context){
  3. returnnewjQuery.fn.init(selector,context);
  4. };
  5. </script>

你可能看到过下面的函数用法。

(function(){

alert("观察我什么时候出现");

})();

这是一个典型的匿名函数基本形式。为什么要用到匿名函数呢?

这时就要进入正题了,如果希望自己的 jQuery 框架与其他任何代码完全隔离开来,也就是说如果你想把 jQuery 装在一个封闭空间中,不希望暴露内部信息,也不希望别的代码随意访问,匿名函数就是一种最好的封闭方式。此时我们只需要提供接口,就可以方便地与外界进行联系。例如,在下面的示例中分别把 f1 函数放在一个匿名函数中,而把 f2 函数放在全局作用域中。可以发现,全局作用域中的 f2 函数可以允许访问,而匿名函数中的
f1 函数是禁止外界访问的。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. (function(){
  3. functionf1(){
  4. return"f1()";
  5. }
  6. })();
  7. functionf2(){
  8. return"f2()";
  9. }
  10. alert(f2());//返回"f2()"
  11. alert(f1());//抛出异常,禁止访问
  12. </script>

实际上,上面的匿名函数就是所谓的闭包,闭包是 JavaScript 函数中一个最核心的概念。

当然,$ 和 jQuery 名字并非是 jQuery 框架的专利,其他一些经典框架中也会用到 $ 名字,也许读者也会定义自己的变量 jQuery 。

在这之前我们需要让它与其他框架协同工作,这就带来一个问题,如果我们都使用 $ 作为简写形式就会发生冲突,为此 jQuery 提供了一个 noConflit() 方法,该方法能够实现禁止 jQuery 框架使用这两个名字。为了实现这样的目的,jQuery 在框架的最前面,先使用 _$ 和 _jQuery 临时变量寄存 $ 和 jQuery 这两个变量的内容,当需要禁用 jQuery 框架的名字时,可以使用一个临时变量 _$ 和 _jQuery
恢复 $ 和 jQuery 这两个变量的实际内容。
实现代码如下。

[html]view
plain
copy

  1. <scripttype="text/javascript">
  2. (function(){
  3. var
  4. window=this,
  5. undefined,
  6. _jQuery=window.jQuery,//暂存jQuery变量内容
  7. _$=window.$,//暂存$变量内容
  8. jQuery=window.jQuery=window.$=function(selector,context){
  9. returnnewjQuery.fn.init(selector,context);
  10. },
  11. quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
  12. isSimple=/^.[^:#\[\.,]*$/;
  13. jQuery.fn=jQuery.prototype={
  14. init:function(selector,context){//定义选择器构造器
  15. selector=selector||document;//设置默认值为document
  16. context=context||document;//设置默认值为document
  17. if(selector.nodeType){//如果选择符为节点对象
  18. this[0]=selector;//把参数节点传递给实例对象的数组
  19. this.length=1;//并设置实例对象的length属性,定义包含的元素个数
  20. this.context=selector;//设置实例的属性,返回选择范围
  21. returnthis;//返回当前实例
  22. }
  23. if(typeofselector==="string"){//如果选择符是字符串
  24. vare=context.getElementsByTagName(selector);//获取指定名称的元素
  25. for(vari=0;i<e.length;i++){//遍历元素集合,并把所有元素填入到当前实例数组中
  26. this[i]=e[i];
  27. }
  28. this.length=e.length;//设置实例的length属性,即定义包含的元素个数
  29. this.context=context;//设置实例的属性,返回选择范围
  30. returnthis;//返回当前实例
  31. }else{
  32. this.length=0;//否则,设置实例的length属性值为0
  33. this.context=context;//设置实例的属性,返回选择范围
  34. returnthis;//返回当前实例
  35. }
  36. },
  37. setOptions:function(options){
  38. this.options={//方法的默认值,可以扩展
  39. StartColor:"#000",
  40. EndColor:"#DDC",
  41. Step:20,
  42. Speed:10
  43. };
  44. jQuery.extend(this.options,options||{});//如果传递参数,则覆盖原默认参数
  45. },
  46. jquery:"1.3.2",//原型属性
  47. size:function(){//原型方法
  48. returnthis.length;
  49. }
  50. };
  51. jQuery.fn.init.prototype=jQuery.fn;//使用jQuery的原型对象覆盖init的原型对象
  52. jQuery.extend=jQuery.fn.extend=function(destination,source){//重新定义extend()函数
  53. for(varpropertyinsource){
  54. destination[property]=source[property];
  55. }
  56. returndestination;
  57. };
  58. })();
  59. </script>

至此,jQuery 框架的设计模式就初见端倪了,后面的工作就是根据应用需要或者功能需要,使用 extend() 函数不断扩展 jQuery 的工具函数和 jQuery 对象的方法。

时间: 2024-09-18 00:48:02

第二章 jQuery技术解密 (二)的相关文章

第二章 jQuery技术解密(一)

2.2 jQuery 原型技术分解 任何复杂的技术都是从最简单的问题开始的,如果你被 jQuery 几千行庞杂结构的源代码所困惑,那么建议你阅读本节内容,我们将探索 jQuery 是如何从最简单的问题开始,并逐步实现羽翼渐丰的演变过程,从 jQuery 核心技术的还原过程来理解 jQuery 框架的搭建原理. 2.2.1 起源 -- 原型继承 用过 JavaScript 的读者都会明白,在 JavaScript 脚本中到处都是函数,函数可以归置代码段,把相对独立的功能封装在一个函数包中.函数也可

第二章 jQuery技术解密 (四)

2.3.4 生成 DOM 元素 jQuery.fn.init() 构造函数能够构建 jQuery 对象,并把匹配的 DOM 元素存储在 jQuery 对象内部集合中.jQuery.fn.init() 构造函数可以接收单个的 DOM 元素,也可以接收 DOM 集合.如果接收的是字符串型 ID 值,则直接在文档中查找对应的 DOM 元素,并把它传递给 jQuery 对象:如果接收的是字符串型 HTML 片段,则需要把这个字符串片段生成 DOM 元素.下面我们将重点分析 jQuery 是如何把 HTM

第二章 jQuery技术解密 (六)

2.4 解析 jQuery 选择器引擎 Sizzle jQuery 从 1.3 版本开始,使用了新的选择器引擎 Sizzle(官方网址 http://sizzlejs.com) .Sizzle 是 jQuery 作者 John Resig 开发的 DOM 选择器引擎 (Dom Selector Engine),速度号称业界第一.而且它有一个重要的特点就是 Sizzle 是完全独立于 jQuery 的,如果用户不想用 jQuery ,还可以只用 Sizzle . Sizzle 选择器引擎目前成为

第二章 jQuery技术解密 (五)

2.3.5 引用 DOM 元素 jQuery() 函数能够直接接受 HTML 字符串,并把它们转换为 DOM 结构,这是上一节中所讲解的利用 jQuery() 函数生成 DOM 元素.当然,我们也可以看到 jQuery() 函数还可以接收 DOM 元素.DOM元素集合.HTML标签或者 ID 值.下面我们就来分析 jQuery.fn.init() 构造器是如何把这些类型的参数转换为 DOM 元素的. 对于 HTML 标签来说,它使用 document.getElementsByTagName()

第二章 jQuery技术解密 (七)

2.4.5 Sizzle 构造器 在 jQuery.fn.init() 构造器中,通过调用 jQuery(context).find(selector) 函数来解析并匹配 DOM 元素.jQuery.find() 函数实际上是引用 Sizzle() 函数,而 Sizzle() 函数仅是 Sizzle 引擎的构造器,它主要调用 Sizzle.find() 函数在 DOM 文档树中查找与 CSS 语法相匹配 DOM 的元素节点的集合.jQuery 名字中 Query 的意义就体现在这里.下面我们来分

《众妙之门——JavaScript与jQuery技术精粹》——第1章 初学JavaScript 需知的七件事 1.1 缩略标记

第1章 初学JavaScript 需知的七件事 我很早以前就开始编写JavaScript代码,很高兴看到这种语言在今天所取得的成功,能成为这个成功故事中的一部分我很开心.关于JavaScript,我写过许多文章.章节以及一整本书,直到今天我仍在寻找新的东西.下文是一些我工作学习过程中激动时刻的记录,大家与其守株待兔,不如自己尝试去体会这种感受. 1.1 缩略标记 众妙之门--JavaScript与jQuery技术精粹 在创建对象和数组过程中可以使用缩略标记是我喜欢JavaScript的重要原因之

&amp;gt; 第二章 NGWS Runtime 技术基础(rainbow 翻译) (转自重粒子空

<<展现C#>> 第二章 NGWS Runtime 技术基础(rainbow 翻译)   出处:http://www.informit.com/matter/ser0000001/chapter1/ch02.shtml 正文: 第二章  NGWS  runtime 技术基础     既然你已经具有了C#全面的印象,我也想让你了解NGWS runtime的全貌.C#依靠由NGWS提供的运行时:因此,有必要知道运行时如何工作,以及它背后所蕴含的概念.    所以,这一章分为两部分--它

Google--PageRank技术解密(二)

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 Google-- PageRank技术解密(二)   7. 非PageRank因素阙值  8. 使用阙值推知两种排名策略的价值  9. PageRank的计算 七:非PageRank因子的上限阙值(Non-PageRank Factor Threshold)  除了PageRank外,其它排名因子都存在一个阙值,也叫临界值或差值.即当增长到一

深入理解bootstrap框架之第二章整体架构_jquery

一. 整体架构 1. CSS-12栅格系统 把网页宽度均分为12等分(保留15位精度)--这是bootstrap的核心功能. 2.基础布局组件 包括排版.按钮.表格.布局.表单等等. 3.jQuery bootstrap插件的基础 4.响应式设计 兼容多个终端.这是bootstrap的终极理念. 5.css插件 提供丰富的样式. 6.js插件 二. 栅格系统 1.基本实现过程 定义容器的大小--跳转边距--媒询 有以下要求: (1)一行(row)数据必须包含在.container中. .cont