看了AngularJS官网的一些例子,觉得很给力,将开发人员的注意力从满屏的DOM操作中转移到传统的业务中,以数据为中心,绑定View,实现二者的绑定和更新。
自己平时做的较多的是地图类应用,类似百度地图PC版和腾讯地图那种,考虑过用AngularJS,可是想来想去觉得不大合适,主要原因是地图类应用一般依赖第三方地图API,比如基于百度地图需要百度地图Javascript API,腾讯也有自己的JS API,这些API的普遍概念是提供一个页面元素,然后在这个元素里创建一个可交互的地图界面。
1 地图初始化
假如我们希望在页面p#map-p这个位置创建一个地图,通常代码如下:
<p id="map-p"></p>
var map=new BMap.Map("map-p",{});
这个map对象有包含了许多方法比如添加叠加物、地图绘制等,这些方法大多数又会引起地图界面的更新,比如下面的代码会在地图界面上弹出一个窗口:
map.addInfoWindow();
如果按照AngularJS的里面,我们应该在页面里声明一个地图的View,类似这样
这样的话,我们需要创建一个bd-map
的directive
,意味着需要针对不同的地图SDK建立不同的directive,虽然这个是一劳永逸的工作,算起来这个不算啥。
2 地图交互
这一块我觉得如果完全通过AngularJS封装会导致把简单问题复杂化,比如我从后台请求了10个酒店的数据markers
,每个酒店有一个位置信息,一般情况下,我会这么干:
for(var i......){
var item=...
var marker=new BMap.Marker(...);
map.addOverlay(marker);
}
但是按照AngularJS的理念,markers
明显应该是某个scope
里面的数据,我们的业务应该关注在这个数据的获取和更新上,界面的更新应该交由directive
完成,于是我好像还需要创建marker
对应的directive,到这一步我已经觉得有点复杂了,有一种多此一举的感觉。
3 事件
地图本身,以及地图上面的叠加物多少都有一些事件的,比如你点击了地图,点击了一个图标等等,这些在地图类应用里面很常见,如果使用AngularjS的话好像又要封装一下。
我的感觉是,地图类SDK本身已经可以看作是一个MVC的实现,比如你把地图的各种参数(数据)设置好,然后通过一句SDK提供的接口,一个地图界面(View)就创建了,通过修改地图中心点等接口,地图视图也跟着变化,这种情况下跟AngularJS强行结合好像会适得其反,这种情况我觉得还是Backbone更合适一点,毕竟Backbone的view还是比较灵活的,Model的渲染完全在自己手里,可以手工操作dom,也可以调用通过地图SDK完成,并没有耦合的很紧密,不需要额外的工作。
学AngularJS时间比较短,大概1周,有这种想法,不知道有没有哪里理解不到位的地方?
补充,我觉得AngularJS最适合的场景是应用只需要原生的页面元素的组合,比如不同的view只是将数据注入到不同的template的中,比如todolist,gmail这种,就是原生html元素的拼凑。
大家讲道理2017-05-15 16:52:21
首先,学 Angular 只有一周就能想到这么深已经是很不容易了,比我当初强太多,我相信你能把 Angular 用的很好。
其次,很遗憾我没有怎么接触过地图类应用,特别是不了解那些 SDK 究竟复杂到什么程度,所以我很难说换用 Angular 是否能让事情变得更好。
先说句题外话,我觉得 API 和 SDK 是不同的,特别是对 webapp 来说。API 通常是用于数据交换的,一般不会涉及到 DOM 对象;而 SDK 才是你说的那种,它们本身就有一套封装好的逻辑,并且通常都提供了和 DOM 紧密耦合的接口调用。
API 对于 Angular 来说可以处理得很好,自带的 Resource 特别适合用于封装 API 服务。但是 SDK 的话其本身的封装就比较完备了,在 Angular 的世界里由于强调不直接操作 DOM 反而使得 SDK 的融入会变得复杂和困难一些。这个现象的确是存在的,解决之道也的确和你想的差不多,利用 directive 抽象 DOM 交互,利用 service 抽象逻辑部分。比如说想 Highcharts 这样的东东——虽然不是地图 SDK,但也是类似的较复杂且封装完备的第三方库——它与 Angular 的整合就相当不容易,坑也不少,所以才会有很多人单独做了 Angular+Highcharts 的模块用于重用,你可以搜搜这方面的例子看看其实现大概能估量出是否合适了。
Angular 的封装是否会让简单问题复杂化?有时候是的。这其实取决于问题本身,Angular 也不是万能药,它并非适合所有类型的应用。你觉得 Backbone 完全能 handle 你现在的工作?那就继续用,不用理会“潮流”。反之等你确实发现 Angular 有 Backbone 无法媲美的部分,那就果断用 Angular 上手,反正没有一个框架是完美的,该解决的问题只要你碰了就还得解决,不碰就没有必要操心。
另外我想延伸一下这个探讨。
让我们把技术粗略的分为三个部分:过去的技术(或者说成熟的技术),眼下的技术(或者说流行的技术),以及未来的技术(或者说代表着趋势的技术)。
我们很容易冲动的决定用“眼下的技术”来替代“过去的技术”,大体上来说会有代价,但也绝对不会没有好处,并且处理得当的话,好处总是胜于代价的。
问题是“眼下的技术”总有很多选择,我们会比较容易陷入这种选择中无法决断,甚至会觉得退回到过去的技术似乎也没有什么大不了的,至少很安全。
我没法说怎样是对的,最近一年回答了很多次这样的问题,自己都有些疲倦了,我只能说说自己的判断。
我倾向于通过学习和了解“未来的技术”来选择“眼下的技术”,并坚决取代“过去的技术”。
“过去的技术”总会过去,迟与早不过是一个时间问题,我是那种“逆水行舟,不进则退”的类型,即使代价会大也在所不惜。
“眼下的技术”是否与“未来的技术”合拍其实反映了作者/团队对于技术趋势的理解和判断,也反映了你个人的理解和判断,这里面会带一点赌博的成分,有没有这份自信和决断能力就得看自己了。
我为什么谈到“未来的技术”呢?就拿你做的地图类应用来说吧,你觉得像现在的这些 SDK 还能用多久?不单单指它们的代码本身,而是它们的技术栈,基于 SDK 以 DOM 为导向的地图类应用开发模式还能持续多久?
如果你觉得这个问题很难回答,那么第一可以回顾一下业界领头羊们的发展历史,比如 Google Maps;再一个去了解一下同行中领先者的技术架构。
我们差不多都知道并可以预期 WebComponents 将会是 webapp 的下一个 big thing,那么,当 WebComponents 变成“眼下的技术”的时候(说不定用不了多久),现在的这一套基于 SDK 以 DOM 为导向的地图类应用开发模式还有多少进步空间和生存空间?
我不知道答案,也不想灌输给你什么“价值观”,我只是描述一下我会如何思考并如何决断。通过你对问题的描述我感觉你并非只是一个程序员,说不定你在你的团队里也扮演者“架构师”一类的角色,所以我才多说这些,总的意思就是四个字:高瞻远瞩。
phpcn_u15822017-05-15 16:52:21
感觉map部分不一定要和angular扯上什么关系,可以把地图放在angular之外或者让angular不去编译map部分。但是不影响你去使用正常的map(毕竟已经被他们封装好了),在需要angular做处理的时候,再交由angular去处理。
虽然你用了angular,但是不一定页面上所有元素都要和angular相关,把它用在它擅长的地方的就可以了。不要为了用angular而去把所有东西都和angular挂钩。
滿天的星座2017-05-15 16:52:21
这属于两个不同领域的框架
地图API专注于G的展现,AngularJS专注于IS的展现,两者并不冲突.举个例子
当我们做查询时,服务端返回一系列的要素信息,现在一般的做法都是便利要素,获取信息,然后通过模板拼凑出HTML,显示结果列表,同时,将这些要素信息添加到图层,绘制到地图上.
地图API帮我们完成了地理要素的绘制,但是信息数据是需要我们自己来控制的.
让我们来模拟一段鼠标和要素交互的例子
function highlight(feature){
map.control.select(feature)
}
//伪代码(原始),或者其他前端模板
var i=0,l=arrs.length,str=[],$case,map;
for(;i<l;i++){
str.push("<li>"+arrs[i].name+"</li>")
}
$case.on("mouseenter","li",function(){
var index=$(this).index();
var feature=arrs[index];
highlight(feature);
})
//AngularJS
<li ng-repeat="item in arrs" ng-mouseenter="highlight(item)">{{item.name}}</li>
当然,原始采用其他的js模板也可进行MVC,但是使用AngularJS的好处在于单页面应用,中间实现过程都只是条条大道通罗马而已.
但是,需求改变了,我们在高亮要素的同时,能够高亮当前的li元素,或者其他的新需求,这时候就会发现,我们改动代码的点不在一个位置
原始方法需要在事件绑定的过程里增加样式的切换
//AngularJS
<li ng-repeat="item in arrs"
ng-mouseenter="highlight(item);item.active=true"
ng-mouseleave="item.active=false"
ng-class="{'highlight':item.active}"
>{{item.name}}</li>
简单来讲,维护变的更快速,原有业务不受影响.
仅有的幸福2017-05-15 16:52:21
的确,地图SDK已经帮你完成了DOM的管理,这部分的工作和ng的重复了,所以再强加ng上去就会感觉怪怪的。如果地图SDK的提供本身就是ng方式的那可能就会带来不一样的开发体验了。
漂亮男人2017-05-15 16:52:21
刚开始觉得是有点麻烦,不过逐渐理解angular就觉得比较顺手了。
要知道不管什么JS框架,对象都是传递的引用。
然后对于SDK,其实把SDK的对象绑到一个service上,注意在回调里$apply一下就好了