如何根据正常变量,函数或逻辑创建一个ember属性?

mig*_*ain 6 javascript ember.js leaflet

问题

我正在为emberjs制作传单视图,我遇到了一些问题.Leaflet是一个外部库,与问题有点无关,但只知道它是一个映射库.

考虑像缩放级别这样的简单属性.传单映射实例具有map.getZoom()可通过其访问和分配的缩放级别map.setZoom(zoomLevel).此外,用户可以与地图交互,并更改其缩放级别.Leaflet允许我们在缩放变化时注册回调.

我希望我的"Ember-Leaflet"视图有一个zoomLevel余烬属性.这样我就可以从ember对象模型中受益(例如,绑定zoomLevel到模板或另一个值),我们正在"使用ember方式".

基础解决方案

我目前拥有的是Ember.View的子类,具有zoomLevel属性.在didInsertElement我创建Leaflet地图实例.代码已注释,应该是不言自明的.

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);
    }
});
Run Code Online (Sandbox Code Playgroud)

清单

为了使这个问题更"可回答",我认为这个问题的解决方案应该满足以下要求:

  1. zoomLevel更改属性后,地图应相应地更改其缩放级别(使用map.setZoom(zoomLevel))
  2. 当用户以交互方式更改地图上的缩放时,zoomLevel应更改属性(可能使用传单贴图的zoomend事件回调)

请注意,我们在这里有一种"循环依赖",即"在zoomLevel更改时执行某些操作(setZoom在地图上)""当某些事情发生时(用户更改缩放),更改zoomLevel".我想要一个可以避免这种循环观察者依赖的解决方案.Ember的notifyPropertyChange可能是一个解决方案.

对于Ember的计算属性来说,这似乎是一个理想的任务,但我不知道在依赖属性字符串中放入什么.zoomLevel基本上是一个依赖于不是余烬属性的东西的属性.


更新

我的第一次尝试是使用观察者在传单上设置缩放并在活页上绑定事件zoomend以设置zoomLevel我的视图.

问题:当我在zoomend leaflet事件上设置zoomLevel时,我会再次自动触发我的观察者.我清楚了吗?

所以,这一系列事件发生了:

  1. 更改zoomLevel交互式地图
  2. 传单火灾zoomend事件
  3. zoomend 事件回调设置ember zoomLevel
  4. 观察者跑
  5. 不必要setZoom地传单

这效率不高,但我不介意它是否有效.问题在于,当用户非常快速地多次改变缩放(地图上的简单长滚动)时,观察者被多次调用,使传单混乱.

mig*_*ain 2

好吧,我想我已经做到了。

我使用了计算属性和辅助属性。

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);

    }
});
Run Code Online (Sandbox Code Playgroud)

基本上有两种情况:

  1. ZoomLevel 以编程方式更改 -> 我们更新地图上的缩放
  2. 地图上的 ZoomLevel 发生了变化 -> 我们在辅助属性上进行了设置,计算机属性观察者也会收到通知,并且我们没有再次在地图上设置缩放级别

然而我有一个新问题,但我认为它与传单有关。当我setZoom在课程中调用另一个缩放动画时,此 setZoom 被忽略。例如,执行:

map.setZoom(1);
map.setZoom(12);
Run Code Online (Sandbox Code Playgroud)

最终达到1缩放级别。

也许与传单相关的问题可以有所帮助。