Casual & Fellow

Cash is King :-)


  • Home

  • Archives

  • Tags
Casual & Fellow

2012年终总结

Posted on 2013-02-10


其实每次农历新年都算是自己的反思夜,反思过去的一年,反思过去发生的事情。而这些事情,都会让我走得更远。2012年是多么丰富多彩的一年,比2011更加的丰富,踏实。遇到了那么多的人,认识了那么多的良师益友,学习了很多自己想要学习的东西,同样的也放弃了好多事情,让我有足够的精力去面对我喜欢的东西。确实要感谢这一年来,家人,朋友鼓励和支持。这篇文章算是给自己一个回忆吧,基本上还是和去年一样,用时间线记录下来。最后也会说说未来一年大体想做的事情。
一月份到二月份:
这段时间里面,我一直在思考几个问题:1,什么是我想要的;2,我喜欢一些什么;3,我做的东西到底对谁有价值,我做的东西我自己会用吗?第一第二个问题我都得到了回答,第三个问题,同样也得到了回答。但是我发现当时的我对于第三个问题的答案我并不满意,于是我选择去放弃一些东西。因为我始终过不了那一关,如果我发现我做的东西对于社会的价值偏低,严重一点,这个东西连我自己也不会去用,那么我会选择放弃。因为那已经达到了兴致的最低点了。因此,对于技术,对于事业,对于生活,我都会抱有这样的态度。当然,如果要选择放弃一些东西的话会让自己难过一段时间。也许难过过后就会让自己知道自己的选择其实没有错。

三月份:
用了大概一个月的时间吧,我证明了我的选择其实是正确的!因为我会放弃一些事情,然后获得一些额外的东西。很有幸地我认识了一群非常聪明的人,也非常值得敬佩,让我学习的人。让我每天都能够处于学习,追赶的状态。这种感觉非常棒!因为这样会感觉自己背后有一股很强的后助力!让自己去进步。也在这个月里面,我开始了一些非常有趣的生活。住公司,学会独立生活,管理自己,安排更多自己的学习。
而且这个月我还参加了Code Jam。也算是第一次参加编程比赛吧,而且这次的比赛让我认识了非常多厉害的人。在技术的圈子里有时候确实觉得很小,但有时候也会觉得很大。觉得很小的原因是好像大家都认识。觉得大的原因是其实很多人都在做跟你一样的事情,如果不努力就会落后!而且我也感觉大家的干劲很足,其实这些年,都是中国互联网创业,发展的绝佳机会。乱象丛生中才能出英雄吧!也许在这个月里我遇到的难题也变多,因此我也发现到自己的基础如何如何不足,我就摸索到一条更准的路,在技术上专攻下去了。

四月份到六月份:
我开始将自己定位得更基础,更专注。因为只有把自己的技术基础打得更扎实,对于各种项目的把握才可以更加有信心。我开始想尽办法去寻找一切的学习资源,并不断地消化,吸收。我想,四月后的每一个月我都在向前奔跑吧。这一年下来,我看过的书,保守估计已经超过50本了,基本上可以说一个星期一本了。不过这也同样让我陷入了一些小的迷惑,其实技术是一个无底洞!而且不管哪个学术领域,都是无底洞。所以我也从本质上告诉自己,自己学习的是理科,每个基础都不应该落下!

七月份到八月份:
这两个月里面我同样坚持着学习。这两个月里面可以说更多时候是无拘无束的状态了!基本上每天都能够用上自己喜欢的技术,做自己喜欢的一些事情。而且这两个月里面的两次出行也让我感受非常的深。一次是杭州,一次是北京。在杭州的时候,给我更多影响的是技术吧。因为当时参加了杭州的阿里巴巴技术嘉年华。可以说很多东西都是前所未有的震撼。不过是哪个领域,阿里在国内,甚至世界上都是领先的。遇到的问题同样是前所未有的。在这里也就给我了4个启发:1,要跟聪明的人在一起,才能够做出厉害的事情;2,解决问题的实践中,要有术,更要有道,要将技术思维运用到生活的方方面面;3,要做对社会,对用户有价值的事情,才能够挣钱;4,小就是美!
再一次是北京。北京的一行基本上我就是在和朋友碰面以及在北京瞎逛了。不过也很庆幸的是,在北京让我感受到社会各个阶层的缩影,以及各种人待在北京的心态。这一行同样让我有不少的感想:1,再次证明了我心中的一个观点,就是所有的事情都是有联系的;2,正因为所有的事情都有联系,所以尽可能快地让自己掌握更多的资源,让这些联系都串联前来。

九月份到十二月份:
后半年的时间里面其实应该算是非常累的。一边上学,一边上班。这段时间这么下来让我学习到了非常多的东西。一边自修数学,以及更多的编程语言,一边要让自己的工作项目变得完美。这种强迫着让自己把事情做到靠近100分的方式,往往能够让自己的能力提高得很快!这段时间里面让我学习到的东西是:
1,往往自己觉得足够,其实还是不够,因此这个时候不应该妥协。比如说,开发的工具似乎已经变得足够好用了,但是往往一给用户去尝试,就会发现一些新的问题出现。也就证明了,自己满意其实还是不够,要永远抱着自己过关,可能仅仅是及格分,离满分还有很远;
2,在程序的世界里,也许是因为需求变多了,也许是自己的基础还不够扎实,也许是因为开发工具的变多方式的变多,会遇到无穷无尽的Bug,人要学会忍耐以及应变。只要一抛给别人去用,你就相当于在做Service,所以千万不要自足;
3,永远保持学习的心态,把自己定位为一个全方面的人,千万不要给自己贴标签,也不要给别人贴标签。在这半年的工作里面,往往会发现知识是交叉的。比如说:前端的开发人员,也往往要处理后端的一些事情,在这样的情况之下,如果你给自己贴了标签,把一些工作留给后端的人做,这样的话你就会丧失了一次学习的机会,以及让自己提高的机会。此外,这也会让你的思维处于局限。因为眼界放得更宽了,知识点才可以打通,你才会了解更多有用的思想。

对于未来一年,我也有了一些想法了,也给了自己一些机会。我想我要再次用自己的方法去养活自己,也想去创造一些新的东西。在我的心里面,依然保持着这样的想法,做的事情一定要对用户,对社会有价值,这些东西我自己也很喜欢去用。这些东西也许不会天马行空,也不一定有什么很颠覆性的思维。但是一定要具有互联网精神,即使不是互联网产品。前半年,我想我还是会花更多的时间去学习,学习一切我想学习的东西。可能这半年里面,我会尝试去接触法律,经济学,社会学相关的东西,让自己变得更强,更全面。此后半年,我会努力往前奔跑,尽可能不辜负大家的期望。然后再酝酿一年,我想方向会更明确,路会更宽,不管有多崎岖,都不会害怕!Welcome to 2013!

Casual & Fellow

Jade模板引擎客户端服务端同时使用

Posted on 2012-12-20 | In 未分类

在Stackoverflow上面看到一个问题
Client side + Server side templating, feels wrong to me, how to optimize?
对于客户端,服务端同时使用Jade模板引擎怎么优化呢?其实问题作者的原意是如何同时使用,而且能够让代码保持分离,同时易于维护。基于我对模板引擎的理解,以及以往的使用经验,其实这个问题并不难,于是我回答了一下,简单地做了一个英文的教程。搜索以下国内的文章,似乎没有一些简单的教程,可能会对好像我这样的菜鸟造成学习上的困扰,于是就把答案转译成中文。分享以下,也欢迎大家同时提供更好的编码经验,分享一下。

毫无疑问,Jade是一个非常不错的模板引擎,尽管它也有一些Bug,不过你提issue,应该很快就会被解决掉的。而且它的语法基于HAML,甚至更优,提高效率的东西因此值得我们去尝试使用。

在阅读本文之前,我假定你已经使用过其他的模板引擎,或者已经会使用Server端的模板引擎。如果不懂的话,要折腾一下,应该很容易理解的。那么在把Server端和Client端的Jade结合前,我们先尝试把单纯客户端的Jade模板渲染,做一遍。

首先我们要下载Jade到本地

git clone https://github.com/visionmedia/jade.git

接着我们需要
$ make jade.js
事实上,jade的项目下,已经有这两个文件了:jade.js 或者 jade.min.js。这个时候,我们只是需要把这两个文件放到我们喜欢的路径上,然后让浏览器加载他。

第三步,看看我的demo,我加载了jade以及jquery,而且你还看到我加载了一段jade模板代码进来。其中item是一个变量,我们就利用jade模板引擎的api使用方式,逐步地把这个模板渲染出啦。

代码中已经把基本的html元素去掉了,因此自行加上 :
<script type='text/javascript' language='javascript' src="lib/jquery-1.8.2.min.js"></script>
<script type='text/javascript' language='javascript' src="lib/jade/jade.js"></script>
<script type='template' id='test'>
ul
  li hello world 
  li #{item}
  li #{item}
  li #{item}
  //这个是jade的模板引擎代码 我们将会渲染三个item变量出来,值都是 "this is an item"
</script>
<script>
  var compileText = $("#test").text();//获取我们要编译的模板文本,数据类型是string,注意缩进
  console.log( typeof( compileText ) );
  var fn = jade.compile( compileText , { layout : false } );//利用jade编译模板文本
  var out = fn( { item : "this is an item " } );//编译好之后,我们执行该函数,把我们要传的变量,渲染的数据传入
  console.log( out );//最后输出最终编译的结果
  $("body").append( out );//利用javascript渲染到前端页面上
</script>

最终看到的结果是

hello world
this is item
this is item
this is item

就是上面简单的几个步骤就可以把我们需要渲染的东西渲染出来了。很简单吧。那么疑问就来了,要是我们服务端要使用jade,客户端也是使用jade,岂不是有语法冲突?(试想一下,服务端使用jade,在服务端就把模板渲染好了,客户端上面拿到的是已经编译好的代码)

这个时候我们就必须要解决冲突的问题。还好。jade早就提供了这套解决方案了。这里要记住,服务端有服务端的渲染,客户端有客户端的渲染。下面来看看例子:
index.jade

!!!5
html
  head
   title hello world
  body
    ul#list

    script#list-template(type='template')
      |- for( var i in data )
      |    li(class='list') \#{ data[i].name }
      |- }

很明显,上面是服务端需要渲染的jade文件,代码应该很容易看懂了。和上面的例子一样,我们在上面要渲染的模板是id 为 list-template里面的内容。不过写法似乎有点不一样 :-)。首先缩进相同的情况下,在代码的左边都加上了 “|” 。

加上”|”的原因是,为了避免和server端的jade模板代码造成混淆,不然可能会报错,或者无法正常去到客户端渲染。

其次,你会看到在#{ data[i].name }的前面,加上了”\”符号,实质上同样是为了转义,不被污染。

下面再看javascript的代码

index.js

/* you javascript code */
var compileText = $('#list-template').text();
var compile = jade.compile( compileText , { layout : false } );

var data = [{ "name" : "Ben" } , {"name" : "Jack" } , {"name" : "Rose" }];
var outputText = compile( data );

$("#list").append( outputText );

这下很容易理解了吧。最后输出的结果就是

Ben
Jack
Rose

小提示:其实在调试的时候有jade语法错误提示,但是依然挺麻烦的。如果确实遇到jade模板服务端,客户端混淆的时候,不妨尝试一下先在纯html页面中,载入jade,写一些测试代码,然后让jade进行渲染。保证到需要编译的文本,是字符串,而且语法符合编译的要求。这样就没有问题了。

更新部分:
上面的内容基本上围绕服务端,以及客户端同时使用Jade的情况。那么如果单纯在客户端使用Jade呢?其实也是可以的。不过写法有点不一样。这里再从更新部分给大家展示一下。

<script id='list-template' type='template'>
- var type = ['爱情','生活'];//此后还要加入颜色分类
- for( var i in data ){
   li.question-list-button( data-id='#{ data[i].id }' )
     .icon 
       img( src='#{ data[i].icon }' )
     .message
      h3.no-return #{ data[i].title } 
      p( class='message-panel no-return' ) #{ ( 235 - data[i].id ) + '天,' +data[i].use_times+'人测过' } 
      p( class='type-panel no-return' ) 
        span #{ type[data[i].type] } 
- }
</script>

大家可以看到,script标签内就是Jade模板的代码了。对于这里的缩进是有要求的。不然你的编译会出错。提示缩进不正确。正确的缩进如上面展示的代码所述。在script里面,逻辑代码全部靠左,不留可白的地方。对于变量,逻辑,循环等的特殊语句需要在前面加上横杠,这个就好像上面Jade Server Side & Client Side的Example一样了。注意的地方就是靠左以及不留空。估计我现在这样表述或许会有点不清,不过在实际写代码时,你注意一下就可以了。:-)

20130720更新部分:
今天遇到另外一个场景,就是在pyjade下,服务端以及客户端同时使用jade。此前采用的方式是直接在HTML文件里面添加一个script标签,然后写入脚本。但是使用pyjade的时候发现同样的语法会报错,暂时没有办法解决(因为这里可能是pyjade本身存在问题,也可能是我的代码没有针对pyjade写对。这里还有待研究。后来想想,我在这里边要写的jade模板其实还是不少的,全部塞进HTML文件里面似乎也不太适合。这里不如就采用一种方法,让模板文件分开管理,然后采用异步加载的方式将这些文件引入进来。

(下面是一个示例)于是我就省下了写script标签的功夫,直接把这些模板写入list-template.txt文件中。文件中的内容如下:

  • for( var i in listdata ){
    li #{ listdata[i].name }
  • }

    然后在javascript中则是这样引入的:

    <script id=’list-template’ type=’text/javascript’>

var request_template_dir = ‘…’;
var listdata = [{ “name” : “Ben” } , {“name” : “Jack” } , {“name” : “Rose” }];//需要全局变量才可以使用template渲染

$(function (){

$.get( request_template_dir + “list-template.txt”,function ( template_string ){
console.log( template_string );
var compileText = template_string;
console.log( typeof( compileText ) );
var compile = jade.compile( compileText , { layout : false } );
var outputText = compile( listdata );
console.log( outputText );
$(“#option_list”).append( outputText );
});

});

</script>

这样就顺利地把模板渲染出来了。这里有一点是非常值得注意的,就是你会看到我的渲染数据使用的是一个全局变量。这点非常重要,假设这个listdata写在闭包里面的话,渲染的时候会出现 listdata is not define的错误。这里的话大家稍微想多一层就会明白为什么会这样。结合以前的例子,渲染的时候,我们的模板是直接写在HTML中的,如果使用模板引擎进行渲染的时候,会直接把渲染的数据暴露在全局变量中,让操作得以正常运行,这里只是在写脚本的时候,定义好这是全局变量。因此避免出现未定义变量的情况。

其实本文并没有什么技术含量,仅仅是一个小教程以及解决一些小疑惑。jade的强大还远远不止这些呢。不过上面已经含括了挺多的功能啦,具体的语法还需要你亲自去探索。

其实最近我的个人网站也在偷偷地上线啦,www.cashlee.me 上面会属于我的开源项目,以及一些想法的实验。同时我也会对一些服务封装一些api出来,提供给大家使用。希望大家喜欢。当然我也会长期维护,放更多有趣的东西上去提供给大家玩,或者自己玩。

Casual & Fellow

Jade模板引擎 VIM语法高亮配置

Posted on 2012-12-19

Jade是原本Node.js框架Express.js推荐使用的模板引擎语言,可是在3.0后,Express.js就好像取消掉了。不过这不阻碍我对这个模板引擎的喜爱,而且语法非常逼近Javascript程序员的写法(至少和HAML语言相比,确实是的)。所以我还是推荐大家使用。

在VIM上,我们编程首先要爽一下,就是语法高亮。对于一个新的语言,要支持,必须要配置一下嘛。貌似没有人发过类似的Config教程,小弟就简单写写吧。

首先Github上面把项目克隆下来,Github项目地址是:git clone git://github.com/digitaltoad/vim-jade.git

克隆下来后大家会看到以下几个文件夹。

/ftdetect
  jade.vim
/ftplugin
  jade.vim
/indent
  jade.vim
/syntax
  jade.vim
没错,这几个文件夹都又jade.vim文件。我们下面要做的就是要把这几个文件夹里面的jade文件,相应地复制到以下这个目录里。
/usr/share/vim/vim73(你的电脑可能不一样)/

你会看到对应的ftdetect ftplugin indent … 文件夹。

确定都复制过去后,把 ~/.vimrc 文件配置以下,支持以下语法高亮即可。

把以下行复制到 ~/.vimrc 文件中即可

syntax on
Casual & Fellow

Phonegap keyboard autohide in ios 关于Phonegap 键盘实现JS控制隐藏

Posted on 2012-09-11

最近困惑于Phonegap的各种诡异问题以及关于键盘事件的控制,实属非常无奈。加上@大城小胖 说了一句,越了解html5就越觉得他的局限性,实在是有种同是天涯沦落人的感觉。不过无论如果,需求都得想办法来解决。

控制键盘事件,在Phonegap或者直接说在ios的uiWebView中,其实都是无法用js来控制的,这个时候只能够透过native code来解决,然后放出接口给js来控制。这里就有一段关于ios键盘降落的native code,需要的朋友可以随便拿去。作出这个脚本主要的想法是这样的。项目中涉及到一个搜索框,搜索完毕后理应将键盘降下,降下键盘我们需要用到native code。

如果你在项目中有使用到任何的phonegap plugin,或许你只是需要将这个方法塞到你的plugin中。注意是以m为拓展名的文件。例如如果你是希望插入到childBrowser的插件中,就添加到 ChildBrowserCommand.m 文件中即可。因为这里主要是以接口作为调用的。

代码如下:


/* keyboard auto hide solution */
- (void) hideKeyboard:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
{
    //UIButton *button = [UIButton
    buttonWithType:UIButtonTypeRoundedRect;
    NSLog(@"hideKeyboard is being called");
    [self.webView endEditing:YES];
} 

那么调用的时候js的代码是:

function hideKeyboard(){
        console.log("关闭键盘");
        cordova.exec("ChildBrowserCommand.hideKeyboard", "隐藏键盘");
}

就是这么简单,注意这里我们使用到的cordova,所以版本过低的用户就肯定是无效的啦。自觉升级到Phonegap 1.5以上吧。现在都2.0啦。

Casual & Fellow

再谈Phonegap应用优化-启动闪屏问题

Posted on 2012-08-24

兴高采烈地到了应用收尾的界面优化阶段,可是问题突然出现了。就是进入应用的时候出现了闪屏的问题。说白了就是性能的问题。因为首次进入应用的时候,我们要做的就是要渲染首页的html+css,这个时候资源一多就会慢。下面就来说说处理的办法。

我们都知道在Phonegap的应用里面,有个Cordova.plist的配置文件,这个文件中有一个AutoHideSplashScreen的设置项,这里就是设置启动页是否自动隐藏的。这里就存在一个问题了,这里的自动隐藏并不是基于Phonegap把你的资源渲染完毕就隐藏的,而是资源加载完毕就自动隐藏的。所以我们就应该在这里调为手动隐藏了。设置办法就是:AutoHideSplashScreen的布尔值改为:NO.好了,这个时候你可以把你的app Build一下,这个时候你就会发现,你的app一直都停留在启动页面。下一步我们就是要将启动页面手动地隐藏掉。

在Phonegap里面,也就是Cordova里面,有很多控制App的内置函数和方法,例如alert,confirm这些基本的提示框。同理,我们也可以关闭启动页面。具体代码就是下面这一句话:

function onDeviceReady(){
    setTimeout("cordova.exec(null, null, 'SplashScreen', 'hide', [])",2000);
}

为什么要setTimeout呢?因为我们在渲染整个页面的时候,是需要时间的,我们期望的是渲染完页面之后才关闭这个启动页面,而实际上渲染完整个页面需要多少时间呢,这个就需要自己去写脚本测试,把渲染的时间print出来,具体print出来的时间就可以在setTimeout中加入。注意的是这段setTimeout的函数,要在DeviceReady后才去调用,不然的话这里就不能够用cordova调用底层函数,关闭启动页面。这里为什么我要强调说要测试这个渲染的时间呢?原因是我尝试过不去设置setTimeout,让app一直停留在启动页面上,实际上这个App已经渲染好界面,而点击“启动页”的时候,实际上也可以操作这个App,只是这个元素都被埋藏在下面,这就可能会导致用户产生误操作。这里必须要控制好。

此外Phonegap的app启动的时候都会有一个loading的小菊花,这也会影响app的体验,这里我们需要关掉这个小菊花。方法还是很简单,也是在Cordova.plist文件中,找到ShowSplashScreenSpinner的选项,把布尔值改为:NO就可以了。这时候小菊花就被隐藏掉了。

其实这么多小问题,归根结底都是性能问题,今天早上也看到新闻说Facebook用原生的方式把App重写了,其实也同样是因为性能问题。苹果似乎不太欢迎这些Hybrid的应用,所以渲染速度上,UIWebView的性能要比Safari的慢。这里就要求我们开发人员在做HybridApp的时候,更多地在Js层面上,用异步编程,让程序的每个交互顺序执行,保证到App的流畅性。所以有些时候觉得,Hybrid App可能比Native更讲究技术性。大家加油吧!

Casual & Fellow

周日下午小尝试-触摸反馈

Posted on 2012-08-05

炎热的周日下午,修复了一些bug(部分bug和项目有关,暂时不说),也做了一些代码片段,以便日后使用。这个文章也主要是用于给大家说说这个代码片段的由来以及要解决的问题。以顺便复习一下此前说的一些小问题。

这个代码片段的地址我已经放到了Github上面,当然这个是我随便写的,还有要提升的地方。这算是一个稍微提升用户体验的效果吧。上上个星期,我参加了爱范儿的一个活动 http://www.ifanr.com/124109 那个活动主要是分享创业经验以及产品的。当时恰好听了新点科技的吴晓丹说的一句话:提高App的响应速度。一个细节的地方在于给应用增加一个点击的反馈。

就是这句话触动了我,此前在做WebApp的时候一直遇到的问题就是响应度问题,首先WebApp存在http请求的话,而且要载数据是固然慢的,即使是制作Phonegap的应用,因为内嵌载UIWebview里面,性能也没有原生的Safari浏览器高,提高响应度是迫在眉睫的事情,因为用户都是急躁的。此前也有做过一个小小的代码总结,就是鼓励大家一定一定要用Touch事件来代替点击事件,尤其是在移动端的WebApp上,因为点击是有延迟的。我做的Touch事件的封装在此:https://gist.github.com/1750374 ,对此我们并没有在视觉上让用户感知。其实提高App响应度,在App的界面上提供点击反馈,这个早就有了,而这些细节往往是我们做WebApp的时候忽略掉的。因此我就做了一个小东西,也尝试了一下,方便自己日后使用吧。就是增加一个点击反馈的效果到页面中。其实就是用了一个a标签解决了。在做的过程中呢,也会出现一些小问题,希望大家日后在做开发的时候注意到:

1,onclick事件在移动端WebApp中是有延误的,不要用了。

2,onclick事件获取鼠标位置(也就是以前的浏览器中event.pageX或者pageY的对象在mobile safari中是undefined的),但是touch事件是有效的,具体怎么做,你可以看我代码。

3,此外,我尝试去使用zepto.js的时候,也发现其提供的tab事件,也是不能获取当前touch位置的,我不清楚其他的框架是否也如此。看来这些框架还有待进一步封装啊!

好了,这个就是我写的代码片段的地址:https://gist.github.com/3264126

这个就是截图:

Casual & Fellow

关于jQuery Mobile进行Page Transition时出现闪烁

Posted on 2012-08-02

在做项目的时候遇到此前没有遇到的事情,就是引入jQuery Mobile的时候出现了闪烁的情况。这个问题在我半年前处理其他项目的时候并不出现,而且最近大部分时间我都在用模拟器去调试,因此也不太察觉。不过既然问题出现了,那么就必须要解决,不要过夜。

具体问题呈现:

当我们使用茅点a,从页面A链接到页面B的时候,jQuery Mobile会自动地帮忙进行一次page transition的动画。默认情况下这个动画默认值是fade。问题就出现这里,在这个动画进行之前,页面会自动引入并闪烁,这个体验非常不好,而且很生硬。我们就要解决这个问题。

问题分析:

既然是页面转换,我们就要分析jQuery Mobile的页面且换机制的做法。一般情况下,目前的Web App的做法就是Single Page App。但是目前我们如果使用的是jQuery Mobile做程序的时候,好处就是希望多页面架构,而且可以帮助我们处理部分的动画效果。这样的好处就是每个View可以直接地在HTML文档下进行分离,方便了代码的管理,而且对于一个长线的应用来说,这样做的好处就是日后维护代码的时候可以更好地管理,而且做到了逻辑,界面渲染的分离。当然我也不反对Single Page App,但是对于一个SPA,在做代码的分离以及维护的时候都很辛苦。最终你喜欢哪个,就要看需求而订下来了。

扯远了,现在再回顾jQuery Mobile的页面引入机制。在多个页面内,进行页面切换,实质上jQuery Mobile也是在但一个页面内进行的。如果你打开浏览器的调试器,观察其HTML代码的变化,实质上在页面内引入了一个新的标签,并载入了新的页面的代码,并执行。对于旧的页面的代码实质上是终止了所有的js,并hide了下去。

按照这么说,我们就可以推断出,出现问题的地方就在于这个新的标签被过早地显示出来了。我们接下来要做的事情就是要防止这个标签被过早地显示出来。

解决问题:

为了解决这个问题呢,我们必须要利用到jQuery Mobile js 还有CSS文件,而且这两个文件必须是开发版本的(就是未压缩的),我们需要修改内部的代码尝试去解决这个问题。而实际上在下载这两个文件之前,我也去了Github,找到了jQuery Mobile的项目,并在内部找issue,而且也上了stackoverflow去看看有没有人遇到类似的问题。答案是有的!这里面我们可能会讨论到几个问题,希望大家不要嫌我说得啰嗦。

首先,我上去stackoverflow的时候,搜索了「jQuery Mobile page transition blinking」就會發先很多人遇到了同样的问题。听到的答案也有以下:

 

1,这个是jQuery Mobile的bug,早在以前的版奔上出现过(这个我此前没有发现,不太清楚)

2,修改css文件中ui-page的css代码,这个比较逼近问题根源。但是修改后无效。

3,这个是浏览器的问题。这个答案也比较逼近真相,因为这里发生了一件有趣的事情。一般我们做Web App的时候会尝试在浏览器中进行调试,而调试的过程当中,我们可能希望这个Web App展现得更加逼真,我们就希望其能够在HOME界面上登陆并展示出来。这样做了下来之后我们就发现一个有趣的事情,在浏览器中(也就是没有去掉底部的工具栏)时,Web App的页面转换非常,流畅,但是到了主屏幕中打开的时候,就会发现这个问题出现了。这里就涉及到苹果safari以及应用中Webview的运行机制了。出于安全因素的考虑,第三方开发者只可以用Nitro较早版本UIWebView作为其引擎,这就是iOS版本Chrome浏览器被迫使用较慢的引擎的原因。这里也导致了添加到主屏幕,或者在iPhone App中的WebView中浏览的时候,效率不够在纯浏览器中高。所以js处理机制上面也会出现一定的问题。

针对上面提出的几个答案,最后我是通过一些比较诡异的办法去解决这个诡异的问题的。最初的时候我是希望能够找到那段处理page transition的函数出来,然后通过修改函数的方式进行处理的。其实已经找到了这段函数,但是如果确实要修改的话,的确不那么快,因为这里涉及到几个比较重要的东西。而核心的代码是在2800行左右(因为里面的代码实在凌乱,而且jQuery Mobile的代码量实在庞大,改了一下,最终还是放弃了。)如果你有兴趣的话,你也可以上去参考一下的。

最终我实现的办法是:
<pre> 《body》 《div class="special_wrap"》 《div id="main_content"》《/div》 《/div》 《script type="text/javascript"》 $(".special_wrap").show(); var dis_spe = setTimeout("display_special_wrap()", 550); 《/script》 《/body》 </pre>
因为我阻止了其因为点击< a >标签后马上显示,做了一定的延时,因此在page transition中,只会有动画出现,而这个闪的诡异问题也即将消失。其实在这篇文章里面并没有说太多技术性,技巧性的东西。只是希望让大家去思考几个问题。

1,在Web App中,实现这些Page Transition的动画一直是个难点,当然这其中浏览器的性能也存在一个瓶颈,如果在当初设计的时候做好架构是一个经验以及技巧,大家可以分享一下大家的做法;
2,在开发过程当中,我们可以引用jQuery Mobile去解决这个问题,发现他太大的时候,我们可以在github上面抽出他的核心代码进行引入。当然如果我们希望更轻便的话,我们还可以使用这个小项目https://github.com/tpryan/CSS-Slide-Transition 不过至于体验,大家懂的。
3,Web App开发还有很长的一段路还走的。我认为在目前开发的过程中很多时候是摸着石头过河,大家都积累好经验吧,而且也只能够期待浏览器的瓶颈慢慢被突破!
4,此外,这片文章就是希望其中提及到的问题引导大家发散思维,想想Web App面临的更多问题。如果有建议,随时可以留言!

Casual & Fellow

UTF-8特殊符号集汇总

Posted on 2012-07-26
⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ⓠ ⓡ ⓢ ⓣ ⓤ ⓥ ⓦ ⓧ ⓨ ⓩ ⓪ ⓫ ⓬ ⓭ ⓮ ⓯ ⓰ ⓱ ⓲ ⓳ ⓴ ⓵ ⓶ ⓷ ⓸ ⓹ ⓺ ⓻ ⓼ ⓽ ⓾ ⓿ ─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿ ▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▐ ░ ▒ ▓ ▔ ▕ ▖ ▗ ▘ ▙ ▚ ▛ ▜ ▝ ▞ ▟ ■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯ ◰ ◱ ◲ ◳ ◴ ◵ ◶ ◷ ◸ ◹ ◺ ◻ ◼ ◽ ◾ ◿ ☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☔ ☕ ☖ ☗ ☘ ☙ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟ ♠ ♡ ♢ ♣ ♤ ♥ ♦ ♧ ♨ ♩ ⌠ ⌡ ⌢ ⌣⌆ ⌇ ⌈ ⌉ ⌊ ⌋ ∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ⊀ ⊁ ⊂ ⊃ ⊄ ⊅ ⊆ ⊇ ⊈ ⊉ ⊊ ⊋ ⊌ ⊍ ⊎ ⊏ ⊐ ⊑ ⊒ ⊓ ⊔ ⊕ ⊖ ⊗ ⊘ ⊙ ⊚ ⊛ ⊜ ⊝ ⊞ ⊟ ⊠ ⊡ ⊢ ⊣ ⊤ ⊥ ⊦ ⊧ ⊨ ⊩ ⊪ ⊫ ⊬ ⊭ ⊮ ⊯ ⊰ ⊱ ⊲ ⊳ ⊴ ⊵ ⊶ ⊷ ⊸ ⊹ ⊺ ⊻ ⊼ ⊽ ⊾ ⊿ ⋀ ⋁ ⋂ ⋃ ⋄ ⋅ ⋆ ⋇ ⋈ ⋉ ⋊ ⋋ ⋌ ⋍ ⋎ ⋏ ⋐ ⋑ ⋒ ⋓ ⋔ ⋕ ⋖ ⋗ ⋘ ⋙ ⋚ ⋛ ⋜ ⋝ ⋞ ⋟ ⋠ ⋡ ⋢ ⋣ ⋤ ⋥ ⋦ ⋧ ⋨ ⋩ ⋪ ⋫ ⋬ ⋭ ⋮ ⋯ ⋰ ⋱ ← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇅ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌ ⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇖ ⇗ ⇘ ⇙ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟ ⇠ ⇡ ⇢ ⇣ ⇤ ⇥ ⇦ ⇧ ⇨ ⇩ ⇪⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ ↀ ↁ ↂ℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ ₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫ € ₭ ₮ ₯ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎‐ ‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “ ” „ ‟ † ‡ • ‣ ․ ‥ … ‧ 

 ‪ ‫ ‬ ‭ ‮   ‰ ‱ ′ ″ ‴ ‵ ‶ ‷ ‸ ‹ › ※ ‼ ‽ ‾ ‿ ⁀ ⁁ ⁂ ⁃ ⁄ ⁅ ⁆                           ! " # $ % &amp; ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; &lt; = &gt; ? @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~  €  ‚ ƒ „ … † ‡ ˆ ‰ Š ‹ Œ Â Ž Â Â ‘ ’ “ ” • – — ˜ ™ š › œ  ž Ÿ ¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿
Casual & Fellow

关于Phonegap,存在跨域吗?

Posted on 2012-07-12

相信很多做Phonegap开发的朋友,都会遇到一个问题,那就是跨域。其实这个并不是一个问题,因为Phonegap本身不存在跨域,我也对这个概念模糊了很久。我一直以为Phonegap存在跨域问题,所以用了很多稀奇古怪的看法。其实一直都是错误的。那么这里到底是怎么引起的呢?又需要我们如何解决呢?好吧,我们一步一步来分析。

首先需求很明确,作为一个Web App就必须要实现局部刷新。那么就需要有Ajax来实现这个功能了。一般来说,地球人都会写简单的Ajax嘛,尤其是调用了jQuery后,就更加简单了。代码如下:

$.ajax({
url : “xxx.com”,
type : “POST”,
dataType: “json”,
data : REQUEST,
success : function (){
console.log(“success”):
}
});

好了,问题就来了。请求后发现浏览器报错,一看console,就发现原来是跨域问题引起的。好吧,跨域问题嘛,我用jsonp,或者是getScript的办法来解决不就好了。但是如果这里面涉及到一些敏感数据的传输,这就危险了,因为我们都知到jsonp或者getScript的f办法都是用GET的办法来传输数据的。那么我硬是用POST的办法来传,怎么办呢?

于是我们就开始查询Phonegap的文档了。找啊找,终于看到Phonegap wiki里面说: “The cross-domain security policy does not affect PhoneGap applications. Since the html files are called by webkit with the file:// protocol, the security policy does not apply.”

对啊!Phonegap本身就没有什么安全问题的限制,是允许跨域请求的啊。这里面到底是出了什么问题呢?于是一连串的调试就开始了。查了好多的文档,问了好多的人。到最后经过Jeff兄的帮忙,看到JQUERY MOBILE的一篇文章,提及到jQuery默认对跨域请求有一定的限制。于是就找到了代码:$.support.cors = true;

设定后,跑动Javascript代码,完事!原来这一切都是因为jQuery引起的。这个小问题困扰了我好几天。有时候再多的聪明也不能够弥补经验上面的缺失啊。所以平时还是要多多练手啊。由于这次的请求我是需要修改header的,所以也把header修改的demo代码在这里和大家分享一下吧。没有经验的朋友赶紧练手哦。

function makeRequest() {
$.support.cors = true;
var settings = {
type: “POST”,
url: URL,
data: REQUEST,
dataType: “json” ,
error: function(XHR,textStatus,errorThrown) {
alert(XHR);
alert(“textStatus: “ + textStatus);
alert(“errorThrown: “ + errorThrown);
//alert (“XHR=”+XHR+”\ntextStatus=”+textStatus+”\nerrorThrown=” + errorThrown);
},
success: function(data) {
//alert(“ok啦”);
//$(“body”).append(data);
alert(JSON.stringify(data));
alert(data.status);
alert(data.message);
},
headers: {
“Access-Control-Allow-Origin” : “xxx.com”,
“Access-Control-Allow-Headers” : “X-Requested-With”,
“X-CASH” : “xxx”,
“X-Lee” : “xxx”,
“X-HELLO” : “xxx”,
“X-WORLD” : “xxx”,
}
};
$.ajax(settings);
}
//执行请求
makeRequest();

这个问题我此前一直有误解。所以在此向看过我PPT分享的朋友说声对不起。大家日后在使用JS库的时候,要看看一些库的默认属性,看看会不会影响到API的调用。不然这会盲目地浪费好多时间在无谓的事情上面。希望大家引以为鉴,我也会好好复习jQuery的。而且Phonegap是一个很强大的框架,可惜的是国内的开发者难以集中起来,出了问题不太好解决,我一般都是上stackoverflow上面咨询的。希望国内的开发者能够踊跃地聚集起来,让这个好的开发工具发扬光大吧。

刚刚提及到安全问题,借此我也说说Phonegap在面对这个问题的时候可能会出现的情况。刚刚解决了跨域问题(实质上并没有跨域,也就是说这样传输数据是安全的),但是不代表没有了安全问题。因为这些应用的逻辑是在JS中实现的,那么核心的代码也会在JS中。这有什么问题呢?问题就在这里了,一般ipa(以ios应用为例),如果被不法分子下载后,反编译去获取ipa文件的代码,可能就可以将js文件重新解析出来。这时候,安全的key等东西就可能会被获取。这个时候一般有几个解决办法:

1,混合到obj-c的代码中(虽然听起来有点高级,不过是可以实现的,这里补充一句,学习obj-c对phonegap开发有莫大的好处);

2,利用一些压缩的技术,混合到一些png文件中,这就好像此前有人压缩js代码一样,混合进取;

3,自己实现一套比较好的加密机制;

4,对代码进行加密,混淆,尽最大限度地不让竞争对手或者是不法分子难以破解。

好的,大概经验就分享到这里了。我遇到问题的时候还会在线上进行提问的。希望大家能够多多交流!:-)

Casual & Fellow

再次曲线救国-调用SAE临时文件

Posted on 2012-06-19

最近在实用腾讯微博开放平台的sdk(2.0版本)搞一些小玩意。使用到腾讯微博的更新头像Api user/update_head 更新用户头像。

在sdk当中,调用的方法其实是非常简单的。

只是需要:

$multi = array(‘pic’ => ‘images/test.jpg’);
$r1 = Tencent::api(‘user/update_head’, $params, ‘POST’, $multi);

这样我们就可以利用php,实现更新头像的动作了。不过如果我的图片很多,而且是动态生成的,那么这就使得图片并不是固定的,那么我们应该怎么处理呢?刚刚开始的时候我也走了很多的弯路。下面直接告诉大家路怎么走就好了。

首先我们来分析一下这句代码:

Tencent::api(‘user/update_head’, $params , ‘POST’ , $multi );

在api函数里面,有四个参数:1,调用的api的接口;2,调用api的参数,在腾讯微博开放平台发布出来的2.0版本sdk中,这里的参数已经封装好,无须用户再次去处理填写,在1.0的版本当中,用户需要自己获取上传文件的base64数据,并post才可以,而2.0中都已经封装好了;3,就是请求的方式啦,这个没有什么好说的;4,最后一个就是post文件的本地路径了(注意,这里就是指路径);

好了,问题来了,SAE上面,Memcache以及Storage服务缓存下来的文件都不是本地路径当中的,因为根据SAE的调用方法,Memcache以及Storage调用的东西都分别在saemc://或者saestor://作为路径前缀进行调用。而这样调用的话无法获取本地路径。

最后我使用了tmpfile()的函数,把动态的图片文件生成出来后先把数据缓存到一个本地文件。然后找到这个文件的本地路径再post出去。

通过echo SAE_TMP_PATH;输出SAE的缓存文件路径,发现是:

sys tmp file path

/saetmp/619/[yourdomain]/1340077764_3893208519

命名规则:/saetmp/日期/domain名字/time()_* (未知)

通过echo FILE; 找到这个php脚本SAE的文件路径。

最后POST的时候使用一堆的路径查找符号,找到缓存图片。

如:$multi = array(‘pic’ => ‘../../../../../..’.SAE_TMP_PATH.’/test.jpg’);

问题解决 :-)

123
Cash

Cash

I would like now to seriously indifferent room of wonderful.

22 posts
1 categories
6 tags
© 2016 Cash
Powered by Hexo
Theme - NexT.Muse