KnockoutJsの$root,$parent(s)とは?
Knockoutjsの$root(あるいは$parent(s))とは?
knockout.jsのチュートリアル(
learn.knockoutjs.com
)やってて途中から急に$root(あるいは$parent(s))って変数が出てくるようになって、なんやねん( ´_ゝ`)と思ったので共有。
View側
<table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Surcharge</th><th></th> </tr></thead> <!-- Todo: Generate table body --> <tbody data-bind="foreach: seats"> <tr> <td><input data-bind="value: name" /></td> <td><select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'"></select></td> <td data-bind="text: formattedPrice"></td> <td><a href="#" data-bind="click: $root.removeSeat">Remove</a></td> </tr> </tbody> </table>
ViewModel側
// Class to represent a row in the seat reservations grid function SeatReservation(name, initialMeal) { var self = this; self.name = name; self.meal = ko.observable(initialMeal); self.formattedPrice = ko.computed(function() { var price = self.meal().price; return price ? "$" + price.toFixed(2) : "None"; }); } // Overall viewmodel for this screen, along with initial state function ReservationsViewModel() { var self = this; // Non-editable catalog data - would come from the server self.availableMeals = [ { mealName: "Standard (sandwich)", price: 0 }, { mealName: "Premium (lobster)", price: 34.95 }, { mealName: "Ultimate (whole zebra)", price: 290 } ]; // Editable data self.seats = ko.observableArray([ new SeatReservation("Steve", self.availableMeals[0]), new SeatReservation("Bert", self.availableMeals[0]) ]);
この中の↓ここ
<select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'">
なんでmealに関しては value: mealでできてるのに、availableMealsはoption: $root.availableMealsみたいに$rootつけなきゃいけないねん( ´_ゝ`)( ´_ゝ`)( ´_ゝ`)
チュートリアルに$rootの説明っぽいの
Note that the $root. prefix causes Knockout to look for a removeSeat handler on your top-level viewmodel instead of on the SeatReservation instance being bound --- that's a more convenient place to put removeSeat in this example. So, add a corresponding removeSeat function to your root viewmodel class, ReservationsViewModel:
あったけど、如何せんEnglishでピンと来ない(・◡ु‹ ) ✧*テヘペロ
ってわけで色々調べて、結局先輩に聞いて解決笑
要は変数のスコープ的な問題らしい。
<select data-bind="options: $root.availableMeals, value: meal, optionsText: 'mealName'">
↑を使ってるときって
<tbody data-bind="foreach: seats">
内なのでforeachの中に居る状態なので、seatsの中にある変数については meal のような形で使えるけど、それよりも上の階層の変数を参照する場合、ViewModelのルートの変数なら$root.hoge、一個上の階層の変数なら$parents[0].hoge($parent.hogeでも可)、2個上の階層なら$parents[1].hoge…というように書いていく必要があるらしい。
ふむ、なるほど。