Title: Coffee script & Javascript organize
Tags: coffeescript,javascript
Slug: coffeescript
Excerpt: rails coffee script
Date: 2012-09-25
CofeeScript & JavaScript Organize
我需要解决以下问题,相信其它朋友也会碰到,这是我翻查的结果,结论已经在我的项目用了,感觉不错,分享一下。原博文在 http://scriptogr.am/mafai/post/coffeescript
Target
- 所有js compile在一个js,不论是否需要
- 不同页面需要运行的js才运行,不需要的不运行
Solution 1
init不同namespace的js
application.html.erb
这段不能用coffee script,原因是动态call init的方法
可以再细分按action name或用正则表达式
:javascript $(function() { #{"Window.#{params[:controller]}"}.init(); });
转换成的代码,当在访问 /apples
Window.apples.init()
对应的 apples.js.coffee
,like
只是为了demo,可以用ujs代替
Window.apples = like: (id) -> console.log("like apple:" + id) return init: () -> console.log("init apple") $(".apple").click () -> console.log("click me") console.log( $(this).attr("id") ) Window.apples.like($(this).attr("id")) return return
oranges.js.coffee
oranges = init: () -> console.log("init orange") return eat: (id) -> console.log("eat orange:" + id) return
当访问 /apples
时,只会init apples的js,如果是/oranges
,则只会init orange js
Solution 2
方案1的变形,不过组织起来更舒服一占o,与方法1差不多
common.js.coffee
将 apples, oranges
等作为namespace
Window.FruitsSite = common: init: () -> console.log("init common") apples: init: ()-> console.log("init apples") like: (id) -> console.log("like apple id: " + id) oranges: init: () -> console.log("init oranges") eat: (id) -> console.log("eat orange id: " + id)
application.haml
动态按controller名去调用
Window.FruitsSite["#{params[:controller]}"].init();
Solution 3
方案2的变形,将需要用到的 js 类放到 body中,同时细分到不同action页面级别
<body data-controller="apples" data-action="index"">
找出对应 apples 的 index 页面需要init的东西init一下
或
<body data-js="apples autoscroll">
Iint apples 和 autoscroll
查找一下data-js
,然后找出对应的模块init
一下就好
例子
apples.js.coffee
Window.FruitsSite = apples: index: init: () -> console.log("init apples index page") return
applicatoin.haml
其实就是多一个层级而已,另外就是可以将这下面这段代码转成coffee script,不用像上面两个例子写一些恶心js在页面上
var $body = $("body"); var controller = $body.attr("data-controller"); var action = $body.attr("data-action"); Window.FruitsSite[controller][action].init();
Solution 4
重写 jquery ready方法,利用body class 调用对应的ready
重写jquery ready方法,看不明proxy的那个方法,不过没关系
这段代码来自于 https://github.com/Verba/jquery-readyselector/blob/master/jquery.readyselector.js
(function ($) { console.log("try to reset the ready function"); var ready = $.fn.ready; $.fn.ready = function (fn) { console.log(this); console.log("Context:" + this.context); console.log(this.context); if (this.context === undefined) { console.log("no context defined"); // The $().ready(fn) case. ready(fn); } else if (this.selector) { console.log("Selector:" + this.selector); ready($.proxy(function(){ $(this.selector, this.context).each(fn); }, this)); } else { console.log("Context have but no selector"); ready($.proxy(function(){ $(this).each(fn); }, this)); } } })(jQuery);
写不同的ready函数
$('.apples.index').ready(function () { console.log("apple index page init"); }); $('.oranges.index').ready(function(){ console.log("oranges index page init"); });
ready这个方法就可有可无了
$(function() { });
body中的class一定要以空间分隔
%body{:class => "#{params[:controller]} #{params[:action]}"}
附
其它的方法还有
用条件语句去控制,只是不那么高明
$(body).hasClass("autoscroll")
只当需要时才new instance
Window.FruitsSite.apples = new Apples;
只能先实例化
创建实例
class Apples index: init: () -> console.log("init apples index page") return console.log(window.FruitsSite) window.FruitsSite.apples = new Apples
简版
window.FruitsSite.apples = index: init: () -> console.log("init apples index page") return console.log(window.FruitsSite)
CoffeeScript 整合 vim
到 node.js 下载一下pkg(Mac)
装完后
sudo npm install -g coffee-scriptmkdir -p ~/.vim/autoload ~/.vim/bundle
curl 'www.vim.org/scripts/download_script.
发表回复