Ember旅程系列(十) -- 服务与工具
来源:互联网 发布:java文件转md5 编辑:程序博客网 时间:2024/05/17 08:56
英文原版:https://guides.emberjs.com/v2.13.0/tutorial/service/
对于Super Rentals应用,我们希望它能显示出每个出租点的位置。为了实现这个功能,我们进一步发掘Ember的潜力:
- 利用工具调用Google地图接口创建一个地图。
- 利用一个服务来将每个租赁地点的地图信息进行缓存。
- 利用一个组件来对租赁列表中的每个租赁点进行展示。
接入Google地图
在实现地图功能之前,我们需要在app中接入一个第三方的地图API。其实有很多方法可以在Ember中引入第三方库。你可以阅读依赖管理这一节来学习如何接入第三方库。
为了使用Google地图API,我们通过<script>来引入它。在app/index.html中加入对Google Maps API的引用:
app/index.html<!DOCTYPE html><html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>SuperRentals</title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> {{content-for "head"}} <link rel="stylesheet" href="{{rootURL}}assets/vendor.css"> <link rel="stylesheet" href="{{rootURL}}assets/super-rentals.css"> {{content-for "head-footer"}} </head> <body> {{content-for "body"}} <script src="{{rootURL}}assets/vendor.js"></script> <script src="{{rootURL}}assets/super-rentals.js"></script> <!-- 引入Google Maps API--> <script src="https://maps.googleapis.com/maps/api/js?v=3.22"></script> {{content-for "body-footer"}} </body></html>
通过工具与Google Maps API交互
Ember工具几乎可以在Ember应用的各种各样的场景下使用并重用。就拿现在的Super Rentals来说,我们将通过Ember工具来与Google Maps API交互。此工具可以将Google Maps API从我们的Maps Service单独抽取出来。
既然已经引入了Google Maps API,接下来我们就来创建地图工具:
ember g util google-maps
上面这条命令会生成一个工具和一个单元测试文件。因为不需要对Google的代码进行测试,所以在这里我们就把测试文件删除了。
我们应用现在需要一个方法,用来调用google.maps.Map以生成地图,那就给这个方法取名createMap 好了。google.maps.Geocoder接口用来查询的目标的经纬度,google.maps.Marker用来做地图定位。
app/utils/google-maps.jsimport Ember from 'ember';const google = window.google;export default Ember.Object.extend({ init() { this.set('geocoder', new google.maps.Geocoder()); }, createMap(element, location) { let map = new google.maps.Map(element, { scrollwheel: false, zoom: 10 }); this.pinLocation(location, map); return map; }, pinLocation(location, map) { this.get('geocoder').geocode({address: location}, (result, status) => { if (status === google.maps.GeocoderStatus.OK) { let geometry = result[0].geometry.location; let position = { lat: geometry.lat(), lng: geometry.lng() }; map.setCenter(position); new google.maps.Marker({ position, map, title: location }); } }); }});
使用服务拉取地图数据
好了,我们现在创建了地图。接下来,继续。我们将创建一个地图服务,用来保持对上一步创建的地图对象的引用。同时将地图接入到页面的HTML元素上。
通过服务来操作地图API 有不少好处:
- 服务可以在被单独注入,这意味着它能将地图API单独抽取出来。方便日后的代码重构和维护。
- 服务是以懒加载形式引入,它直到被第一次调用的时候才会初始化。在某些场景,这在一定程度上可以减少app对cpu的负载及内存消耗。
- 服务是单例的,这意味着它在整个应用中只有一个实例。所以它能恒久远的保存地图数据,以至于当用户在应用内瞎逛然后又回到地图页面时,不用重新远程读取数据。
创建服务:
ember g service maps
紧接着编写此服务的代码。需要注意的是,我们首先需要判断一下有没有给定条件的地图存在,如果没有则需要调用Google Maps工具来创建它:
app/services/maps.jsimport Ember from 'ember';import MapUtil from '../utils/google-maps';export default Ember.Service.extend({ init() { if (!this.get('cachedMaps')) { this.set('cachedMaps', Ember.Object.create()); } if (!this.get('mapUtil')) { this.set('mapUtil', MapUtil.create()); } }, getMapElement(location) { let camelizedLocation = location.camelize(); let element = this.get(`cachedMaps.${camelizedLocation}`); if (!element) { element = this.createMapElement(); this.get('mapUtil').createMap(element, location); this.set(`cachedMaps.${camelizedLocation}`, element); } return element; }, createMapElement() { let element = document.createElement('div'); element.className = 'map'; return element; }});
通过组件来展示地图
基于服务和工具来讲地图渲染到页面是不够的,这里我们还需要一个组件来把这些环节串起来。
创建组件:
ember g component location-map
我们在app/templates/components/location-map.hbs中添加一个div元素,用它来做承载地图的容器:
app/templates/components/location-map.hbs<div class="map-container"></div>
下一步,完善我们的组件,让组件把地图输出到上面创建的div元素中。
我们通过在组件中创建一个属性来引入地图服务,属性就叫maps好了。服务可以在包括组件在内的Ember的任何对象内被注入。当你使用Ember.inject.service()来对Ember对象中的属性进行初始化的时候,Ember会自动的将与属性同名的服务注入。
通过maps服务,我们可以调用一个名叫getMapElement的方法,并将location信息传入。我们通过didInsertElement()钩子方法将从服务中得到的地图放到容器元素内。此钩子函数会在组件渲染期间被调用:
app/components/location-map.jsexport default Ember.Component.extend({ maps: Ember.inject.service(), didInsertElement() { this._super(...arguments); let location = this.get('location'); let mapElement = this.get('maps').getMapElement(location); this.$('.map-container').append(mapElement); }});
你或许发现了this.get(‘location’)这句代码中指定的location属性并没有被显示的定义。其实这个属性在引入组件的父模板文件中定义。
最后一步,打开rental-listing组件模板,并且引入刚刚新鲜出炉的location-map组件:
app/templates/components/rental-listing.hbs<article class="listing"> <a {{action 'toggleImageSize'}} class="image {{if isWide "wide"}}"> <img src="{{rental.image}}" alt=""> <small>View Larger</small> </a> <h3>{{rental.title}}</h3> <div class="detail owner"> <span>Owner:</span> {{rental.owner}} </div> <div class="detail type"> <span>Type:</span> {{rental-property-type rental.propertyType}} - {{rental.propertyType}} </div> <div class="detail location"> <span>Location:</span> {{rental.city}} </div> <div class="detail bedrooms"> <span>Number of bedrooms:</span> {{rental.bedrooms}} </div> <!-- location属性定义在父模板中 --> {{location-map location=rental.city}}</article>
开启服务器,看看我们成果:
本节完
- Ember旅程系列(十) -- 服务与工具
- Ember旅程系列(三) -- 路由与模版
- Ember旅程系列(四) -- 模型钩子
- Ember旅程系列(五) -- 安装插件
- Ember旅程系列(十一) -- 嵌套路由
- Ember旅程系列(终章) -- 部署
- Ember旅程系列(八) -- 使用Ember Data
- Ember旅程系列(一) -- 创建你的应用
- Ember旅程系列(二)-- 设计的你应用
- Ember旅程系列(六) -- 创建简单组件
- Ember旅程系列(七) -- 创建Handlerbars助手
- Ember旅程系列(九) -- 构建一个比较复杂的组件
- Ember 翻译——教程十:服务和功能
- Ember.js 介绍系列 (待续)
- Ember学习(1):Ember核心概念
- Ember
- 工具类库系列(十)-Object
- ember.js提供的基础服务介绍
- Oracle SQL*PLUS 下的 glogin.sql文件路径及默认配置
- 轻松入门React和Webpack
- 有关js里的[native code]导致的非法调用
- Linux下的多进程编程初步
- Webpack入门教程
- Ember旅程系列(十) -- 服务与工具
- android Activity管理类(全局管理Activity)
- webpack基础入门
- JDK中URLConnection参数使用总结
- 项目实训——第三周(1)
- webpack 从入门到上线
- Collections.sort 使用
- android 仿微信聊天界面,以及语音录制功能
- Android 应用界面设计