如何创建依赖于普通变量、函数或逻辑的ember属性
How to create an ember property dependent on a normal variable, function or logic?
问题
我正在为emberjs制作传单视图,我遇到了一些问题。传单是一个外部库,有点与问题无关,但只需知道它是一个映射库。
考虑一个简单的属性,如缩放级别。传单地图实例具有可通过map.getZoom()
访问和可通过map.setZoom(zoomLevel)
分配的缩放级别。此外,用户可以与地图交互,并更改其缩放级别。传单允许我们在缩放变化时注册一个回调。
我希望我的"余烬传单"视图有一个zoomLevel
余烬属性。这样我就可以从ember对象模型中获益(例如,将zoomLevel
绑定到模板或另一个值),并且我们正在"以ember的方式"做这件事。
基础解决方案
我现在拥有的是Ember的一个子类。视图,带有缩放级别属性。在didInsertElement
上,我创建了传单地图实例。代码有注释,应该是自解释的。
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);
}
});
为了使这个问题更"可回答",我认为这个问题的解决方案应该满足以下要求:
- 当属性
zoomLevel
被改变时,地图应该相应地改变其缩放级别(使用map.setZoom(zoomLevel)
) - 当用户交互地改变地图上的缩放时,
zoomLevel
属性应该被改变(可能使用传单地图的zoomend
事件回调)
注意,我们在这里有一种"循环依赖",即"当zoomLevel
更改时执行某事(setZoom on map)"和"当发生某事时(用户更改缩放),更改zoomLevel
"。我想要一个解决方案,可以避免这种循环的观察者依赖。Ember的notifyPropertyChange可能是一个解决方案。
对于Ember的计算属性来说,这似乎是一个理想的任务,但我不知道在依赖属性字符串中放入什么。zoomLevel
基本上是一个依赖于非ember属性的属性。
更新
我的第一次尝试是使用一个观察者来设置传单的缩放,并在传单zoomend
上绑定一个事件来设置我的视图上的zoomLevel
。
问题:当我在zoomend传单事件上设置zoomLevel时,我将自动再次触发我的观察者。我说得清楚了吗?
那么,这一系列的事件发生了:
- 改变
zoomLevel
在交互式地图 - 传单触发
zoomend
事件 -
zoomend
事件回调集zoomLevel
- 观察者运行
- 在传单上不必要地调用
setZoom
这是不有效的,但我不介意如果它工作。问题是,当用户非常快速地改变缩放多次(地图上一个简单的长滚动)时,观察者会被调用多次,这会混淆传单。
好的,我想我已经做到了。
我使用了一个计算属性和一个辅助属性。
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被编程改变->我们更新地图上的缩放
- 缩放级别在地图上改变了->我们设置了辅助属性,计算机属性观察者也会得到通知,我们没有再设置地图上的缩放级别
然而我有一个新的问题,但我认为它与传单有关。当我调用setZoom
时,另一个缩放动画在过程中,这个setZoom被忽略。例如,执行:
map.setZoom(1);
map.setZoom(12);
结束于1
缩放级别。
也许传单上有关SO的问题会有帮助。
要从zoomLevel在ember到setZoom,你可以使用一个观察者。
如果要用另一种方式,你可能需要绑定一个事件到宣传单上的zoomChange
使用稍微不同的策略,我将zoomLevel作为属性并从函数中观察它,并且仅在属性的实际值与实际缩放值不同时才在地图上设置缩放。看这个小提琴http://jsfiddle.net/5As2z/30/我将逻辑传递给控制器,视图在插入文档
时设置映射。App.ApplicationController = Ember.Controller.extend({
//default zoom level
zoomLevel: 13,
map: null,
zoomLevelChanged: function () {
var zoomLevel = this.get('zoomLevel');
var map = this.get('map');
//Control not changing the zoom of the map if it is yet at the value
if (zoomLevel != map.getZoom()) {
map.setZoom(zoomLevel);
}
}.observes('zoomLevel')});
App.ApplicationView = Ember.View.extend({
templateName: 'application',
didInsertElement: function () {
var center = [41.3823000, 2.1825000];
var controller = this.get('controller');
var zoomLevel = controller.get('zoomLevel');
var map = L.map('map').setView(center, zoomLevel);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
// configure map instance...
// Event listeners
map.on('zoomend', function (e) {
console.log('zoomend', 'Setting zoomLevel ' + e.target.getZoom());
controller.set('zoomLevel', e.target.getZoom());
});
// save map instance
this.controller.set('map', map);
}});
html <script type="text/x-handlebars" data-template-name="application">
<h1> Leaflet map ember example </h1>
{{view Ember.TextField valueBinding="zoomLevel"}}
<div id="map"></div >
</script>
- 从嵌套函数访问函数属性
- Javascript嵌套函数属性继承
- Javascript-在全局作用域中调用本地函数/属性
- 正在重置原型对象的构造函数属性
- javascript函数属性设置器中的延迟
- jQuery插件返回this.each并为每个对象添加函数属性
- 从函数属性访问对象属性;不适用于Firefox
- 当使用“”创建时保留函数属性;绑定”;
- 在多个(html)元素上循环执行相同的JavaScript函数属性更改
- 如何将新的构造函数属性推送到数组
- 通过构造函数属性和运算符实例设置继承
- 角度表达式无法使用构造函数属性分辨变量类型
- 为什么要在函数定义之外引用静态变量(函数属性)
- Javascript“构造函数”属性中的错误 - IE 8
- 为什么浏览器支持对象的隐式函数属性
- 构造函数属性值应该是什么 .a 原型构造函数或对象构造函数本身
- 使用模块模式调用函数属性
- React 组件流类型检查中的可选函数属性失败
- 是否可以在 javascript 中的对象文字上定义函数属性
- JavaScript:如何捕获对象的任何缺失函数/属性