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…

相關文章
相關標籤/搜索