2017-12-27 153 views
1

考慮下面的代碼:在JavaScript編寫C#的擴展淘汰賽可觀察

if (countriesLookup()) { 
    countriesLookup().fill(initialData.Countries); 
} else { 
    const subscription = countriesLookup.subscribe(function (lookup) { 
     lookup.fill(initialData.Countries); 
     subscription.dispose(); 
    }); 
} 

在這裏,我有一個ko.observable countriesLookup。如果在數據初始化的時候,組件本身還沒有初始化(countriesLookup() == undefined),我訂閱了這個observable,當它最終獲得組件時,我使用初始數據執行初始化並擺脫訂閱。

讓我們暫時忘記這種方法導致回調地獄等等,並考慮可能的方法來使這個不那麼醜陋。

我想寫的東西,如C#擴展可觀察到的,將是這樣的使用:

countriesLookup.initialize(x => x.fill(initialData.Countries)); 

及實施設像她那樣:

ko.observable.prototype.initialize = function(initializeFunc) { 
    const currentValue = ??? 
    if (currentValue()) { 
     initializeFunc(currentValue()); 
    } else { 
     const subscription = currentValue.subscribe(function (lookup) { 
      initializeFunc(lookup); 
      subscription.dispose(); 
     }); 
    } 
} 

顯然,這不工作,尤其是因爲我不確定是否有可能在「擴展」方法內獲得可觀察值的當前值。

我目前正在思考C#編程方面的問題,在這方面我有點熟練,並且非常希望能夠寫出如何擴展的一些建議。


也許我應該多解釋我的問題。我知道當前值可以在原型中添加方法this中檢索,但問題在於observable返回一個函數。

例如,這

String.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 
"blah".SayHi();  //return "Hi blah!" 

作品就好了,但這

ko.observable.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 
var a = ko.observable("blah") 
a.SayHi(); 

失敗,出現以下錯誤:

VM543:1 Uncaught TypeError: a.SayHi is not a function at <anonymous>:1:3

我希望它增加了一些澄清。

回答

2

如果我明白了你的觀點,你的目標是爲觀察者添加一個自定義函數。
在這種情況下,您應該使用fn而不是prototype
看看這個鏈接:http://knockoutjs.com/documentation/fn.html

I am not sure if this is possible to get the current value of observable inside the "extension" method

,你可以得到使用這種方法,您觀察到的電流值,因此您上面的例子是非常接近你想要什麼。

ko.observable.fn.initialize = function(initializeFunc) { 
 
    const currentValue = this; 
 
    if (currentValue()) { 
 
    initializeFunc(currentValue()); 
 
    } else { 
 
    const subscription = currentValue.subscribe(function(lookup) { 
 
     initializeFunc(lookup); 
 
     subscription.dispose(); 
 
    }); 
 
    } 
 
    return this; 
 
} 
 

 
var ViewModel = function() { 
 
    this.data = ko.observable().initialize(x => console.log("Value changed to: " + x)); 
 
    this.data("100"); 
 
}; 
 

 
ko.applyBindings(new ViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

================================
注意:有一個關於爲什麼使用fn而不是prototype的討論,有人指出,出於某些性能原因,最好使用extenders
請閱讀這裏:https://github.com/knockout/knockout/issues/979

+0

偉大的工作,阿德里安!非常感謝你! –

+0

不客氣! – Adrian