如何创建依赖于正常变量,函数或逻辑的余烬属性? [英] How to create an ember property dependent on a normal variable, function or logic?
问题描述
我正在处理emberjs的传单视图,我有一些问题。传单是一个外部图书馆,与问题无关,但只知道它是一个映射库。
I'm working on a leaflet view for emberjs, and I'm having some problems. Leaflet is an external library and somewhat irrelevant to the question, but just know that it is a mapping library.
考虑一个简单的属性,如缩放级别。传单地图实例通过 map.getZoom()
可以通过 map.setZoom(zoomLevel)
指定缩放级别。此外,用户可以与地图进行交互,并改变其缩放级别。传单允许我们在缩放更改时注册回调。
Consider a simple property like zoom level. Leaflet map instances have a zoom level accessible through map.getZoom()
and assignable through map.setZoom(zoomLevel)
. Also, users can interact with the map, and change its zoom level. Leaflet allows us to register a callback when the zoom changes.
我希望我的Ember-Leaflet视图具有一个 zoomLevel
ember属性。这样,我可以从ember对象模型(例如绑定 zoomLevel
到一个模板或另一个值)中受益,我们正在做这个ember方式。
I would like my "Ember-Leaflet" View to have a zoomLevel
ember property. This way I can benefit from the ember object model (bind zoomLevel
to a template or to another value, for example), and we're doing it "the ember way".
我目前拥有的是Ember.View的子类,具有zoomLevel属性。在 didInsertElement
我创建了Leaflet地图实例。代码被评论,应该是不言自明的。
What I currently have is a subclass of Ember.View, with a zoomLevel property. On didInsertElement
I create the Leaflet map instance. The code is commented and should be self-explanatory.
App.Leaflet = Ember.View.extend({
classNames : ['ember-leaflet'],
//default zoom level
zoomLevel : 13,
didInsertElement : function() {
var self = this;
var zoomLevel = this.get('zoomLevel');
// create map instance
var map = L.map(this.$().get(0)).setView(center, zoomLevel);
// configure map instance...
// Event listeners
map.on('zoomend', function(e) {
self.set('zoomLevel', e.target.getZoom());
});
// save map instance
this.set('map', map);
}
});
清单
我认为这个问题的解决方案应该满足以下要求:
Checklist
To make this question more "answerable", I think that a solution to this problem should fulfill the following requirements:
- 当属性
zoomLevel
已更改,地图应相应更改其缩放级别(使用map.setZoom(zoomLevel)
) - 当用户交互地更改地图上的缩放时,应该更改
zoomLevel
属性(可能使用传单地图的缩放
事件回调)
- When the property
zoomLevel
is changed, the map should change its zoom level accordingly (usingmap.setZoom(zoomLevel)
) - When the user interactively changes the zoom on the map, the
zoomLevel
property should be changed (probably using leaflet map'szoomend
event callback)
请注意,我们在这里有一种循环依赖,即做一些(setZoom在地图上)当发生某些事情(用户更改缩放)时 zoomLevel
更改和,更改 zoomLevel
的。我想要一个可以避免这种循环观察者依赖性的解决方案。 Ember的 notifyPropertyChange 可能是一个解决方案。
Notice that we have here a kind of "circular dependency", i.e "Do something (setZoom on map) when zoomLevel
changes" and "when something happens (user changes zoom), change zoomLevel
". I would like a solution that could avoid this circular observer dependencies. Ember's notifyPropertyChange could be a solution.
这似乎是一个理想的任务, Ember的计算属性,但是我不知道放在依赖属性字符串中的内容。 zoomLevel
基本上是一种依赖于不是ember属性的属性。
This seemed like an ideal task for Ember's computed properties, but I didn't know what to put in the dependent properties string. zoomLevel
is basically a property that is dependent on something that isn't an ember property.
我的第一个尝试是使用观察器设置小册子上的缩放,并在传单上绑定一个事件缩放
可以在我的视图中设置 zoomLevel
。
My first attempt was to use an observer to set the zoom on leaflet and to bind an event on leaflet zoomend
to set the zoomLevel
on my view.
问题:当我设置zoomLevel在zoomend传单事件中,我自动再次触发我的观察者。我明白了吗?
Problem: When I set zoomLevel on the zoomend leaflet event, I'm automatically triggering again my observer. Did I make myself clear?
所以,这一连串的事件发生了:
So, this sequence of events happen:
- c
c> c c c c c >
zoomend
事件回调设置emberzoomLevel
- 观察员运行
- 在传单上不必要地调用
setZoom
- change
zoomLevel
on interactive map - leaflet fires
zoomend
event zoomend
event callback sets emberzoomLevel
- observer runs
- unecessarily calls
setZoom
on leaflet
这不是有效的,但我不会介意,如果它有效。
问题是当用户非常快速地变换缩放倍数(地图上简单的长滚动)时,观察者被多次调用,混乱传单。
This is not efficient, but I wouldn't mind if it worked. The problem is that when the user changes zoom multiple times very quickly (a simple long scroll on map) the observer is called multiple times, confusing leaflet.
推荐答案
好的,我想我已经做了。
Ok, I think I've did it.
我使用了一个计算的属性和一个辅助属性。
I used a computed property and an auxiliary property.
App.Leaflet = Ember.View.extend({
classNames : ['ember-leaflet'],
//default zoom level
zoomLevelValue : 13,
zoomLevel : function(key, value){
// getter
if (arguments.length === 1) {
var zoomLevel = this.get('zoomLevelValue');
return zoomLevel;
// setter
} else{
var map = this.get('map');
this.set('zoomLevelValue', value);
map.setZoom(value);
return value;
}
}.property('zoomLevelValue'),
didInsertElement : function() {
var self = this;
var zoomLevel = this.get('zoomLevel');
var map = L.map(this.$().get(0)).setView(center, zoomLevel);
// configure map instance...
// Event listeners
map.on('zoomend', function(e) {
console.log('zoomend', 'Setting zoomLevel '+e.target.getZoom());
self.set('zoomLevelValue', e.target.getZoom());
});
// save map instance
this.set('map', map);
}
});
基本上有两种情况:
- zoomLevel已被程序更改 - >我们更新地图上的缩放
- zoomLevel已在地图上更改 - >我们设置在辅助属性上,而计算机财产观察员也会收到通知,我们还没有在地图上再次设置缩放级别
但是我有一个新问题,但我认为这是传单相关的。当我调用另一个缩放动画时,调用 setZoom
,这个setZoom被忽略。
例如,执行:
However I have a new problem, but I think it is leaflet related. When I call setZoom
when another zoom animation on course, this setZoom is ignored.
For example, executing:
map.setZoom(1);
map.setZoom(12);
最终在 1
缩放级别。
也许有关传单相关的SO问题可以帮助。
Maybe a leaflet related SO question can help.
这篇关于如何创建依赖于正常变量,函数或逻辑的余烬属性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!