uni-app: 根据定位获取天气(附城市控件)

经过本章节你能学到那些?

一、Uni-App 测试数据封装 二、Uni-App 城市控件(Uni-App元素操做相关) 三、ES6 多种遍历方式区别javascript

uni-app: 根据定位获取天气(附城市控件)

要源码的同窗,购买后能够私信我。下面咱们来具体看看:css

Uni-App 测试数据封装

城市控件,咱们就查询接口了,根据高德提供的城市数据,咱们进行处理后,放到一个文件中。html

// Json.js
const cityList = [{
  "firstLetter":"A",
  "cityList":[{
    "cityID":"513209",
    "city":"阿坝县",
    "abbr":"阿坝县",
    "firstSpell":"abx",
    "spell":"abaxian",
    "latitude":32.908167,
    "longitude":101.712951,
    "isSecond":1
  }, {
    ...
  }]
}, {
  "firstLetter":"B",
  "cityList":[{
    "cityID":"110000",
    "city":"北京市",
    "abbr":"北京",
    "firstSpell":"bjs",
    "spell":"beijingshi",
    "latitude":39.929986,
    "longitude":116.395645,
    "code":"010",
    "sort":1,
    "isSecond":0
  }, {
    ...
  }]
})

export default {
	cityList
}
复制代码

而后咱们在main.js里面引入,使其能够共用。vue

// main.js
...
import Json from './Json'

const json = type=>{
	// 模拟异步请求数据
	return new Promise(resolve=>{
		setTimeout(()=>{
			resolve(Json[type]);
		}, 500)
	})
}

Vue.prototype.$api = {json};
复制代码

下面,咱们就能够在任意vue页面使用this.$api.json('xxxx'),来获取Json.js里面暴露的对象了。java

this.cityList = await this.$api.json('cityList');
复制代码

下面咱们对cityList的数据进行渲染node

Uni-App 城市控件

一、选择pages目录,右击新建页面,记得勾选自动在pages.json中注册,不然须要手动去配置它。git

uni-app: 根据定位获取天气(附城市控件)

新建完成后,pages.json会多一段配置vuex

{
  "path" : "pages/city/city",
  "style" : {
    // 手动配置title
    "navigationBarTitleText": "城市选择"
  }
}
复制代码

同时,pages目录下会多一个目录city,咱们的城市选择页面就写到city/city.vue页面。json

二、获取城市数据小程序

// city/city.vue
data() {
  return {
    cityList: []
  };
},
async onLoad() {
  this.cityList = await this.$api.json('city');
  console.log(this.cityList);
},
复制代码

打印数据以下图:

uni-app: 根据定位获取天气(附城市控件)

三、html结构

uni-app: 根据定位获取天气(附城市控件)

// 对应样式
.filter{
	position: fixed;
	top: 80upx;
	font-size: 24upx;
	right: 0;
	line-height: 40upx;
	text-align: right;
	z-index: 10;
	.li{
		padding-left: 20upx;
		padding-right: 20px;
	}
}
.city-list{
	.letter{
		padding: 10upx 20upx;
		background: #DCDFE660;
		display: block;
	}
	.city{
		padding: 0upx 20upx;
		line-height: 64upx;
		border-bottom: 1upx solid #F8F6FC;
		font-size: 30upx;
		&:last-child{
			border-bottom: none;
		}
	}
}
复制代码

H5预览图:

uni-app: 根据定位获取天气(附城市控件)

四、事件处理 (1)选择城市列表事件

choose (item) {
  // 选择城市后,将城市名字,adcode,经纬度缓存给vuex
  this.$store.commit('setCity', {
    city: item.city,
    adcode: item.cityID,
    latitude: item.latitude,
    longitude: item.longitude
  })
  // 而后根据经纬度查询具体位置
  this.$store.dispatch('getLocation', {
    location: `${item.longitude},${item.latitude}`
  })
  // 最后返回首页
  uni.navigateBack({
      delta: 1
  });
}
复制代码

下面看store.js实现

// store/index.js
mutations: {
  ...
  setCity(state, data){
    state.location = {
      address: data
    };
  },
  setLocation(state, data){
    data = data.regeocode.addressComponent;
    state.location = {
      address: {
        adcode: data.adcode,
        city: data.city.length && data.city || data.province,
        district: data.district
      }
    };
  }
},
actions: {
  getWeather({ commit }, params){
    ...
  },
  getLocation({ commit, dispatch}, params){
    // 高德逆地址解析,根据经纬度获取具体位置
    http({
      methods: 'get',
      url: 'https://restapi.amap.com/v3/geocode/regeo',
      data: {
        key: 'd9xxx7d4xx7bx91xx61cxx5',
        location: params.location,
        output: 'json'
      }
    }).then((data) =>{
      commit('setLocation', data)
      dispatch('getWeather', {
        city: data.regeocode.addressComponent.adcode
      })
    }, (err) => {
      console.log(err)
    })
  }
}
复制代码

逆地址解析数据结构以下:

uni-app: 根据定位获取天气(附城市控件)

这里逆地址解析后,又查询了一次天气,就能够更新到首页天气数据了,咱们选择城市后,是直接返回的,因此这里查询一次天气,首页就不须要处理了。

(2)城市筛选事件 第一次,咱们的解决方案是这样:

filter (name, index) {
  let scrollTop = this.$refs.letter[index].$el.offsetTop;
  uni.showToast({
    title: name,
    icon: 'none',
    duration: 500
  });
  uni.pageScrollTo({
    scrollTop: scrollTop,
    duration: 500
  });
}
复制代码

经过ref找到对应的A-Z,得出他们距离顶部的距离offsetTop,而后滚动(uni.pageScrollTo)到对应位置,H5预览效果:

uni-app: 根据定位获取天气(附城市控件)

然而,小程序/APP报错:

uni-app: 根据定位获取天气(附城市控件)

这里的this.$refs是空的,小程序压根就不能这样操做元素。好吧,只能换方式了。

第二次解决方案:

filter (name, index) {
  uni.createSelectorQuery().select('.city-list').boundingClientRect(data=>{
      uni.createSelectorQuery().select('#letter' + name + '').boundingClientRect((res)=>{
          uni.showToast({
            title: name,
            icon: 'none',
            duration: 500
          });
      uni.pageScrollTo({
              duration: 200,
              scrollTop:res.top - data.top
          })
      }).exec()
  }).exec();
}
复制代码

这里为何要嵌套2层,这是由于滚动到实际距离是元素距离顶部的距离减去最外层盒子的滚动距离

小程序预览图:

uni-app: 根据定位获取天气(附城市控件)

IOS真机预览图:

uni-app: 根据定位获取天气(附城市控件)

Uni-App API解析: uni.createSelectorQuery():返回一个 SelectorQuery 对象实例。能够在这个实例上使用 select 等方法选择节点,并使用 boundingClientRect 等方法选择须要查询的信息,必须在生命周期 mounted 后进行调用。

SelectorQuery提供如下方法: (1)、selectorQuery.in(component):将选择器的选取范围更改成自定义组件 component 内,返回一个 SelectorQuery 对象实例。(初始时,选择器仅选取页面范围的节点,不会选取任何自定义组件中的节点)。

(2)、selectorQuery.select(selector):在当前页面下选择第一个匹配选择器 selector 的节点,返回一个 NodesRef(用于获取节点信息的对象) 对象实例,能够用于获取节点信息。

注意:selector 相似于 CSS 的选择器,但仅支持下列语法。 ID选择器:#the-id

class选择器(能够连续指定多个):.a-class.another-class

子元素选择器:.the-parent > .the-child

后代选择器:.the-ancestor .the-descendant

跨自定义组件的后代选择器:.the-ancestor >>> .the-descendant

多选择器的并集:#a-node, .some-other-nodes

const query = uni.createSelectorQuery().in(this);
query.select('#id').boundingClientRect(data => {
  console.log("获得布局位置信息" + JSON.stringify(data));
  console.log("节点离页面顶部的距离为" + data.top);
}).exec();
复制代码

(3)、selectorQuery.selectAll(selector):在当前页面下选择匹配选择器 selector 的全部节点,返回一个 NodesRef(用于获取节点信息的对象) 对象实例,能够用于获取节点信息

(4)、selectorQuery.selectViewport():选择显示区域,可用于获取显示区域的尺寸、滚动位置等信息,返回一个 NodesRef 对象实例。

(5)、selectorQuery.exec(callback):执行全部的请求。请求结果按请求次序构成数组,在callback的第一个参数中返回。

下面咱们来增强城市控件功能,添加搜索

<!-- pages/city/city.vue -->
<!-- 搜索功能 -->
<view class="search">
  <input class="keyword" v-model="keyword" type="text" placeholder="北京/bj/beijing">
</view>
<!-- 城市列表 -->
<view class="ul city-list" v-if="!keyword">
...
</view>
<view class="city-list" v-else>
  <view class="li city" @click="choose(city)" v-for="(city, cindex) in showCityList" v-bind:key="cindex">
    {{city.city}}
  </view>
</view>
<!-- 快速筛选A-Z -->
<view class="ul filter" v-if="!keyword">
</view>
复制代码

咱们用计算属性对原有的城市数据处理

data() {
  return {
    keyword: '',
    cityList: []
  };
},
computed:{
  // 将全部城市数据整理到citys里面
  citys() {
    let list = [];
    this.cityList.map(item=>{
      list.push(...item.cityList)
    })
    console.log(list);
    return list;
  },
  // 搜索结果展现数据
  showCityList(){
    return this.citys.filter(item => {
      let name = item.city + item.spell;
      return name.indexOf(this.keyword) > -1;
    })
  }
}
复制代码

citys数据结构:

uni-app: 根据定位获取天气(附城市控件)

预览效果图:

uni-app: 根据定位获取天气(附城市控件)

uni-app: 根据定位获取天气(附城市控件)

这里用到了数据的2个方法,filter和map,咱们来温故一下数组的几种遍历方式,和他们各有什么区别。

一、forEach() 迭代数组每一项,没有返回值

二、every() 迭代数组每一项,每项都符合条件的才返回true,反之false

三、some() 迭代数组每一项,只要有一项符合条件就返回true,若是所有不符合才返回false

四、map() 迭代数组每一项,能够给特定条件会返回从新组成新的数组

五、filter() 迭代数组每一项,能够给特定的条件进行筛选返回新的数组

详细内容请点击:JavaScript数组5种迭代方法各有什么妙用?

总结

今天你学到了什么?今天的核心内容: 一、数据的处理(数组操做) 二、uni-app元素操做,筛选滚动

下一章节,天气数据处理(图标、多场景等)

最后,谢谢你们支持。

uni-app: 根据定位获取天气(附城市控件)
喜欢的能够关注我哦!

原文地址:www.javanx.cn/20190829/un…

相关文章
相关标签/搜索