标签归档:Web

jQuery事件处理

在浏览器交互过程中特定事件发生时脚本会进行相应的处理, jQuery 会针对不同的事件进行特定的处理。

浏览器检测到自身发生变化或遇到错误时,抛出的事件称为浏览器事件。比如浏览器页面内容发生滚动时会触发 scroll 事件,浏览器出错会触发 error 事件。可分别对应事件绑定相应的事件处理函数,这样当事件发生时就会调用此函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//当一个image标签指定要加载的图片不存在时,产生错误
$("<img />", {
  "src" : "not/an/bb.png",
  "alt" : "no image"
})
.error(function() {
  console.log("图片无法加载");
})
.appendTo("body");
 
//当滚动浏览页面内容时,触发 scroll 事件
$(window)
  .scroll(function() {
    console.log("窗口滚动");
  });

通常在页面中的 javascript 会在页面加载完成后才能开始执行,为了防止脚本过早执行,而页面中的元素还未加载而导致异常,通常会使用 ready 函数来保证等 DOM 准备好可以接受处理时才触发进行处理,通常会把整个脚本做成一个回调函数传递给 ready 函数。

1
2
3
$(document).ready(function() {
  //脚本
});

在浏览器中可以触发很多事件,jQuery 提供很多快捷方法对应相应的事件,常见的事件有 click 、 blur 、 focus 、 mousedown 、 mouseup 、submit 等,给对应的元素绑定事件及其处理函数可在事件发生时进行相应的响应。

bind()

可以给元素绑定事件处理函数,可最多接受三个参数,第一个参数为事件名,第二个参数为事件处理函数,可以一次为多个事件绑定同一个事件处理函数,也可以为不同的事件绑定不同的事件处理函数。如果为多个事件绑定同一个事件处理函数,在第一个参数中用空格分隔不同的事件。如果要为不同的事件绑定不同的事件处理函数,需要给bind方法传递一个 JSON 对象。另外可接受的第三个参数用于向事件处理函数传递数据,这个参数是一个 JSON 对象,该参数的数据会绑定到事件处理函数的 event 对象,从而完成数据的传递。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//给段落绑定 click 事件,点击段落输出段落被点击信息
$("p").bind("click", function() {
  console.log("段落被点击");
});
 
//给段落绑定 click, mouseover 事件,并输出事件发生信息
$("p").bind("click mouseover", function() {
  console.log("事件发生");
});
 
//给段落绑定 click, mouseover 事件,并输出不同的信息
$("p")
  .bind({
    "click" : function() {
      console.log("Click Event");
    },
    "mouseover" : function() {
      console.log("MouseOver Event");
    }
  });
 
//给事件处理函数传递数据
var Msg = "message 1";
$("#bar").bind("click", {m:Msg}, function(event) {
  console.log(event.data.m);
});
 
var Msg = "message 2";
$("p.foo").bind("click", {m:Msg}, function(event) {
  console.log(event.data.m);
});

unbind()

可以使用 unbind 方法移除元素的事件,如果不带参数调用该方法,则会移除当前元素的所有绑定事件,如果需要指定移除那个事件,就把该事件名作为第一个参数传递给 unbind 方法,如果要移除指定的事件处理函数,就把准备移除的事件处理函数作为第二个参数传递给 unbind 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//删除绑定在段落中的所有事件
$("p").unbind();
 
//仅删除绑定在段落中的click事件
$("p").unbind("click");
 
//删除指定事件处理函数
var fun1 = function() {
  console.log("event one triggered!");
},
    fun2 = function() {
  console.log("another one event!");
};
$("#bar").bind("click",fun1)
         .bind("click",fun2)
         .trigger("click")
         .unbind("click", fun1);

live() 和 die()

live 和 die 跟 bind 和 unbind 类似,也是负责为元素绑定事件和事件处理函数,所不同的是能为动态添加到 DOM 中的匹配元素绑定事件和事件处理函数,用 live 绑定的事件处理和事件处理函数必须使用 die 来解除绑定, 在 jQuery 1.7 以后 live 以过时,应该使用on方法。

one()

跟bind功能唯一的区别就是使用one绑定的事件及事件处理函数是一次性的,事件触发后自动解除绑定,其他功能跟bind相同。

trigger()

触发事件使用trigger,接受两个参数,第一个参数是被触发的事件名,第二个参数可选,为数组类型,用于给事件处理函数传递数据。

1
2
3
4
5
6
7
8
9
10
11
//给 id = bar 的元素绑定 click 事件,然后触发
$("#bar").bind("click", function() {
  console.log("Clicked!");
}).trigger("click");
 
//给事件处理函数传递数据
var notice = "I was triggered!";
$("#bar").bind("click", function(event, msg) {
  var log = msg || "I was clicked!";
  console.log(log);
}).trigger("click", [notice]);

jQuery数据集处理函数及动画效果函数

map / each / show / hide / fadeOut / fadeIn / fadeTo / slideUp

slideDown / slideToggle /animate

本文中代码其测试页面点击此处可以查看

map & each

使用回调函数对结果集内的每个元素进行处理,回调函数接受两个参数,分别是当前元素索引和当前元素。二者的区别在于map返回回调函数返回值的新对象,each返回受回调函数影响的原始对象。
比如给所有的段落和类为foo的元素追加标签名和索引。

1
2
3
$("p,.foo").map(function(index, ele) {
  $(this).append("  " + ele.tagName + "  #" + index);
});

可同样使用each完成同样的功能,但是如果对追加了标签名和索引的元素集合进一步处理,比如给标签为,类为foo的元素设置一个红色的字体,黄色的背景,则应该使用each,如果使用map则无法达到期望的结果。

1
2
3
4
5
$("p,.foo")
  .each(function(index,ele) {
    $(this).append("  " + ele.tagName + "  #" + index);
  })
  .find("span.foo").css({"color" : "red", "background" : "yellow"});

show & hide

不带参数调用这两个函数会对元素的样式添加或删除display:none;
如 $(“#bar”).hide(); 或 $(“#bar”).show();
这样调用没有动画效果,直接显示或者直接隐藏,没有过度效果,可以通过增加过度时间参数来增加效果。
如 $(“#bar”).hide(2000); 或 $(“#bar”).show(2000);

fadeOut 、fadeIn、fadeTo

可以实现元素淡入淡出效果,fadeOut淡出,通过将元素透明度从1调整到0,来实现元素的淡出,元素淡出结束后设置元素display:none;样式,可设置持续时间参数,默认持续时间为400ms,也接受回调函数参数,在结束后被调用。fadeIn淡入,通过将元素透明度从0调整到1,来实现元素的淡入,元素淡入结束后如果元素有display:none;样式,则会移除该样式。fadeTo可指定淡入或淡出的透明度,为0至1之间的一个数值。必须提供两个参数,一个是持续时间,另一个是目标透明度,也可以通过回调函数作为第三个参数用于在调用结束后被调用。
淡入淡出函数接受两个文本的快捷持续时间,分别是fast和slow,分别对应200ms和600ms。
如将表单元素淡出,并输出对应淡出信息,再讲表单元素淡入,输出对应淡入信息。

1
2
3
4
5
6
7
$("form")
  .fadeOut(1000, function() {
    console.log("淡出!");
  })
  .fadeIn(1000, function() {
    console.log("淡入!");
  });

将表单淡出到50%透明度,并输出对应信息。

1
2
3
$("form").fadeTo(1000, 0.5, function() {
  console.log("50%透明度");
});

slideUp、slideDown、slideToggle

可以实现元素的收缩与展开,slideUp向上收缩元素,slideDown向下展开元素,slideToogle是展开和收缩的开关,当前元素处于展开状态,应用slideToggle则会收缩,当处于收缩的时候应用则会展开,收缩与展开结束后通过设置元素display:none;样式或删除该样式给用户视觉展现。都可以接受两个参数,分别是持续时间和回调函数。

1
2
3
4
5
6
7
$("p.foo")
  .slideUp(1000, function() {
    console.log("收缩!");
  })
  .slideDown(1000, function() {
    console.log("展开!");
  });

同样针对类为foo的段落使用slideToggle。

1
2
3
4
5
6
7
8
$("p.foo").slideToggle(1000, function() {
  $bar = $("p.foo").attr("style");
  if ($bar === "display: none;") {
    console.log("slide Up");
  } else {
    console.log("slide Down");
  }
});

animate

能利用元素绝大多数可视CSS属性制作动画,其接受两种格式的多种参数,其中第二种格式的参数有更多的选项​,分别是
animate({json target css}, duration, action, succ callback)
animate({json target css}, {json animate options})
我们给id=bar的段落增加背景色和边框,然后5秒内完成段落的长宽缩放,并输出完成信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$("#bar")
  .css({
    "background" : "yellow",
    "border" : "1px solid black"
  })
  .animate(
    {
      "width" : "500px",
      "height" : "100px"
    },
    5000,
    "swing",
    function() {
      console.log("animate complete!");
    });

采用第二种格式的参数代码如下,效果与前段一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$("#bar")
  .css({
    "background" : "yellow",
    "border" : "1px solid black"
  })
  .animate({
               "width" : "500px",
               "height" : "100px"
           },
           {
             "duration" : 5000,
             "easing" : "swing",
             "complete" : function() {
               console.log("Animate complete!");
             }
          });

jQuery中的内容包装与元素删除函数

wrap / unwrap / wrapAll / wrapInner

remove / detach

测试文件见前篇文章中的测试页面代码。点击此处可直接进入

wrap

在元素(标签)外包装一个或多个元素(标签),函数参数接受元素集合,也接受返回标签的回调函数作为参数。如通过在所在标签<span></span> 标签外包装<strong></strong>标签、给所有的段落包装<strong></strong>标签,使得文字变粗,或者给所选元素集合包装一个<div>

在使用的时候注意标签的嵌套是否合法,如给所有的段落外增加<strong></strong>就属于嵌套不合法。

1
2
3
4
5
6
7
8
$("span").wrap("<strong></strong>");
//$("span").wrap("<strong />"); $("span").wrap("<strong>");
//像上面这样写也可以
 
//类为foo的span包装<strong>标签,其他span标签包装<em>标签
$("span").wrap(function() {
  return $(this).is(".foo") ? "<strong></strong>" : "<em></em>";
});

unwrap

删除包住所选元素的元素,不接受参数,如要删除包住<span>元素的元素。

1
$("span").unwrap();

wrapAll

wrapAll将所选的元素集合都用一个元素包装,如将所有的段落用一个<div>包住,需要注意的是wrapAll是会移动元素的,在<span>元素集合上使用wrapAll,使用<strong>包住该元素集合。

1
2
3
4
5
6
7
var div = $("<div>", {
  "css" : {"background" : "yellow"}
});
$("p").wrapAll(div);
 
//注意元素的移动
$("span").wrapAll("<strong></strong>");

wrapInner

包裹元素内容,可以用标签包住元素内的所有内容,如将所有的段落文字变成粗体。

1
$("p").wrapInner("<strong />");

remove & detach

remove和detach用于删除DOM中的元素,其区别是remove直接删除选中的元素,detach除了删除选中的元素外,还保存了删除元素的数据。

jQuery在DOM中添加元素

学习jQuery使用的测试页面代码如下,后续的继续学习中如无变化则以该文档为测试练习文档,练习时jQuery的版本为1.11.1,其所在路径与测试页面相同,该系列文档为《深入PHP与jQuery开发》的阅读笔记及总结。

    <!DOCTYPE html>
    <html>
    <head>
      <title>Reading Test Page</title>
    </head>
    <body>
      <p>Hello World!</p>
      <p class="foo">Another paragraph, but this one has a class.</p>
      <p><span>This is a span inside a paragraph.</span></p>
      <p id="bar">Paragraph with an id. 
        <span class="foo"> And this sentence is in a span.</span>
      </p>
 
      <form action="#" method="post">
        <fieldset>
          <legend>Sign Up Form</legend>
          <label for = "name">Name</label><br>
          <input name="name" id="name" type="text"><br>
          <label for="password">Password</label><br>
          <input name="password" id="password" type="password"><br><br>
          <label>
            <input type="radio" name="loc">
            I'm on my computer
          </label><br>
          <label>
            <input type="radio" name="loc" checked="checked">
            I'm on a shared computer
          </label><br><br>
          <input type="submit" value="Log In"><br>
          <label>
            <input type="checkbox" name="notify" disabled="true">
            Keep me signed in on this computer
          </label><br>
        </fieldset>
      </form>
      <script type="text/javascript" src="jquery-1.11.1.js"></script>
    </body>
    </html>

append() / appendTo()

作用:在目标元素内之后添加元素
区别:由目标元素调用 / 由新建元素调用
示例:

    //append()
    var para = $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    });
    $("body").append(para);
 
    //appendTo()
    $("<p>", {
       "text" : "I'm a new paragraph!",
       "css"  : {"background" : "yellow"}
    }).appendTo("body");

prepend() / prependTo()

作用: 在目标元素内之前添加元素
区别: 由目标元素调用 / 由新建元素调用
示例:

    //prepend()
    var para = $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    });
    $("body").prepend(para);
 
    //prependTo()
    $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    }).prependTo("body");

after() / insertAfter()

作用: 在目标元素外之后添加元素
区别: 由目标元素调用 / 由新建元素调用
示例:

    //after()
    var para = $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    });
    $("p.foo").after(para);
 
    //insertAfter()
    $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    }).insertAfter("p.foo");

before() / insertBefore()

作用: 在目标元素外之前添加元素
区别: 有目标元素调用 / 由新建元素调用
示例:

    //before()
    var para = $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    });
    $("p.foo").before(para);
 
    //insertBefore()
    $("<p>", {
      "text" : "I'm a new paragraph!",
      "css"  : {"background" : "yellow"}
    }).insertBefore("p.foo");

一个游戏运营项目失败的思考

这是我对自己参与的一个项目失败的思考,有点马后炮的赶脚。仅仅代表个人的观点和看法,不一定正确,仅供记录我这个阶段的一些想法,积累下来以供将来重新的审视与提高。

先简要的介绍一下这个项目,这是一个网络游戏在海外运营的项目,促成这个项目的开始是出自同事以往行业内的从业经历,恰逢其会的是该同事具有前期能引流的人脉并且也愿意一番尝试,在技术上也具有在预期时间内完成基础平台建设的能力。在项目启动之初,可谓「天时、地利、人和」齐活了,一个比较完美的开始就这样诞生了,剩下的就是甩开膀子,在快速迭代试错中迈着小碎步向前奔跑,以成就一番事业。

「愿望总是美好的,现实总是残酷的」,我甚至不知道这个项目最终结束的具体时间,因为项目进行的中间我就已经离开这个游戏创业项目了,很短暂的开始,很短暂的结束,但当整个团队决定开始增加新方向的时候,这个项目终将结束在我看来也是必然的。

gameplatform

按照这个项目来说,项目的主体共有三方组成:游戏厂商、初始用户导入方、平台运营团队。三方各司其职,共同推进整个项目的发展。

(1)被选中且能够与我们开展合作的游戏厂商的主要工作是完成游戏的接入,游戏的升级维护及节日活动的推出与定制,另外就是三方的结算对账。
(2)初始用户导入方完成用户的引流工作,以及运营分成的财务结算对账,完成境外其他资源引流的合作洽谈,找出最佳的引流途径。
(3)平台运营团队就是我们了,主要负责运营平台的建设、游戏的筛选与签订合同、游戏接口与平台的接入、平台的充值及换算、后台数据分析与核对、游戏运营活动的策划与运营推广、游戏客服、「建立自己的用户资源」、与各方财务结算。

游戏厂商在整个进程中的配合是非常良好的,在发生问题的时候总是能及时得到反馈,在活动及游戏内资源的支持上也不遗余力,而且从洽谈的过程中,能明显的感觉到他们是乐意合作的。

初始用户的引流工作虽然是资源方乐意尝试的,但不是其主营,这点上可能力度有待进一步加强,这些可以通过沟通来解决,还有就是对于引流的效果应该由我们结合引流方式给予资源方一定的支持,当然这些是要依据一定的数据方式,比如在游戏中做一些有奖励的调查问卷来获得其大部分的来源途径,其实这些在资源方那边是可以统计出来的。

我主要负责技术这块,并且参与跟游戏厂商的洽谈接触,在初始系统基础上安排设计人员和开发人员进一步定制以后基本上满足开始的运营需求,整个平台就这样开始运营了。我一直认为在一件事开始之后,专注与围绕专注开展工作是一个前提,就这个平台开始运营之初,构成其未来的主要工作集中在两部分:「其一是运营推广,这是重中之重,其长期努力的方向是建立自己的用户资源;其二是围绕运营推广提供强劲持久的技术驱动力,持续发展运营平台及其周边增值服务,保证给不同类别的用户持续输出富有娱乐性的游戏」。

围绕这两部分开展工作就是基础,刚开始运营其实从数据上来看还是比较符合预期的,在差不多一个月单游戏单区的情况下,用户注册数、每日在线数、充值数、日注册及活跃增长数及用户留存率上来看还相对符合预期,下面是一个月的部分充值记录。

paysummary

有了一个好的开始,但随后突然就放下了,主要的工作没有行之有效的开展,或者说没有足够的努力。危机意识不强,对技术长期驱动力的价值也不太认可,加上团队成员的实际生活问题等诸多因素的影响下,又有了开展其他行业新业务想法。在这种情况下,我最终选择了离开,因为我没有更多的资金投入开展新的业务,同时我也不认为当时的团队与投入能够有精力同时开展两条线的业务。

至于说主要的工作没有行之有效的开展是我个人的观点,对于我这个初次涉足游戏行业的人来说,在开始到离开这段时间其实有不少的想法,比如说在通过资源方引流的原始用户基础上,通过怎样的策划与推广,带来新的朋友用户,能不能制订积分体系加物质激励来完成?能不能通过游戏虚拟物品激励来完成,平台自己是否增加用户推荐体系并给予满足条件的推荐用户以激励?围绕游戏如何建立社区论坛?能否增加周边商城拓展游戏增值服务?满足这些运营平台应怎样重新架构? 诸如此类的想法有不少,但是这些想法没有成文后与团队成员进行充分的沟通,虽然这些想法对于初涉游戏行业的我显得比较稚嫩,但至少也应该跟团队成员讨论一下,在讨论过后相信自己也能获得长足的提高,增加对这个行业的认知。

危机意识不强的很大一部分原因是被这开始的充值额冲昏了头脑,按照一款游戏一个区来计算,想来多款游戏多个区就能达到预期,从我后来离开后的间断性关注中,先后上线了新的两款游戏,并且增加了新开区,但是充值及用户增长却一度中断,中间我没有看到任何针对这些不好影响的调整。这段时间我的猜测是人力资源不能跟进以保证用户的使用引导及足够的支持工作,由于新开展的其他行业新项目占据太多的精力,导致迟迟没有建立初步的用户服务机制、用户引入机制、用户激励机制、用户参与机制等。且在整个行业的发展中,游戏的变化也是急剧的,缺少对端游、页游、手游这些不同类型游戏的持续性关注。

再往后就没有往后了,却留下了诸多的不良影响,影响之一是在合作过程中给其他两方留下了一定的印象;影响之二是给玩过一阵的玩家留下了一定的印象,进而导致资源方也给玩家留下了足够的印象;影响之三是给所有团队成员留下来一定的印象。那么收获呢?

对于我来说这个短暂的创业经历有几点收获:

(1)要一直专注,所有要做的事情都要围绕最初设定的目标来做,尝试能够尝试的一切方法只为向目标迈进或者由目标衍生的新目标,直至结束,在未终止前我们其实没有更多的精力同时专注两件事;
(2)要有危机感,要给自己设定尽量涵盖全范围的最差的情况,然后设法找到解决方式,时刻保持危机感能促使专注;
(3)运营是重中之重,运营始终需要强力的技术作为保障,从这个角度来讲,技术是运营的支撑,技术是驱动力,要尽量获得团队成员对技术的认可,运营平台系统的建设不是一锤子买卖,需要长时间的演变,从功能到架构;
(4)要设定退场时对各方影响的补偿机制,用户从开始使用提供服务的第一天就会投入情感,任何时候不要让用户失望,说不定结束前小小的沟通就能超出用户的预期;
(5)人在任何时候都是关键,保持足够的沟通能够增加互相的了解,比较理想的是在没明确结束前,大家都能全力的参与其中;
(6)多少人做多少事,我们往往太过相信自己能够做的更多,可往往我们并不能做更多的事情,我们往往过高估计自己。