1.首先我们先在本地获取到城市定位

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <style type="text/css">
        body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
    </style>
    <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"></script>
    <title>IP定位获取当前城市</title>
</head>
<body>
    <div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
    // 百度地图API功能
    //var map = new BMap.Map("allmap");
    //var point = new BMap.Point(116.331398,39.897445);
    //map.centerAndZoom(point,12);

    function myFun(result){
        var cityName = result.name;
        //map.setCenter(cityName);
        console.log("当前定位城市:"+cityName);
    }
    var myCity = new BMap.LocalCity();
    myCity.get(myFun);
    console.log('不好意思,我先走一步');
</script>

页面效果

需要注意的是script标签引入百度地图时记得换成你的开发密钥。

接下来我们可以去Vue项目中获取当前城市了。

1.在index.js中引入

<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"></script>

2.我们了解一下模块化程序设计

模块化程序设计的基本思想是自顶向下、逐步分解、分而治之,即将一个较大的程序按照功能分割成一些小模块,各模块相对独立、功能单一、结构清晰、接口简单。

我们整个Vue项目就是一个大的程序,而用百度地图通过IP定位获取当前城市就是其中的一个小功能。符合我们前面说的模块化程序设计思想。

前端用模块化开发,刚好ES6就为我们提供了 export 和 import

export

export语句用于在创建JavaScript模块时,从模块中导出函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。

import

import语句用于导入由另一个模块导出的绑定。无论是否声明了 strict mode ,导入的模块都运行在严格模式下。import语句不能在嵌入式脚本中使用。

其中的语法这里不详细介绍,但有需要注意的地方是模块语法的限制

只能在模块的顶级作用域使用 export 和 import

if (flag) {
    export flag; // 语法错误
}

模块化开发了解后,我们开始封装用百度地图通过IP定位获取当前城市的js

3.封装用百度地图通过IP定位获取当前城市的js

1.创建getUserLocation.js文件

// 这样导出,引入的是 ''
let currentCity = '';//当前城市
function getCurrentCity(result){
  currentCity = result.name;
  console.log("当前定位城市:" + currentCity);
}
var myCity = new BMap.LocalCity();
myCity.get(getCurrentCity);
console.log('不好意思,我先走一步' + currentCity);
export default currentCity

细心的朋友在上面的页面效果时应该就发现了我们这样导出的变量是我们第一次复制的空字符串。

为什么会出现上面的结果?了解 JS执行顺序 的应该知道,JS是一门单线程解释型语言,JS会从上到下排序执行。 排序执行,那当然就有排序的规则,这个自行了解。我这里说的就是JS会自上而下先执行顶层的语句(export),遇到回调函数,会塞入异步队列中等待执行,等顶层的语句都执行完毕再依次执行异步队列中的函数(getCurrentCity),异步队列执行时也是同理。

那我们回到上面的问题,我们可以把问题归纳一下:在模块化开发时,异步获取到的数据如何导出?或者说不论同步或者异步,我们如何能拿到我们想要的值,完成业务?

我们再回到上面的代码,发现我们并不是没拿到值,而是拿到值的时机不对。那我们就会想直接不模块化开发了,把我们的业务写在回调函数中好了。 当然,这样也是可以拿到值的。

但这样给我们带来的风险是:
1.那以后我需要用到这个值的业务是不是都要写在这个回调函数内?如test函数
2.那其他项目中需要用到这个功能时,我们是不是再把这份代码检查一遍,把其他的业务删除掉,再复制过去?
......
这样普通的需求成千上万个,那我们是不是都要这么费力不讨好的写下去?

前面我们说到问题的关键在于导出值的时机不对,因为异步操作,导出的值是我们初始定义的值。那我们会想,要不把生成值的过程导出,此例就是导出myCity.get函数。

var myCity = new BMap.LocalCity()
export default myCity.get

但我在组件中拿到却是这样的:


这个应该是他的源码,其中this是上下文,我们导出这个get函数再在组件中调用时,this是指向vue实例的,而他的this是要指向Hd.prototype的。所以此路不通。

我们去百度搜索下:模块化开发异步获取到的数据如何导出?
答案就是ES6的 promise,我们不再导出单个的值,我们导出一个封装好的promise 对象
Promise 介绍:

A Promise is a proxy for a value not necessarily known when the promise is created. It allows you to associate handlers with an asynchronous action's eventual success value or failure reason. This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future

意思是:
1.promise是一个在promise创建时不一定知道最终值的一个代理。
2.它允许您将处理程序与异步操作的最终成功值或失败原因相关联
3.它让异步方法返回类似同步方法的值
4.这个异步方法不是立即返回最终值,而是返回一个promise,在将来的某个时候提供该值

我们来把上面的异步函数封装成promise,再导出:

let getCurrentCityName = function () {
  return new Promise(function (resolve, reject) {
    let myCity = new BMap.LocalCity()
    myCity.get(function (result) {
      resolve(result.name)
    })
  })
}

export default getCurrentCityName

我这里获取到的值commit到vuex的mutations里