Knockoutで、動的イメージソース

Knockout.jsでimgタグsrc属性にデータバインドする時のアンチパターン http://qiita.com/trapple/items/5f566784364087b82428

by MKGaru

HTML

<script src="http://knockoutjs.com/downloads/knockout-3.2.0.js"></script>
<script src="http://mbest.github.io/knockout.punches/knockout.punches.min.js"></script>
<!-- パターン1 : 3項演算子 -->
<img data-bind="attr:{src:resource()?'http://lorempixel.com/'+resource():''}"/>


<!-- パターン2:親でifガード-->
<div data-bind="if:resource()">
    <img data-bind="attr:{src:'http://lorempixel.com/'+resource()}"/>
</div>

<!-- パターン3: 適当に自作バインディング -->
<img data-bind="src:['http://lorempixel.com/',resource]"/>

<!-- ↓Punchesがつかえるなら↓ -->
<!-- パターン4 -->
<div data-bind="if:resource()">
    <img data-bind="attr.src:'http://lorempixel.com/'+resource()"/>
</div>

<!-- アンチパターン --><!-- コレはダメ
<div data-bind="if:resource()">
    <img src="http://lorempixel.com/{{resource}}"/>
</div>
-->

JavaScript

function VM(){
    var vm = this;
    this.resource = ko.observable();
    setTimeout(function(){
        vm.resource("400/200");
    },1000);
    
    setTimeout(function(){
        vm.resource("400/180");
    },3000);
}

ko.bindingHandlers['src']= {
    update: function(element, valueAccessor, allBindings, viewModel, bindingContext) {
        var src = valueAccessor().map(function(item){return ko.unwrap(item)});
        if(src.indexOf(undefined)==-1){
            element.setAttribute('src',src.join(''));
        }
    }
}

ko.punches.enableAll();
ko.applyBindings(new VM());