庇护祝福的分享

Be worthy

Ruby_string

字符串连接

+
concat()
<<                              #concat()的参数为整数则会转换成对应的字符串。

正则匹配与替换

match , =~ , !~ 匹配

"name".match(/a/)         #=>true
"name" =~ /a/               #=>1                       #肯定匹配
"name" =~ /b/               #=>nil
"name"  !~ /b/                #=>false                 #否定匹配

delete() & delete!() 删除

example:
    str="ababaaaaaccccb"
    str.delete("ab")  #=>"cccc"        #删除所有包含的字符串,而不是删除字符串组合
    str.delete!("ab")      #=>"cccc"
    str #=>"cccc"
    str.delete!("ab")      #=>"nil"
    str #=>"cccc"

sub,gsub &sub!,gsub! 替换

"abcdefaaa".sub(/a/ , "x")  #=> "xbcdeaaa"
"abcdefaaa".sub(/a/ , "x")  #=> "xbcdexxx"
第一个参数可以是正则,也可是字符串

slice()&slice!()

参数可以是索引值,索引范围(range) , 正则 , 字符串。返回匹配的字符串。
"abcdaaa".slice(1) #=>"b"
"abcdaaa".slice(1..3) #=> "bcd"
"abcdaaa".slice(-3..-1) #=> "aaa"
"abcdaaa".slice(/a\w{3}a/) #=> "abcda"
"abcdaaa".slice("abc") #=> "abc"

slice!()会对原字符串进行切割,切掉匹配参数的部分
str ="abcdaaa"
str.slice!(0)
str="bcdaaa"

scan(regexp) 返回一个数组,所有匹配的字符串

split

离职总结

互联网方向和企业服务方向存在根本性的不同

现在OA,ERP系统等企业级服务等都在向web端,乃至移动端靠近,看起来好像和互联网服务区别越来越小,但是对于外包团队来说,区别是本质上的。

互联网产品面向普罗大众,要求是使用简单,可接受度高,个性化。而且互联网方向主要客户来自创业者以及传统行业面向用户渠道的互联网化。业务逻辑相对简单,但对品质的要求是比较高的。同样,这部分客户的资金实力往往比较弱。因此如果公司面向互联网渠道提供服务,我认为应该在设计,咨询,技术支持等方面入手。消耗的时间相对少,同时可以做多个客户,以量取胜。不要轻易尝试承接整体工程。风险大,周期长,利润低,除非有渠道可以做政府的项目,或者客户需求和自有产品对的上号。

而需要企业级服务的企业往往规模庞大,业务逻辑相当复杂,每个项目的价格都会比较高,赚头足,但是对外包企业的要求也比较高:首先,要有自己的基础产品,开发要基于基础产品来做,而不是从头开始,其次人手必须充足,这种项目往往不是2,3个精英程序员就可以搞定的,因为有大量的基础的,低技术含量的工作需要做,做这些事情使用高级程序员是非常不划算的,因此需要将功能拆分,通过使用大量的水平一般,薪水低廉的程序员来做,一方面需求使然,一方面控制风险。我认为这也是做这种业务的企业多使用.net,jsp的原因:容易招到大量的中低水平的程序员。

公司的问题

没有根据自身特点选准方向

1.外包方面的主管是设计外包出身,那么在设计人员招聘,设计咨询,忽悠客户方面是内行,并且有多年为运营商做前端,设计服务的经验。但是对技术评估方面并不在行,也没法在技术方面和客户进行沟通。

2.技术主管虽然先后就职于百度,人人,编程能力,学习能力,沟通能力都非常强,但是经验是在互联网方向,对于企业级的服务并不在行,而且他本人也对外包毫无兴趣。

因此很明显了,实际公司是无力组建一个面向企业的技术外包团队的,而面向互联网,也仅仅是可以做,但做不好,因为打心眼里就不想做。技术方面如果找不到适合带外包团队的人,那就干脆不要做,专心做产品去,外包全部由设计来支持,技术方面最多做一些咨询服务就好了。可偏偏公司要去接互联网前后台乃至app全包的项目。

明明是小公司,偏偏有大公司的毛病

就是一个创业型的公司,虽然有母公司的大力支持,但是实力仍然有限,但是信息隔离,缺乏激情,管理僵化,事不关己,高高挂起的毛病还是通过领导人从母公司带了过来。

CEO来自投资方

由于公司是香港集团的全资子公司,CEO是该集团的一位经理,但他同时管理多家控股公司,其他公司和母公司业务比较贴近,做硬件方面,更多的是资本,渠道的东西,这方面他很了解,而我们这边做软件,设计则更多是看人。一方面CEO并非所有精力都在这边,一方面他对设计和软件业务并不了解。而现在的情况是一个本该是政委,或者监军的人坐在了主帅的位置上。虽然这不是他的错,他也尽自己最大的努力放权给更懂业务的主管们,但毕竟身在那个位置,很多决策需要他来定。不可避免的会出现外行领导内行的情况。

%Q, %q, %W, %w, %x, %r, %s

%Q

遇到引号嵌套的时候我们往往需要使用反斜线来实现转义,使用%Q(…)可以实现同样的效果,最终输出字符串,并且支持使用#{}操作变量

>> %Q(Joe said: "Frank said: "#{what_frank_said}"")
=> "Joe said: "Frank said: "Hello!"""

The parenthesis “(…)” can be replaced with any other non-alphanumeric characters and non-printing characters (pairs), so the following commands are equivalent:

>> %Q!Joe said: "Frank said: "#{what_frank_said}""!
>> %Q[Joe said: "Frank said: "#{what_frank_said}""]
>> %Q+Joe said: "Frank said: "#{what_frank_said}""+

You can use also:

>> %/Joe said: "Frank said: "#{what_frank_said}""/
=> "Joe said: "Frank said: "Hello!"""

%q

%q和%Q大同小异,只是用于单引号,因此无法支持变量

>> %q(Joe said: 'Frank said: '#{what_frank_said} ' ')
=> "Joe said: 'Frank said: '\#{what_frank_said} ' '"

%W

转化为数组并支持变量

>> %W(#{foo} Bar Bar\ with\ space)
=> ["Foo", "Bar", "Bar with space"]

%w

转化为数组,但不支持变量

>> %w(#{foo} Bar Bar\ with\ space)
=> ["\#{foo}", "Bar", "Bar with space"]

%x

Uses the ` method and returns the standard output of running the command in a subshell.The syntax is similar to %Q.

>> %x(echo foo:#{foo})
=> "foo:Foo\n"

%r

转化为正则表达式

>> %r(/home/#{foo})
=> "/\\/home\\/Foo/"

%s

转化为symbols.It’s not subject to expression substitution or escape sequences.

>> %s(foo)
=> :foo
>> %s(foo bar)
=> :"foo bar"
>> %s(#{foo} bar)
=> :"\#{foo} bar"

Ruby中一些特别的数据类型

Range

example:

    1..9
    (1..9).to_a #=>[1,2,3,4,5,6,7,8,9]
    a=["aa","bb","cc","dd"]
    a[0..2]=["aa","bb","cc"]
    a..c
    (a..c).to_a #=>[a,b,c]
    (1..9) ===5           #=> true  #可以用做间隔测试

Symbol

Symbol是ruby特有的一种数据类型,每一个变量都对应这一个同名Symbol值,每个Symbol对应一个内部id,因此查询速度很快,常用于作为键名。

    1.9以前版本只支持 :name => "xieyu"
    新版本同时支持 name:"xieyu"

block

数组和Range可以通过block来进行迭代 example:

    (1..5).each{ |i| puts 2*i}
    #=>2
    #=>4
    #=>6
    #=>8
    #=>10
    花括号可以使用do ... end来代替
    (1..5).each do |i|
        2*i
    end

Hash

Hash本质是一个数组,但是它的索引值不局限于数字,它的索引可以是任何对象。

Ruby元编程笔记一

打开类

通过

class String
  def to_alphanumeric
    gsub /[^\w\s]/,''
  end
end

可以直接打开已有的类并给其添加方法,class关键字的核心任务是把你带入到类的上下文中,让你可以定义其中的方法。
如果方法名重合,那么会覆盖原来的方法,这称为“猴子补丁(Moneypatch)”。

对象和方法

class MyClass
  def my_method
    @v=1
  end
end
obj = MyClass.new

obj #=> <MyClass:0x007f8e42830838 @v=1>  #obj作为一个实例对象包含一个实例变量@v和一个类MyClss
obj.class  #=>MyClass
obj.my_method
obj.instance_variables #=>[:@v]

obj.methods.grep(/my/)  #=>[:my_method] 
MyClass.instance_methods(false) #=>[:my_method] 
MyClass.methods.grep(/my/) #=>[]       
#通过对比可以看出,my_method是MyClass的一个实例方法,只有当MyClass实例化后才能调用,MyClass类本身并没有这个方法。

MyClass.class #=>Class
#类也是对象,它包含一个叫Class的类。

类与模块

Class.superclass #=>Module
#Class的超类是Module,Class实际就是一个增加了new(),allocate(),superclass()的Module,Class是Module的子类.
#所有的类都最终继承于Object,Object继承于BasicObject

以Rake为例:

module Rake
  class Task
   #...
   #使用Rake::Task来拓展命名空间

关于常量:

module MyModule
  MyContent = "aaa"
  class MyClass
    MyContent = "bbb"
  end
end      
#对于常量MyContent,也可以使用MyModule::MyClass::MyContent这样的格式来引用

Kernel模块

Object引用了Kernel模块,因此Kernel模块中的方法可以对任何对象使用。那么可以用类似打开类的方式给Kernel增加方法(称为“内核方法”)

module Kernel
  def my_method
  end
end

self

class MyClass
  def testing_self
    @var = 10
    self.my_method()
  end
  def my_method
    @var = @var+1
  end
end

常用前端资源整理

整体解决方案

Bootstrap:

大而全的前端框架,适合原型搭建。
中文文档1 中文文档2

渴切

有很多适合中国特色的解决方案。

兼容性问题

Alice:

支付宝团队开源的兼容性问题解决方案
github访问

PIE:

CSS3在IE下的兼容

响应式设计

生产力工具

scss

基于ruby

less

基于js

compass

基于scss

常用效果

表单前端验证:

Livevalidation 中文文档

幻灯片:

表单美化与一致性:

iCheck:单选框与复选框的美化与一致性。

图表控件:

Chart.js:基于HTML5,通过ExplorerCanvas 可向下支持低版本IE,但只支持6种基本图表。

动画效果:

Javascript权威指南笔记二:核心语法(数组)

创建数组

字面量直接创建

example:

 var arr=[1,2,3,4,5];

使用构造函数array创建

example:

 var arr=new array()  // 创建一个空数组
 var arr=new array(10)  // 创建一个长度为10 的数组
 var arr=new array(1,2,3)  // 相当于字面量直接创建

数组方法

join()

将数组转化为字符串序列,参数为分隔符

reverse()

将原数组倒序排列

sort()

根据字母表排序

concat()

数组合并

slice()

返回指定的数组片段

splice()

在数组中插入或删除元素的通用方法

push()&pop()

在队尾实现添加或删除,实现类似堆栈的功能

unshift()&shift()

在队头实现添加或者删除。

数组方法分类

改变原数组:

reverse() , splice() , push()&pop() , unshift()&shift()

返回新数组:

concat()

JQuery插件开发

JQuery插件的开发是有一套成熟的规范的: 主要由以下几部分组成:

(function($){})(jQuery)

最外层的封装

$.fn

$.fn = JQuery.prototype。
在插件制作中,所有的对象方法都添加到$.fn对象中

$.extend和$.fn.extend()

extend(dest,src1,src2):将src1,src2合并到dest中,属性名相同的则后面的自动覆盖前面的,因此常用于default值的设置 extend(boolean dest,src1,src2):如果第一个参数为布尔值,则决定是否深层覆盖,如果为true,则嵌套的对象也将进行覆盖

$.extend(src)    //该方法将src合并到jquery的全局对象中,为JQuery添加了一个静态方法,可以用$.src()直接执行
$.fn.extend(src) //该方法将src合并到jquery的实例对象中,只有JQuery的实例才可以调用,比如$("#input").src()

this.each(function(){ })

编写该扩展方法执行的函数

example:

(function($){ 
  $.fn.tableUI = function(options){ 
    var defaults = { 
      evenRowClass:"evenRow", 
      oddRowClass:"oddRow", 
      activeRowClass:"activeRow" 
    } 
    var options = $.extend(defaults, options); 
    this.each(function(){ 
      var thisTable=$(this); 
      $(thisTable).find("tr:even").addClass(options.evenRowClass); 
      $(thisTable).find("tr:odd").addClass(options.oddRowClass); 
      $(thisTable).find("tr").bind("mouseover",function(){ 
        $(this).addClass(options.activeRowClass); 
        }); 
        $(thisTable).find("tr").bind("mouseout",function(){ 
          $(this).removeClass(options.activeRowClass); 
          }); 
          }); 
        }; 
})(jQuery); 

Javascript插件开发

用一个样例来讲述javascript插件的开发过程,虽然工作中更多的使用JQuery,但是原生js基础仍然很重要。 功能说明:一幅长长的画卷,按照一定的速度,或垂直,或水平循环滚动,在指定位置暂停X秒,鼠标进入停止,可以用按钮控制。 可以控制的属性: direction: 方向水平or垂直 stop_time: 暂停时间 hover_control: 鼠标进入是否停止 stop_position: 暂停位置(px) id:滚动体的id container:滚动体容器的id

var scroll={
  container:"content",
  id: "box",
  dirction:"marginTop",
  stop_time:3000,
  hover_control:"on",
  stop_position:[330, 660]
}
var scroll_module = (function(){
  var container = document.getElementById(scroll.container);
  var scroll_part = document.getElementById(scroll.id);
  var divheight= scroll_part.offsetHeight
  var part2 = scroll_part.cloneNode(true);
  container.appendChild(part2);
  var martop = parseInt(scroll_part.style.marginTop || 0 )
  var hoverover = false;
  var go = function(){
    martop = martop - 2;
    scroll_part.style.marginTop = martop + "px";
    timer = setTimeout(go , 5);
    for (var i=0,j=i+1;i<scroll.stop_position.length+1;i++){
      if (martop <=-divheight){
        martop = 0;
        clearTimeout(timer);
        setTimeout(function(){
          go()
        },scroll.stop_time)
      }
      else if (martop== -scroll.stop_position[i]){
        clearTimeout(timer);
        if(hoverover == false){
          setTimeout(function(){
            go()
          },scroll.stop_time)
        }
      }
    }
  }
  var hoveron = function(){
    scroll_part.onmouseover=function(){
      hoverover = true;
      alert(hoverover)
    }
    scroll_part.onmouseout=function(){
      go();
      hoverover = false;
      alert(hoverover)
    }
  }
   return {
     go : go,
     hoveron : hoveron
    }
})()
  scroll_module.go();
  scroll_module.hoveron();

Javascript权威指南笔记三:事件处理

注册事件处理程序

为javascript对象设置事件处理

用“on+事件名”来注册事件 example:

window.onload = function(){
    .......
}

为HTML标签设置事件处理

有一系列标准方法:
onfocus , onblur , onresize , ononline onafterprint , onundo , onredo , onload , onerror , onstorage , onhashchange
onmessage , onoffline , onpagehide , onhaschange , onbeforeprint , onunload , onbeforeunload , onpopstate

example:

<button onclick = "alert("Thank you!")">click me</button>

addEventListener( )

IE8之前的版本不支持,忽略。三个参数(“click” , function(){….} , false)

表单事件

window事件

鼠标事件

click:点击事件
dbclick:双击
mousedown:按下鼠标
mouseup:释放鼠标
mousemove:移动鼠标
mouseover , mouseenter(不冒泡):鼠标进入元素
mouseout , mouseleave(不冒泡):鼠标离开元素

键盘事件

DOM事件

HTML5事件

触摸屏事件