小程序自定义API给筛选栏赋值


大家好,这篇文章主要分三部分讲解如果自定义一个筛选插件,并且封装api获取数据,并在页面调用这个插件对其赋值
先上效果图

在这里插入图片描述

封装筛选插件

在我们的小程序开发中,主页经常会有很多功能,如果大家把这些功能写在一个页面,势必会造成页面代码繁多,后期维护起来也头疼,所以把功能封装成组件是大家要养成的良好习惯

js

先上代码

//Component() 来注册组件,并提供组件的属性定义、内部数据和自定义方法

Component({
    properties: {
      // 这里定义了innerText属性,属性值可以在组件使用时指定
      dropDownMenuTitle: {
        type: Array,
        value: ['时间', '地点', '类型','高级筛选'],
      },
      dropDownMenuFirstData: {
        type:Array,
        value:[
            
        ]
      },
     
      dropDownMenuSecondData: {
        type: Array,
        value: ['时间', '地点', '类型','高级筛选']
      },
      dropDownMenuThirdData: {
        type: Array,
        value:[
            {"title" :"嘟嘟喵"},
            {"title" :"小兔子"}
        ]
      },
      dropDownMenuFourthData: {
        type: Array,
        value: ['时间', '地点', '类型','高级筛选']
      },
    },
    data: {
      // 这里是一些组件内部数据
      hyopen: false,
      sqopen: false,
      pxopen: false,
      sortopen: false,
      shownavindex: '',
      dropDownMenuDataFirstRight: { },
      select1: '',
      select2: '',
      selectedQt: 0,
      selectedSq: 0,
      selectedSort: 1,
    },
    methods: {
      // 这里是自定义方法
      listqy: function (e) {
        if (this.data.hyopen) {
          this.setData({
            hyopen: false,
            sqopen: false,
            pxopen: false,
            sortopen: false,
            shownavindex: 0
          })
        } else {
          this.setData({
            hyopen: true,
            pxopen: false,
            sqopen: false,
            sortopen: false,
            shownavindex: e.currentTarget.dataset.nav
          })
        }
  
      },
      list: function (e) {
        if (this.data.sqopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
            shownavindex: 0
          })
        } else {
          this.setData({
            sqopen: true,
            pxopen: false,
            hyopen: false,
            sortopen: false,
            shownavindex: e.currentTarget.dataset.nav
          })
        }
      },
      listpx: function (e) {
        if (this.data.pxopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
            shownavindex: 0
          })
        } else {
          this.setData({
            sqopen: false,
            pxopen: true,
            sortopen: false,
            hyopen: false,
            shownavindex: e.currentTarget.dataset.nav
          })
        }
        console.log(e.target)
      },
      listsort: function (e) {
        if (this.data.sortopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
            shownavindex: 0
          })
        } else {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: true,
            shownavindex: e.currentTarget.dataset.nav
          })
        }
      },
      selectleft: function (e) {
    
        var model = e.target.dataset.model.childModel;
        var selectedId = e.target.dataset.model.id
        var selectedTitle = e.target.dataset.model.title;
        this.setData({
          dropDownMenuDataFirstRight: model==null?"":model,
          select1: selectedId,
          select2: '',
        })
        if (model == null || model.length == 0) {
          this.closeHyFilter();
          this.triggerEvent("selectedItem", { index: this.data.shownavindex, selectedId: selectedId, selectedTitle: selectedTitle })
        }
      },
      selectcenter: function (e) {
        var selectedId = e.target.dataset.model.id
        var selectedTitle = e.target.dataset.model.title;
        this.closeHyFilter();
        this.setData({
          select2: selectedId
        })
        this.triggerEvent("selectedItem", { index: this.data.shownavindex, selectedId: selectedId, selectedTitle: selectedTitle })
      },
      selectsqitem: function (e) {
        var selectedId = e.target.dataset.model.id
        var selectedTitle = e.target.dataset.model.title;
        this.closeHyFilter();
        this.setData({
          selectedSq: selectedId
        })
        this.triggerEvent("selectedItem", { index: this.data.shownavindex, selectedId: selectedId, selectedTitle: selectedTitle })
      },
      selecsortlitem: function (e) {
        var selectedId = e.target.dataset.model.id
        var selectedTitle = e.target.dataset.model.title;
        this.closeHyFilter();
        this.setData({
          selectedSort: selectedId
        })
        this.triggerEvent("selectedItem", { index: this.data.shownavindex, selectedId: selectedId, selectedTitle: selectedTitle })
      },
      selecqtlitem: function (e) {
        var selectedId = e.target.dataset.model.id
        var selectedTitle = e.target.dataset.model.title;
        this.closeHyFilter();
        this.setData({
          selectedQt: selectedId
        })
        this.triggerEvent("selectedItem", { index: this.data.shownavindex, selectedId: selectedId, selectedTitle: selectedTitle })
      },
      
      /**关闭筛选 */
      closeHyFilter: function () {
        if (this.data.hyopen) {
          this.setData({
            hyopen: false,
            sqopen: false,
            pxopen: false,
            sortopen: false,
          })
        } else if (this.data.sqopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
          })
        }
        else if (this.data.pxopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
          })
        }
        else if (this.data.sortopen) {
          this.setData({
            sqopen: false,
            pxopen: false,
            hyopen: false,
            sortopen: false,
          })
        }
      },
    },
    //组件生命周期函数,在组件实例进入页面节点树时执行
    attached: function () {
      // 可以在这里发起网络请求获取插件的数据

     
      
     
    },
  
  })

组件有两个重要属性propertiesdata
他们两者有什么区别呢?
properties是外部可以访问到的,比如我们这个筛选插件的一些初始值可以放在properties里,当我们调用的时候可以动态给其赋值
data是组件的一些内部数据,这些数据在组件内进行赋值或运算,并不需要外部来访问

json

{
  "component": true,
  "usingComponents": {}
}

自定义组件的json里面通常有着两个属性
component是指明这是一个组件,外部可以使用它
usingComponents顾名思义是这个组件里面使用的其他组件,我们如果在这个组件里面需要使用其他组件就要引用进来
例:我在index页面引用我自定义的筛选组件

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

wxml

二话不说直接上代码,大家复制即用

<view class="nav">
    <view class="nav-son {{hyopen? 'active' : ''}}" bindtap="listqy" data-nav="1">
      <view class="content">{{dropDownMenuTitle[0]}}</view>
      <view class="icon"></view>
    </view>
    <view class="nav-son borders {{sqopen? 'active' : ''}}" bindtap="list" data-nav="2">
      <view class="content">{{dropDownMenuTitle[1]}}</view>
      <view class="icon"></view>
    </view>
    <view class="nav-son borders-right {{pxopen? 'active' : ''}}" bindtap="listpx" data-nav="3">
      <view class="content">{{dropDownMenuTitle[2]}}</view>
      <view class="icon"></view>
    </view>
    <view class="nav-son {{sortopen ? 'active' : ''}}" bindtap="listsort" data-nav="4">
      <view class="content">{{dropDownMenuTitle[3]}}</view>
      <view class="icon"></view>
    </view>
  </view>




  <view class="quyu {{hyopen ? 'show' : 'disappear'}} ">
    <view class="qy quyu-left">
      <view class="{{select1 == item.id ? 'current' : ''}}" wx:for="{{dropDownMenuFirstData}}" bindtap="selectleft" data-model='{{item}}' wx:key="unique" >
        {{item.title}}
      </view>
    </view>
    <view class="qy quyu-center">
      <view class="{{select2 == item.id ? 'current2' : ''}}" wx:for="{{dropDownMenuDataFirstRight}}" bindtap="selectcenter" data-model='{{item}}' wx:key="unique">
        {{item.title}}
      </view>
    </view>
  </view>

  <view class="temp temp3 {{sqopen ? 'show' : 'disappear'}} ">
    <view class='tempheight'>
      <view>
        <block wx:for="{{dropDownMenuSecondData}}" wx:key="unique">
          <view class="sortitem {{selectedSq==item.id ? ' active ' : ' '}}" data-model='{{item}}' bindtap='selectsqitem'> {{item.title}}</view>
        </block>
      </view>
    </view>
  </view>
  <view class="temp temp3 {{pxopen ? 'show' : 'disappear'}} ">
    <view class='tempheight'>
      <view>
        <block wx:for="{{dropDownMenuThirdData}}" wx:key="unique">
          <view class="sortitem {{selectedQt==item.id ? ' active ' : ' '}}" data-model='{{item}}' bindtap='selecqtlitem'> {{item.title}}</view>
        </block>
      </view>
    </view>
  </view>
  <view class="temp temp3 {{sortopen ? 'show' : 'disappear'}} ">
    <view class='tempheight'>
      <view>
        <block wx:for="{{dropDownMenuFourthData}}" wx:key="unique">
          <view class="sortitem {{selectedSort==item.id ? ' active ' : ' '}}" data-model='{{item}}' bindtap='selecsortlitem'> {{item.title}}</view>
        </block>
      </view>
    </view>
  </view>

wxss

这里是样式文件,相当于css,也是直接复制

.page {
  width: 100%;
  height: 100%;
  background: #fff;
  overflow: hidden;
}
.position{position:absolute;}
.nav {
  position: relative;
  z-index: 99;
  display: flex;
  border-bottom: 1px solid #d1d3d4;
  background: #fff;
}

.nav-son {
  display: flex;
  flex: 1;
  text-align: center;
  height: 20px;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  margin: 20rpx 0;
}
.borders-right {
  border-right: 1px solid #e6e6e6;
}
.borders-left {
  border-left: 1px solid #e6e6e6;
}
.borders {
  border-left: 1px solid #e6e6e6;
  border-right: 1px solid #e6e6e6;
}

.content {
  display: inline-block;
}

.icon {
  display: inline-block;
  border: 4px solid transparent;
  border-top: 4px solid #9b9b9b;
  margin-left: 5px;
}

.temp {
  position: relative;
  z-index: 4;
  font-size: 14px;
}

.temp1 {
  display: flex;
  width: 100%;
  height: 600rpx;
  overflow-y: scroll;
  background: #e0e0e0;
  color: #666;
}



.slidedown {
  transform: translateY(0%);
}

.quyu {
  position: absolute;
  display: none;
  z-index: 5;
  width: 100%;
  height: 100%;
  overflow-y: scroll;
  background-color: rgba(0,0,0,0.5);
}

.quyu .qy {
  overflow-y: scroll;
  float: left;
  width: 50%;
  height: 600rpx;
  line-height: 80rpx;
  box-sizing: border-box;
  font-size: 14px;
  
}

.qy view {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
  padding-left: 15rpx;
}

.quyu-left {
  background: #F7F7F7;
}

.quyu-center {
  background: #fff;
}

.quyu-right {
  background: #fff;
}

.quyu-right view {
  border-bottom: 1px solid #c5c5c5;
}

.current {
  background: #fff;
}

.current2 {
  background: #fff;
  color: #fa871e;
}

.fullbg {
  position: fixed;
  top: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  background: rgb(1, 1, 1);
  transition: all 2s;
  opacity: 0;
}

.fullopacity {
  opacity: 0.2;
}

.nav-son.active .content {
  color: #fa871e;
}

.nav-son.active .icon {
  border-bottom: 4px solid #fa871e;
  border-top: 0;
}

@keyframes slidown {
  from {
    transform: translateY(-100%);
  }

  to {
    transform: translateY(0%);
  }
}

.slidown {
  display: block;
  animation: slidown 0.2s ease-in both;
}

@keyframes slidup {
  from {
    transform: translateY(0%);
  }

  to {
    transform: translateY(-100%);
  }
}

.tempheight {
  height: 600rpx;
  overflow-y: scroll;
  background: #fff; 
}

.slidup {
  display: block;
  animation: slidup 0.2s ease-in both;
}

.disappear {
  display: none;
}
.show {
  display: block;
}
.slidowntop {
  display: flex;
  flex-direction: row;
  padding: 20rpx 24rpx 10rpx 24rpx;
}

.emptyall {
  margin-left: 475rpx;
  color: #fa871e;
}

.emptyallright {
  width: 80rpx;
  text-align: center;
}

.endselect {
  width: 350rpx;
  text-align: left;
}

.return {
  margin-left: 200rpx;
  color: #fa871e;
}

.slidowncenter {
  margin-top: 20rpx;
  padding-top: 20rpx;
  padding-left: 24rpx;
  display: flex;
  flex-direction: row;
  align-content: space-between;
  border-top: solid #d1d3d4 1rpx;
}

.slidownbottom {
  margin-top: 10rpx;
  padding: 10rpx;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.sdbitem {
  width: 119rpx;
  text-align: center;
  border: solid #ccc 1rpx;
  margin: 12rpx;
  justify-content: space-between;
  padding: 12rpx 19rpx 12rpx 19rpx;
}

.emptyendcitys {
  padding-left: 12rpx;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}

.emptyendcitysitem {
  width: 120rpx;
  text-align: center;
  border: solid #ccc 1rpx;
  margin: 10rpx;
  justify-content: space-between;
  padding: 12rpx 18rpx 12rpx 18rpx;
}

.queding {
  width: 100%;
  height: 100rpx;
  background-color: #fa871e;
  color: #fff;
  text-align: center;
}

.queding {
  font-size: 18px;
  line-height: 100rpx;
}
.temp2 {
  width: 100%;
  height: 600rpx;
  overflow-y: scroll;
  background: #fff;
  color: #666;
}
.commanders{
  padding: 10rpx;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
}
.sdbitem.active{  
  color: #fa871e;  
  background-color: #F1E6B8;
}  

.sortitem {
  border-bottom: solid #F7F7F7 1rpx;
  justify-content: space-between;
  padding: 20rpx 30rpx;
}
.sortitem.active{  
  color: #fa871e;  
}  

.temp3 {
  width: 100%;
  height: 100%;
  position: absolute;
  overflow-y: scroll;
  background-color: rgba(0,0,0,0.5);
}

封装自定义api

所有api接口都可以做成一个通用功能,使用起来非常简单,
代码也很清爽,先看看结构图:
在这里插入图片描述

constant.js

这个js存放了api的一些基本配置,方便大家修改,大家可以根据实际情况酌情添加

exports.TOKEN ="USER_TOKEN"; //请求token
let ip = "XX.XXX.XXX.XX:8080";//服务器地址
exports.API_IP =ip;//请求的IP
exports.socketOpen =false;
let TEST = true; //是否测试状态
if(TEST){
  exports.API_IP ="http://127.0.0.1:8080"
}else{
  exports.API_IP ='http://${ip}';
}
exports.MTG_VERSION ="BATE1.0"//版本号




还有要说的一点,如果你想在本地测试你的接口,要在详情页面勾选不校验域名,否则你的ip是通不过的
在这里插入图片描述

api.js

这个js则存放了通用接口方法
大家先看看代码:

let CONSTANT = require('../api/constant')
    // 从本地存储Storage中获取token值
function getToken() {
    return wx.getStorageSync(CONSTANT.TOKEN);
}

// 创建请求头header的内容
function buildHeaders(isJson) {
    let headers = {
        "Content-Type": isJson ? 'application/json' : "application/x-www-form-urlencoded",
        "version": CONSTANT.MINI_VERSION,
    };
    const token = getToken();
    if (token) {
        headers["token"] = token;
    }
    return headers;
}

// 发起 HTTPS 网络请求。
let baseURL = CONSTANT.API_IP;

function fetchApi(baseURL, url, params, method, isJson) {
    // wx.getNetworkType判断网路类型。eg:wifi、2g、3g...;none值表示无网路
    wx.getNetworkType({
        success: function(res) {
            // &&表示“并”"none" === e.networkType如果为真,才会去执行&&后面的内容,否则不执行
            "none" === res.networkType && (wx.hideLoading(), wx.showModal({
                title: "提示",
                content: "当前无网络,请检查网络设置后重新加载",
                showCancel: false
            }));
        }
    });
    return new Promise((resolve, reject) => {
     
        wx.request({
            url: `${baseURL}${url}`,
            method: method,
            header: buildHeaders(isJson),
            data: params,
            success: function(res) {
                // 成功返回statusCode参数表示开发者服务器返回的 HTTP 状态码
                // 统一拦截提示错误
                // var o = res.statusCode;
                // if (o !== 200 && [21020000, 41020001, 41020003, 21020002].indexOf(res.data.status) == -1) {
                //     wx.hideLoading();
                //     wx.showModal({
                //         title: "提示",
                //         content: res.data.msg
                //     });
                //     return;
                // } 2020.3.9
                // 41020001表示未登录那就要去拿code值
                // 21020002表示登录超时
                // 并重新请求获取token值
                if (41020001 == res.data.status || 21020002 === res.data.status) {
                    wx.login({
                        success: res => {
                            wx.request({
                                url: baseURL + "/api/user/login",
                                method: "GET",
                                header: {
                                    "token": "",
                                    "version": CONSTANT.MINI_VERSION,
                                },
                                data: {
                                    code: res.code,
                                },
                                success: function(res) {
                                    wx.removeStorageSync(CONSTANT.TOKEN);
                                    if (21020000 === res.data.status) {
                                        wx.setStorageSync(CONSTANT.TOKEN, res.data.data);
                                        console.log("already refresh token");
                                        fetchApi(url, url, params, method);
                                    }
                                }
                            });
                        }
                    });
                }
                // 41020003表示未授权了直接跳转到授权页(请求授权获取用户信息)
                else if (41020003 == res.data.status) {
                    wx.redirectTo({
                        url: "/pages/accredit/accredit"
                    });
                } else {
                    resolve(res.data);
                }
            },
            fail: function(res) {
                reject(res.data);
                console.log("network fail.", res);
            },
            complete: function(res) {
        
                resolve(res.data);
                // console.log('complete', res);
            }
        });
    });
};
function setlocation(baseURL, url,  method) {

    wx.request({
        url: `${baseURL}${url}`,
        method: method,
        success: function (res) {
            return res.data;
          
        },
        fail: function () {
            doFail();
        },
    })
};
module.exports = {
    // 定义各种api的方法
    register(params) {
        return fetchApi(baseURL, '/api/index', params, 'GET');
    },
    setlocation() {
        return fetchApi(baseURL, '/filter', '11', 'GET','true');
    },
}

在这里面的module.exports我们可以定义我们要封装的各种接口,和各种异常的统一处理机制,如果大家有兴趣了解ES6 Promise用法,可以移步
异步机制-Promise用法小结
我在这里就不多赘述了

页面引用组件并通过定义的api进行赋值

index.json

很简单,在json里引入我们封装的筛选组件

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

}

index.wxml

这里非常简单,只需要一行代码即可搞定,是不是看起来清爽许多?

filter dropDownMenuFirstData ="{{filterFirst}}"></filter>

index.js

在js里面,我们就要对自定义组件进行赋值了,
dropDownMenuFirstData
组件的这个属性,就是点击按钮展示的父级和子集数据,其他属性也大同小异,我就只写一种来举例

var api = require("../../api/api")
Page({
  data: {
    filterFirst:[],
  },

首先在index.js里面引入我们封装的api
然后在初始属性中初始化我们的参数
注意:传入的参数要和组件里面定义的类型一致
我在组件里面定义的是array,自然要初始化为数组

onLoad: function () {
    
    var that = this;
    api.setlocation().then(res => {
      var firstValue =res.data;
      console.log(res.data);
        this.setData({
          filterFirst:[firstValue]
       })
    })
  },

在load里面对组件进行赋值,赋值根据实际情况决定,大家也可以不写在onload里面
**api.setlocation()**这是调用我们之前封装好的接口
**then(res => {**这里是接收Promise.resolve的返回值
**filterFirst:[firstValue]**这是对array对象进行赋值,
注意,这里要构造array对象,我先给大家展示一下数组结构

[
			{"title" :"嘟嘟喵",
            "childModel":[{"title" :"嘟嘟喵起床",
                         "id" :"ddmqc"},{"title" :"嘟嘟喵睡觉",
                         "id" :"ddmsj"},{"title" :"嘟嘟喵要抱",
                         "id" :"ddmyc"}],
            "id" :"dudum"
            },
            {"title" :"小兔子",
            "childModel":[{"title" :"小兔子起床",
                         "id" :"xtzqc"}],
            "id" :"xtz"
            },  
            {"title" :"爬爬龟",
            "childModel":[{"title" :"爬爬龟起床",
                         "id" :"papgqc"}],
            "id" :"papg"
            }
    ]

这就是展示需要的数组结构,大家在后端构造好传入前端即可
到现在,我们的筛选已经实现了二级联动和从数据库取值的操作了!!
完结撒花

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值