2012-06-04 7 views
5

私はknockout.jsをクローズアップでラップしようとしていますが、それは非常に難しいことです。私が持っている問題は、 'this'変数への参照です。私はあきらめて、ただjavascriptを直接使うことを考えています。clojurescriptを使ってknockout.jsをラップする

私はいくつかのマクロで簡単に機能をラップするために管理してきましたhttp://knockoutjs.com/examples/helloWorld.htmlhttp://knockoutjs.com/examples/contactsEditor.html

オフの例を撮影しました。たとえば:

var ViewModel = function() { 
    this.firstName = ko.observable("Bert"); 
    this.lastName = ko.observable("Bertington"); 

    this.fullName = ko.computed(function() { 
     // Knockout tracks dependencies automatically. It knows that fullName depends on firstName and lastName, because these get called when evaluating fullName. 
     return this.firstName() + " " + this.lastName(); 
    }, this); 
}; 

は次のようになります。

(defviewmodel data 
    (observing :first_name "Bert") 
    (observing :last_name "Bertington") 
    (computing :name [:first_name :last_name] 
    (str :first_name " " :last_name))) 

しかし、困難のようなもののために:

var BetterListModel = function() { 
    this.itemToAdd = ko.observable(""); 
    this.allItems = ko.observableArray(["Fries", "Eggs Benedict", "Ham", "Cheese"]); // Initial items 
    this.selectedItems = ko.observableArray(["Ham"]);        // Initial selection 

    this.addItem = function() { 
     if ((this.itemToAdd() != "") && (this.allItems.indexOf(this.itemToAdd()) < 0)) // Prevent blanks and duplicates 
      this.allItems.push(this.itemToAdd()); 
     this.itemToAdd(""); // Clear the text box 
    }; 

    this.removeSelected = function() { 
     this.allItems.removeAll(this.selectedItems()); 
     this.selectedItems([]); // Clear selection 
    }; 

    this.sortItems = function() { 
     this.allItems.sort(); 
    }; 
}; 

ko.applyBindings(new BetterListModel()); 

私はこのようなコードを一致させるclojurescriptに何ができるかわかりません。 this.allItems.push(this.itemToAdd())

あなたのJavaScriptのthis動的バインディングを明示的に参照する必要がある場合

+0

Keming Labsで内部的に使用していたKnockout.jsに似たCompute-Observablesライブラリの提供を1か月間続けていただければ幸いです。私のGithub(@lynaghk)を見守ってください。 –

+0

ありがとうKevin!私は本当に図書館で遊ぶのを楽しみにしています。しかし、クローズされていない他の内部変数にアクセスする変数を宣言するのと同様のタイプの問題を持つあまりにも多くの素晴らしいjavascriptライブラリがあります。私は、jsとcljの間を補間する明確な方法を持つことが重要であると感じています。 clojurescript ande javascriptで遊ぶほど、良いjsライブラリは淡々としています... clojureを学んだ後、私は接続を見ただけです。とにかく、私の答えにあなたのコメントを得ることを望む – zcaudate

+0

http://fluentsoftware.github.com/cljs-binding/を見て、ノックアウトとして成熟していないが、.. – edtsech

答えて

5

、私はとclojurescriptのための同じ構造を持っている方法を考え出しましたJavaScriptのために。

this-asマクロは、いくつかの特異性を持っており、唯一の方法は、例えば、クラス

に置かれたとき、私はJavaScriptでこのようなものを作りたい作品:

var anobj = {a: 9, 
      get_a: function(){return this.a;}}; 

私がする必要があります

(def anobj (js-obj)) 
(def get_a (fn [] (this-as me (.-a me)))) 
(aset anobj "a" 9) 
(aset anobj "get_a" get_a) 

clojのように美しい言語のため真剣に醜いです:clojurescriptで同じオブジェクトを取得するために全体の多くのコーディングを行いますure。ノックアウトで起こるように、お互いにリンクする機能を持っていると状況が悪化します。

多くのthisがあるjsオブジェクトを作成する最良の方法は、__init__メソッドを定義し、それをクラスに追加して実行してからクラスから削除することです。例えば、私は別のオブジェクトにしたかったとしますとclojurescriptとして書か

var avobj = {a: this, 
      b: 98, 
      c: this.a 
      get_a: function(){return str(this.a) + str(this.c);}}; 

をして__init__方法は次のようになります。

(def avobj (js-obj)) 
(def av__init__ 
    #(this-as this 
     (aset this "a" this) 
     (aset this "b" 9) 
     (aset this "c" (.-a this)) 
     (aset this "get_a" (fn [] (str (.-a this) (.-c this)))))) 
(aset avobj "__init__" av__init__) 
(. avobj __init__) 
(js-delete stuff "__init__") 

ジャバスクリプトよりも全体の束より多くのコードがまだあります...しかし、最も重要なことは、javascriptと同じオブジェクトを取得することです。このフォームを使用してすべての変数を設定すると、マクロを使用して単純化することもできます。だから私はマクロを定義した:

(defmacro defvar [name & body] 
    (list 'do 
    (list 'def name 
     (list 'map->js 
     { 
      :__init__ 
      (list 'fn [] 
       (list 'this-as 'this 
       (list 'aset 'this "a" "blah")))   
     })) 
    ;(. js/console log ~name) 
    (list '. name '__init__) 
    (list 'js-delete name "__init__"))) 

とjayqから取られたmap-> js。utilsの:

(defn map->js [m] 
    (let [out (js-obj)] 
    (doseq [[k v] m] 
     (aset out (name k) v)) 
    out)) 

今私は、このようなコードを書くことができます。

(defvar avobj 
    a this 
    b 9 
    c (.-a this) 
    get_a (fn [] (str (.-a this) (.-c this)))) 

とノックアウトへの答えのために:

それは本当によくJavaScriptを一致するよう、私にとっては本当にいいです
(defvar name_model 
    first_name (observable "My") 
    last_name (observable "Name") 
    name (computed (fn [] (str (. this first_name) " " (. this last_name))))) 

(. js/ko (applyBindings name_model)); 

その完全に読みやすい!

関連する問題