小程序城市选择自定义组件

小程序城市选择自定义组件

    • 前言
    • 文件目录
    • index中引入组件
    • address组件部分

针对微信小程序选择城市这块,本文开发的小程序为开发提供者一个参考,注意:如果不了解如何使用微信小程序自定义组件的,建议先看一下官方说明: https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/
小程序城市选择自定义组件_第1张图片

前言

类似功能的小程序也有挺多,其实都是大同小异,有部分样式是参考其他小程序,该小程序还在开发中,还有很多没有完善…

文件目录

  • components
    • address
      • address.js //自定义组件逻辑处理
      • address.json
      • address.wxml //自定义组件视图
      • address.wxss //自定义组件样式文件
      • config.wxs //小程序脚本配置文件
  • pages
    • index
      • index.js
      • index.json
      • index.wxml
      • index.wxss

index中引入组件

首先要在index,json中引入组件,代码如下

{
	"usingComponents": {
    "address": "../../components/address/address"
  }
}

然后在index.wxml中使用组件


 <view class='wrapper'> 
  <address my-city="北京" data="{{city}}" binddetail="bindtap"></address>
 </view> 
 <!--参数说明:
 	data [Object] : 列表所需要的数据(所有城市的json格式)
 	my-city [String]: 我的城市, 
 -->

city中的数据如图所示,如需这些数据可以私信我。
let city = require(’…/…/data/allcity.js’);
小程序城市选择自定义组件_第2张图片

address组件部分

该组件的wxml,wxss部分,这里就不多讲话了,下面直接给代码吧,这里讲一下js跟config部分。
js这里就两个核心点,1、处理index页面携带进来的数据(即组件初始化数据),2、将选中的城市抛出去,记录历史选中城市。
一、config.wxs

module.exports = {
  horizontal: true, // 第二个选项是否横排显示(一般第一个数据选项为 热门城市,常用城市之类 ,开启看需求)
  animation:true ,// 过渡动画是否开启
  search:true ,// 是否开启搜索
  history:true ,// 是否开启历史访问城市
  searchBtn:false ,// 是否存在搜索按钮
};

二、address.js
初始数据处理:这里只需将所有城市的json赋值给list便可。

	  let rightArr = []
      for (let i in data) {
        rightArr.push(data[i].title.substr(0, 1));
      }
      this.setData({
        list: data,
        rightArr
      })

历史访问数据处理

		let detail = e.currentTarget.dataset.detail;
		this.triggerEvent('detail', detail, myEventOption);
      if(wx.getStorageSync('historyAddress')){
        var arr = wx.getStorageSync('historyAddress');
        for(var i=0;i<arr.length;i++){ 	
          if(arr[i].name==detail.name){//这里主要将以前访问过的,又重新选中的放到最前面
            var arr1 = arr[i];
            var arr2 = arr[0];
            var arr3 = [];
            arr3 = arr1; 
            arr[i] = arr[0];
            arr[0] = arr3;
            wx.setStorageSync('historyAddress',arr)
            break;
          }
          if(i==arr.length-1){ //如果选中的这个城市以前没访问过,这记录下来
            arr = prepend(arr,detail); 
            wx.setStorageSync('historyAddress',arr);
            function prepend(arr, item) {
                 //将arr数组复制给a
                 var a = arr.slice(0);
                 //使用unshift方法向a开头添加item
                 a.unshift(item);
                 return a;
             }
            break;
          }
        }
      }else{
        var newArr = [];
        newArr.push(detail);
        wx.setStorageSync('historyAddress',newArr)
      }

搜索:

_search(){
      console.log("搜索")
      let data = this.data.data;
      let newData = [];
      for (let i = 0; i < data.length; i++) {
        let itemArr = [];
        for (let j = 0; j < data[i].item.length; j++) {
          if (data[i].item[j].name.indexOf(this.value) > -1) {
            let itemJson = {};
            for (let k in data[i].item[j]) {
              itemJson[k] = data[i].item[j][k];
            }
            itemArr.push(itemJson);
          }
        }
        if (itemArr.length === 0) {
          continue;
        }
        newData.push({
          title: data[i].title,
          type: data[i].type ? data[i].type : "",
          item: itemArr
        })
      }
      this.resetRight(newData);
    },

完整js代码


Component({
  /**
   * 组件的属性列表
   */
  properties: {
    data: {
      type: Object,
      value: {},
      observer: function (newVal, oldVal) { 
        this.resetRight(newVal);
        if(wx.getStorageSync('historyAddress')){
          this.setData({
            historyAddress:wx.getStorageSync('historyAddress')
          })
        }
      }
    },
    myCity: {
      type: String,
      value: "",
    },
    // 用于外部组件搜索使用
    search:{
      type:String,
      value:"",
      observer: function (newVal, oldVal) { 
        console.log(newVal)
        this.value = newVal;
        this.searchMt();
      }
    }
  },

  data: {
    inputValue: '',
    list: [],
    rightArr: [],// 右侧字母展示
    jumpNum: '',//跳转到那个字母
    myCityName: '请选择', // 默认我的城市
    screenHeight:wx.getSystemInfoSync().screenHeight,
    historyAddress:null,
  },
  ready() {
    let data = this.data.data;
    this.resetRight(data);
    if (this.data.myCity) {
      this.getCity()
    }
  },
  methods: {
    // 数据重新渲染
    resetRight(data) {
      let rightArr = []
      for (let i in data) {
        rightArr.push(data[i].title.substr(0, 1));
      }
      this.setData({
        list: data,
        rightArr
      })
    },
    getCity() {
      var _this = this;
      wx.getLocation({
        type: 'wgs84',
        success: function (res) {
          _this.latitude = res.latitude;
          _this.longitude = res.longitude;
          console.log(res)
        }
      })
    },
    // 右侧字母点击事件
    jumpMt(e) {
      let jumpNum = e.currentTarget.dataset.id;
      this.setData({jumpNum:jumpNum});
      console.log(this.data.jumpNum,'jumpNum')
    },
    // 列表点击事件
    detailMt(e) {
      let detail = e.currentTarget.dataset.detail;
      if(e.currentTarget.dataset.mycity){
        var mycity = {
          name:detail,
          key:'我的城市'
        }
        detail = mycity
      }
      
      let myEventOption = {
        bubbles: false,//事件是否冒泡
        composed: false,//事件是否可以穿越组件边界
        capturePhase: false //事件是否拥有捕获阶段
      } // 触发事件的选项
      this.triggerEvent('detail', detail, myEventOption);
      console.log(detail,'detail');
      if(wx.getStorageSync('historyAddress')){
        var arr = wx.getStorageSync('historyAddress');
        for(var i=0;i<arr.length;i++){
          if(arr[i].name==detail.name){
            var arr1 = arr[i];
            var arr2 = arr[0];
            var arr3 = [];
            arr3 = arr1; 
            arr[i] = arr[0];
            arr[0] = arr3;
            wx.setStorageSync('historyAddress',arr)
            break;
          }
          if(i==arr.length-1){
            // var aa= [
            //   {name:detail.name,key:detail.key}
            // ];
            // aa.push(detail)
            // arr[arr.length] = detail; 
            arr = prepend(arr,detail); 
            wx.setStorageSync('historyAddress',arr);
            function prepend(arr, item) {
                 //将arr数组复制给a
                 var a = arr.slice(0);
                 //使用unshift方法向a开头添加item
                 a.unshift(item);
                 return a;
             }
            break;
          }
        }
      }else{
        var newArr = [];
        newArr.push(detail);
        wx.setStorageSync('historyAddress',newArr)
      }
      
      // wx.setStorageSync('historyAddress',_this.data.myConcern);
    },
    // 获取搜索输入内容
    input(e) {
      this.value = e.detail.value;
      this._search();
      this.setData({
        inputValue:e.detail.value
      })
    },
    clear() {
      this.value = '';
      this.setData({
        inputValue:''
      })
      this._search();
    },
    // 基础搜索功能
    searchMt() {
      this._search();
    },
    _search(){
      console.log("搜索")
      let data = this.data.data;
      let newData = [];
      for (let i = 0; i < data.length; i++) {
        let itemArr = [];
        for (let j = 0; j < data[i].item.length; j++) {
          if (data[i].item[j].name.indexOf(this.value) > -1) {
            let itemJson = {};
            for (let k in data[i].item[j]) {
              itemJson[k] = data[i].item[j][k];
            }
            itemArr.push(itemJson);
          }
        }
        if (itemArr.length === 0) {
          continue;
        }
        newData.push({
          title: data[i].title,
          type: data[i].type ? data[i].type : "",
          item: itemArr
        })
      }
      this.resetRight(newData);
    },
    // 城市定位
    locationMt() {

      // 定位自己的城市,需要引入第三方api
    }

  }
})

`wxml,这部分包括,城市搜索,我的城市,历史访问城市,热门城市推荐,城市字母选择,城市列表。其中搜索,历史访问城市,热门城市以及过度动画是否开启,这些都做在config.wxs中。

<wxs src="config.wxs" module="config" />

<view class='list-warpper'>
  <view wx:if="{{config.search}}" class='list-search'>
    <view class='list-search-box'>
      <icon type="search" size="15" color="#d1dbf6" />
      
      <input placeholder-style="color:white;font-size:30rpx;" placeholder="输入您要搜索的城市" bindinput='input' value="{{inputValue}}"/>
      <icon bindtap="clear" type="clear" size="15" color="#d1dbf6" />
    </view>
    <button wx:if="{{config.searchBtn}}" class='search-button' catchtap='searchMt'>搜索</button>
  </view>
  
  <block wx:if="{{list.length != 0 }}">
    <scroll-view style="height: {{screenHeight*0.95}}px;" class="list-scroll {{config.search?'top':''}}" scroll-y="true" scroll-into-view="{{jumpNum}}" scroll-with-animation="{{config.animation}}">
      <view class="line-h30" style=""></view>
      <!-- 我的位置  -->
      <view wx:if="{{myCity}}">
        <view class='list-horizontal myaddress'>
          <view class="wh40" style="">
            <image class="wh100" mode="aspectFit" src="/image/address.png"></image>
          </view>
          <view class='myaddressText' data-detail="{{myCity}}" data-mycity='1' catchtap='detailMt'>
            {{myCity}}
          </view>
          <view class="mt14">GPS定位</view>
        </view>
      </view>

      <!-- 历史访问城市 -->
      <view wx:if="{{historyAddress&&config.history}}">
        <view class='list-title'>历史访问城市</view>
        <view class='list-horizontal'>
          <view class='list-name border' wx:for="{{historyAddress}}" wx:for-item="history" wx:for-index="idx" wx:key="history" data-detail="{{history}}" catchtap='detailMt'>
            {{history.name}}
          </view>
        </view>
      </view>

      <!-- 热门搜索&所有城市 -->
      <view id="{{'index'+index}}" wx:for="{{list}}" wx:key="key">
        <view class='list-title'>{{item.title}}</view>
        <view class='{{index===0&&config.horizontal&&item.type==="hot"?"list-horizontal":""}}'>
          <view class='list-name {{idx === 0 ?"":"border"}}' wx:for="{{item.item}}" wx:for-item="city" wx:for-index="idx" wx:key="city" data-detail="{{city}}" catchtap='detailMt'>
            {{city.name}}
          </view>
        </view>
        <view wx:if="{{index===0}}" class="line-h30"></view>
      </view>

    </scroll-view>
    <view class='list-right-wrapper'>
      <view class='right-item' wx:for="{{rightArr}}" wx:key="rightArr" data-id="{{'index'+index}}" catchtap='jumpMt'>
        {{rightArr[index]}}
      </view>
    </view>
  </block>
  <block wx:else>
    <view class='nodata'>暂无更多数据</view>
  </block>
</view>

wxss部分

page{
  height:100%;
  width:100%;
}
.wh100{
  width:100%;
  height:100%;
}
.list-warpper {
  position: relative;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}

.list-scroll {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
.list-scroll.top{
  padding-top: 90rpx;
}

/* 样式控制  */

.list-title {
  background: #fff;
  color: #999;
  font-size: 28rpx;
  padding: 10rpx;
  padding-left: 30rpx;
  padding-top: 15rpx;
}

.list-name {
  position: relative;
  font-size: 28rpx;
  padding: 30rpx;
  padding-left: 30rpx;
  color: #444;
}

.list-name.border::after {
  content: "";
  position: absolute;
  left: 30rpx;
  right: 0;
  top: 0;
  height: 1px;
  background: #f5f5f5;
}

.list-right-wrapper {
  position: fixed;
  top: 12%;
  right: 2rpx;
  padding: 10rpx;
  border-radius: 20rpx;
  z-index: 2;
  height: 80%;
  overflow: auto;
  /* background: #ddd; */
}

.right-item {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 2rpx 10rpx;
  font-size: 25rpx;
  color: #666;
}

.list-search {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  width: 100%;
  /* height: 90rpx; */
  padding: 10rpx 30rpx;
  box-sizing: border-box;
  z-index: 20;
  background: #3e67d9;
  padding-bottom: 20rpx;
}

.search-title {
  flex-shrink: 0;
  font-size: 28rpx;
  padding-right: 10rpx;
}

.list-search-box {
  display: flex;
  align-items: center;
  padding: 0 30rpx;
  width: 100%;
  height: 70rpx;
  background: #6585e1;
  border-radius: 90rpx;
  font-size: 28rpx;
  box-sizing: border-box;
}

  .list-search-box input {
  width: 100%;
  padding-left: 10rpx;
  color: white;
}

.search-button {
  /* width: 100rpx; */
  flex-shrink: 0;
  height: 60rpx;
  line-height: 60rpx;
  font-size: 28rpx;
  margin-left: 10rpx;
  color:white;
}

/* 热门城市横排显示样式  */

.list-horizontal {
  display: flex;
  flex-wrap: wrap;
  padding: 10rpx 30rpx;
  padding-right: 50rpx;
  align-items:center;
}

.list-horizontal .list-name{
  border:1rpx #ddd solid;
  border-radius:5rpx;
  margin-right:3%;
  width:29%;
  text-align:center;
  padding:15rpx 0;
  margin-bottom:25rpx;
  font-size:30rpx;
  color:#333;
  position: static;

}


/* 无数据  */
.nodata {
  padding-top: 200rpx;
  text-align: center;
  font-size: 32rpx;
  color: #ddd;
}

.wh40{
  width: 40rpx;
  height: 40rpx;
}
.myaddress{
  padding: 20rpx 0;
  margin: 0 30rpx;
  border-bottom: 1rpx solid #eee;
  font-size: 30rpx;
  color: #999;
}
.line-h30{
  width: 100%;
  height: 30rpx;
  background: #f7f7f7;
}
.myaddressText{
  font-size: 40rpx;
  color: #000;
  margin: 0 15rpx;
}
.mt14{
  margin-top:14rpx;
}

参考效果小程序:
小程序城市选择自定义组件_第3张图片

你可能感兴趣的:(微信小程序)