我想从可观察数组中为元素设置动画。
我没有在observableArray中添加或删除项目。
考虑到以下jsfiddle,我想调用animateFirstElement函数并突出显示行星' Mercury'
我可以很容易地得到这个项目。但我不知道如何获得相应的HTML元素:
this.animateFirstElement = function() {
alert(this.planets()[0].name);
};
答案 0 :(得分:1)
我会在评论中说出@CrimsonChris所说的内容,尽管这两种方式都相当简单。默认情况下,Knockout将参数data, event
传递给视图上的任何绑定。因此,例如,如果您想在用户点击它时突出显示行星,您可以执行以下操作:
<div data-bind="attr: { 'class': 'planet ' + type },
text: name,
click: highlightElement"> </div>
在highlightElement
:
function highlightElement(data, e) {
var target = e.target || e.srcElement;
myHighlightFunction(target);
}
如果你想从父上下文触发动作,你可以坚持下去。容器的id
属性,例如planet-list
,以及在Knockout之外使用jQuery添加/删除动画,例如:
this.removeFirstElement = function() {
var target = document.getElementById('planet-list'),
planet = target.children[0];
$(planet).slideUp(400,function() { self.planets.shift(); });
};
您也可以在敲除中执行此操作,例如通过构建controls descendant bindings的自定义绑定,或者当阵列变小时您可以使用planetsToShow.subscribe
进行相应的动画处理/更大。请注意,在视图中,您可以将$element
完美地传递给函数,或$index
(如下面的测试中所示)
我对你的小提琴进行了一些修改,请查看:http://jsfiddle.net/8k8V5/2652/
答案 1 :(得分:1)
关键是不要对抗淘汰赛。您的viewmodel永远不需要知道用于呈现它的HTML元素。
如果要影响项目的可见性,请在viewmodel上引入visible
属性,并使您的视图对此属性中的更改做出反应。如有必要,创建处理动画本身的自定义绑定 - 我在下面创建了fadeVisible
和slideVisible
绑定。
以下使用单独的Planet
视图模型和typeToShow
属性的订阅。
function Planet(data) {
var self = this;
self.name = data.name;
self.type = data.type;
self.visible = ko.observable(true);
}
Planet.create = function (data) {
return new Planet(data);
};
function Planets(data) {
var self = this;
self.planets = ko.observableArray(ko.utils.arrayMap(data.planets, Planet.create));
self.typeToShow = ko.observable("all");
self.displayAdvancedOptions = ko.observable(true);
self.addPlanet = function(name, type) {
self.planets.push(new Planet({
name: name || "New planet",
type: type || "rock"
}));
};
self.typeToShow.subscribe(function (type) {
ko.utils.arrayForEach(self.planets(), function(planet) {
planet.visible(type === "all" || ko.unwrap(planet.type) === type);
});
});
}
ko.bindingHandlers.fadeVisible = {
init: function(element, valueAccessor) {
var value = valueAccessor(),
visible = ko.unwrap(value);
$(element).toggle(visible);
},
update: function(element, valueAccessor) {
var value = valueAccessor(),
visible = ko.unwrap(value);
$(element)[visible ? "fadeIn" : "fadeOut"]();
}
};
ko.bindingHandlers.slideVisible = {
init: function(element, valueAccessor) {
var value = valueAccessor(),
visible = ko.unwrap(value);
$(element).toggle(visible);
},
update: function(element, valueAccessor) {
var value = valueAccessor(),
visible = ko.unwrap(value);
$(element)[visible ? "slideDown" : "slideUp"]();
}
};
ko.applyBindings(new Planets({
planets: [
{ name: "Mercury", type: "rock"},
{ name: "Venus", type: "rock"},
{ name: "Earth", type: "rock"},
{ name: "Mars", type: "rock"},
{ name: "Jupiter", type: "gasgiant"},
{ name: "Saturn", type: "gasgiant"},
{ name: "Uranus", type: "gasgiant"},
{ name: "Neptune", type: "gasgiant"},
{ name: "Pluto", type: "rock"}
]
}));
&#13;
body { font-family: arial; font-size: 14px; }
.liveExample { padding: 1em; background-color: #EEEEDD; border: 1px solid #CCC; max-width: 655px; }
.liveExample input { font-family: Arial; }
.liveExample b { font-weight: bold; }
.liveExample p { margin-top: 0.9em; margin-bottom: 0.9em; }
.liveExample select[multiple] { width: 100%; height: 8em; }
.liveExample h2 { margin-top: 0.4em; }
.planet { background-color: #AAEECC; padding: 0.25em; border: 1px solid silver; margin-bottom: 0.5em; font-size: 0.75em; }
.planet.rock { background-color: #EECCAA; }
.liveExample input { margin: 0 0.3em 0 1em; }
li { list-style-type: disc; margin-left: 20px; }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div class='liveExample'>
<h2>Planets</h2>
<p data-bind='fadeVisible: displayAdvancedOptions'>
Show:
<label><input type='radio' name="type" value='all' data-bind='checked: typeToShow' />All</label>
<label><input type='radio' name="type" value='rock' data-bind='checked: typeToShow' />Rocky planets</label>
<label><input type='radio' name="type" value='gasgiant' data-bind='checked: typeToShow' />Gas giants</label>
</p>
<div data-bind='foreach: planets'>
<div data-bind='attr: { "class": "planet " + type }, text: name, slideVisible: visible'></div>
</div>
</div>
&#13;
现在,第一颗行星的动画是如此微不足道,以至于我没有费心去实现它。
答案 2 :(得分:0)
你可以这样做: 换行:
<div data-bind='attr: { "class": name + "_" + type }, text: name'> </div>
this.animateFirstElement = function() {
$("." + this.planets()[0].name + "_" + this.planets()[0].type).toggle();
};