标签归档:JS

knockout在不同ViewModel之间的通讯

构建复杂应用,view-model之间的通讯是非常重要的一个环节,此过程的方便与否,组件之间的严格隔离与否,直接影响健壮性和开发禅道心情。

本文会:

  1. 介绍knockout.js自带的事件收发;
  2. 一个简单扩展实现 ViewModel之间 数据同步(或者叫数据捆绑);

 一:Knockout的事件收发

抽象的理解:建立一个公开的无线电塔,任何viewmodel可以在某个频道广播信息,其他正在收听的viewmodel,只要频道对的上,那么就能收听到对应信息

var radioTower = new ko.subscribable(); //创建一个无线电塔

收听者用法:

 //三个参数依次为收到的信息callback、目标viewModel(可选)、频道名称(可选)
radioTower.subscribe(callback, target, channel);
//收听者的俩个例子
radioTower.subscribe(function(newValue) { this.latestTopic(newValue);}, vm, "mytopic");
radioTower.subscribe(function(newData) {
    console.log("收到新数据:",newData);
}, null, "changeLength");

发送者的用法:

//两个参数依次为想发送的数据、频道名称
radioTower.notifySubscribers(data, channel);
//真实的例子
//接收者
radioTower.subscribe(function(newValue) {
    this.latestTopic(newValue);
}, vm, "mytopic");
//发送者
radioTower.notifySubscribers("MayDay MayDay!", "changeLength");

二:一个小扩展来更方便的实现数据同步

扩展代码:

;(function(ko){
    var radioTower = new ko.subscribable();

    ko.subscribable.fn.pub = function(topic) {
        this.subscribe(function(newValue) {
            radioTower.notifySubscribers(newValue, topic);
        });
        return this; //support chaining
    };
    ko.subscribable.fn.sub = function(topic,call,vm) {
        var target = vm || null;
        var cb = call || this; //如果没有call,那么直接捆绑原始数据
        radioTower.subscribe(cb, target, topic);

        return this;  //support chaining
    };
})(ko);

用法:

viewModel-A中:
//监听数组,当数组变化时在“ulist”频道里发送list这个数据
this.list = ko.observableArray([]).pub("ulist");
viewModel-B中:
this.list2 = ko.observableArray([]);
this.list2.sub("ulist"); //收听"ulist",当viewModel-A中的list改变时,它也会跟着变

//如果不想直接绑定,比如这里实现viewModel-A中的ulist的长度 和 viewModel-B中的length同步:
self.length = ko.observable(0);
self.length.sub("ulist",function(val){
    self.length(val.length);
});//第二个可选参数为回调

源代码例子

WebStorm里配置Browserify自动编译

Browserify Logo

Browserify

Browserify是个好东西,相比requireJS seaJS 他配合Script的async属性去实现“模块化、异步、非阻塞”可以说是“Drop Dead Simple”,简单高效又直接。自从他添加了sourcemap功能后,chrome里调试起来简直如鱼得水,越发喜欢了。

但是它本身是一个Compiler,不是一个JS框架。每次修改模块都需要重新执行一次browserify命令,相当麻烦。

我这里来介绍下WebStorm里的配置,以让Browserify自动化。
继续阅读

就是现在,用Promise取代callback吧!

Callback-Hell
什么是callback hell?
答:(如上图)过多的,过深的callbacks导致代码丑陋,难以阅读和维护。

window.Promise兼容不好吧?
答:这篇文章就是教你如何想Promise就Promise想callback就callback,还有去兼容浏览器的Promise的polyfill

ES6里的Promise让JS变得更加优雅。那么现在我们怎么把原有的代码转变成Promise Style呢?

原有代码(Callback Style):

    var waitCon = function(time,callback){
        //这里可以做很多工作的代码,先用延迟来代替
        var result=1+1;
        setTimeout(function(){
            if(callback){
                callback(result);
            }
        },time);
    };

原有代码(Callback Style)-调用方法:

    waitCon(2000,function(res){
        console.log(res); //两秒后得出2这个结果
    });

改写成Promise Style:

    var waitCon = function(time){
        return new Promise(function(resolve,reject){
            var result=1+1;
            setTimeout(function(){
                resolve(result);
                //成功完成,传出结果。如果用reject则是完成失败,传出错误内容
            },time);
        });
    };

Promise Style的调用方法:

    waitCon(2000).then(function(result){
       //原本callback里的内容
       console.log(result);
    });//可读性很高:先执行XXX,然后XXX

还可以Promise链、多重Promise具体查看 http://www.html5rocks.com/zh/tutorials/es6/promises/
这里只谈最简单的异步callback升级换代。

这里送出一个callback+Promise的整合版,想用什么用什么,妈妈再也不用担心其他小朋友不会用婆迷丝了。

    var waitCon=function(time,callback){
        return new Promise(function(resolve,reject){
            var result=1+1;
            setTimeout(function(){
                if(typeof callback === "function"){callback(result);}//执行callback
                resolve(result);//成功完成,传出结果
            },time);
        });
    };

AngularJS兼容IE的处理(官方文档不全面)

AngularJS
最近在学些AngularJS,感觉挺强大的。
但是如果想投入到生产环境中,还需要考虑到IE6,7的兼容问题。

官方文档提到如何兼容IE了,但是即使全部按照文档里说的做,其实还是不能做到在IE6,7下运行。

经过各种实践,在这里给出一个补充:
需要在html标签上添加id=”ng-app”和class=”ng-app:APPNAME”,于是一个标准的ng-app的标签应该是:(app名为myapp为例)

##注意下面的“HTMLTAG”必须是合法的html标签,永远不要使用自定义标签(ng-view改成<div ng-view>),否则依然不兼容IE
<html xmlns:ng="http://angularjs.org">
......
<HTMLTAG ng-app="myapp" class="ng-app:myapp" id="ng-app">
   ....
</HTMLTAG>
.....
</html>

这样就行了,以上是唯一的和官网说明不同的地方.

另附官网文档所说的让IE兼容JSON2和HTML5标签的JS在这,直接引用进head标签里就行了里就行了(这两个JS也是必要的)

<script src="http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.2pre/html5shiv.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/json2/20121008/json2.js"></script>

随便做了一个demo,兼容IE67:
http://tools.regou.me/angularJS.html

2013.6.22更新
目前我在正式的生产环境中,用AngularJS+jQueryMobile+PhoneGap在做一个B2B商城APP
分享了点AngularJS用户手机APP开发的心得:
blog.regou.me/?p=790

2013.12.16更新
我看了下,官方文档已经做好了补充,现在可以完全以官网文档为准了。
AngularJS 1.3.0开始,将不再支持IE8和IE8以下的浏览器,所以,别再挣扎了

JS/PHP添加Do Not Track(DNT),保护访客隐私

大多数的网络浏览器的设置中有一个“Do Not Track”(DNT 即“不追踪”)设定,让用户能够控制自己的隐私信息被追踪的情况。
但是网站到底是否真的不追踪,还要看网站本身是否响应它
那么,做一个善良的网站,如果用户设置了Do Not Track,那么就保护一下他的隐私吧!

下面这个为JavaScript的代码,如果 navigator.doNotTrack 等于1,那么用户就开启了DNT,不要去运行那些搜集用户信息的脚本了!

if(!navigator.doNotTrack){
  //这里面写搜集信息的脚本,如果开启DNT则不执行
}

这个为PHP的,通过判断HTTP Header “HTTP_DNT”的值是否为”1″来判定是否开启了DNT:

function get_dnt() {
  // returns TRUE if DNT is on and is equal to 1
  return (isset($_SERVER['HTTP_DNT']) && $_SERVER['HTTP_DNT'] == 1);
  $DoNotTrackHeader = "DNT";
  $DoNotTrackValue = "1";

  $phpHeader = "HTTP_" . strtoupper(str_replace("-", "_", $DoNotTrackHeader));
  return (array_key_exists($phpHeader, $_SERVER)) and ($_SERVER[$phpHeader] == $DoNotTrackValue)
}

同理,nodejs的:

var dnt=function(){
  return (headers['HTTP_DNT']==1)
}

HTML5视频的多平台兼容方案 JW Player

JW Player通过配置可以在不支持HTML5浏览器的情况下,自动的将HTML5视频转化为Flash视频
同时也支持m3m8、flv等流媒体播放。具体参见 http://www.longtailvideo.com/players/

DEMO预览点这里

配置起来很简单,先在引JS

<script src='jwplayer.js'></script>

再在想放视频的地方放下如下代码就行了,上面面那个demo是我希望优先用html5播放,再其次用Flash播放

<video id='mediaplayer' ></video>
<script type="text/javascript">
    jwplayer('mediaplayer').setup({
        'id': 'playerID',
        'width':1280,
        'height':720,
        levels: [
            {file: 'Using2-stepverification.mp4',type: 'video/mp4' },//mp4文件提供给Flash
            {file: 'Using2-stepverification.webm', type: 'video/webm' },//webm文件提供给HTML5
        ],
        'modes': [
            {type: 'html5'},//优先级1,以下类推
            {type: 'flash', src: 'player.swf'},
            {type: 'download'}
        ]
    });
</script>

推荐用JSON来写对象工厂方法

推荐用JSON来写工厂方法(Factory Method),本人特别喜欢使用JSON的格式,主要原因是条理清晰,整体感强。
推荐用JSON写工厂方法,很好理解,新建对象,然后返回就行了。可读性非常强,推荐下
下面这个例子是用工厂的方法定义两个”角色”对象

var wordspace=document.getElementById("spotlight");
var Character={
    crate:function(name,lv,exsist){ //传了3个值
        var newobj={
            name:name,
            lv:lv,
            exsist:exsist||false,
            spotlight:function(){
                wordspace.innerHTML+='Name: '+this.name+' Level: '+this.lv+' Exsist: '+this.exsist;
            },
            destroy:function(){
                wordspace.innerHTML+='Name: '+this.name+' is Gone!!';
                return null;
            }
        };
        return newobj;
    }
};
var Character1=Character.crate('Vurtne', '23'); //创件角色对象,可读性比常规工厂方法强
var Character2=Character.crate('DrakeDog', '85', true);
Character1.spotlight();
console.log(Character1);
//断开引用,好让环境自动释放内存
Character1=Character1.destroy();
console.log(Character1);

参考资料

发布 WordPress手机版 WordPress Mobile Reader

这是一个WordPress的手机版阅读器,用Ajax去请求博客的RSS XML内容
纯粹前端,没用用到PHP
由于Ajax限制,它必须和博客同域名(跨域名解决方案看底部更新)

托管在Google,使用方法、Wiki页面、问题、BUG里面很全了,

大家也可以在此文章下面评论也可以在项目页里评论

Host by GoogleCode : http://code.google.com/p/wpmr/

Demo: https://blog.regou.me/m/

—————8月30日跟新跨域名解决方案————
可以配置 .htaccess 文件,来允许Cross-origin resource sharing,从而跨域名阅读博客,甚至无需空间直接在下到本地阅读博客

相关文章:http://dev.opera.com/articles/view/dom-access-control-using-cross-origin-resource-sharing/#SettingResponseHeaders
只需要在博客域名下的.htaccess里添加这么一行就可以让任意域对其进行XHR请求

Header set Access-Control-Allow-Origin *

要注意,IE10以下浏览器或过低版本的Firefox Opera Safari不支持此功能

谷歌今日的首页能弹奏,那么,我就来一曲

谷歌今天的首页,是电吉他之父莱斯·保罗 96 周年诞辰

如果你晚于今天看到这篇文章,点这里试试: http://www.pomocode.com/google-guitar/

google

把那个键盘的东西点一下,再按键盘就行了(你可能需要Chrome Opera FF等浏览器才能听到声音)

鼠标也可以弹,但你不是上帝之手….你APM没到1万…

不是用Flash做的,好强大的js求指导…

————————————————————————————————————————————————

以下作曲(自己试试什么歌):

12311231345345

3~5656 6698767 79065 997990

EERT TREW QQWE EWW EERT TREW QQWE WQQ

pouyt uytew wewetyuop ppouyty