微信小程序学习

微信小程序UI之旅:便捷的搜索框组件

2019-04-15  本文已影响0人  码途有道

前言

做小程序开发有段时间了,开发中遇到各种各样的UI需求,很多都是类似甚至重复。虽然可以使用templateinclude来实现代码复用,但是它们都没有逻辑处理能力,有时一些简单的逻辑,我们更加希望可以直接被模板内部实现掉,所以更好的方法是直接封装成组件,最大程度的实现代码复用。

本文及后续一系列文章将会介绍常用UI组件的封装,方便今后开发中使用,所有样式源码及示例将提交至开源项目wx-abui

搜索框组件:ab-search-bar

搜索框是常用组件之一,也是本文封装的对象。在封装时我主张对外暴露出常用的属性和方法,以便在项目中重复使用时减少对源码的修改。

github传送门:https://github.com/albert-lii/wx-abui/tree/master/widgets/ab-search-bar
demo传送门:https://github.com/albert-lii/wx-abui/tree/master/pages/mainex

样式示例

搜索框样式
搜索框样式

自定义属性和方法

自定义属性 描述
placeholder 搜索框中的提示字
value 搜索框的内容
自定义方法 描述
bindinput 输入监听
bindclear 清除内容按钮点击监听
bindback 返回按钮点击监听
bindsearch 搜索按钮点击监听

使用示例

<view class="container">
  <!-- 搜索框 -->
  <ab-search-bar placeholder="请输入关键字" value="{{searchValue}}" bindinput="searchInput" bindsearch="searchTab" bindclear="searchClear" />
</view>
const LABEL_SOURCE = require('../../utils/label_flow_source.js');

Page({

  data: {
    searchValue: ''
  },

  /*=========================================================
   * 搜索框相关
   *=========================================================*/
  /**
   * 搜索框输入监听
   */
  searchInput: function (e) {
    console.log('searchInput >>> ' + e.detail.value);
  },
  /**
   * 搜索框清除监听
   */
  searchClear: function (e) {
    console.log('searchClear');
  },
  /**
   * 搜索框右侧按钮点击监听
   */
  searchTab: function (e) {
    let _key = e.detail.key;
    let _value = e.detail.value;
    if (_key === 'search') {
      console.log('searchTab >>> search');
      console.log(e.detail);
    } else if (_key === 'back') {
      console.log('searchTab >>> back');
      console.log(e.detail);
    }
  }
})
{
  "navigationBarTitleText": "abui",
  "usingComponents": {
    "ab-search-bar": "../../abui/widgets/ab-search-bar/ab-search-bar"
  }
}

源码

<view class="ab-search-bar">
  <view class="ab-search-bar__box">
    <icon class="ab-search-bar__icon" type="search" size="{{iconSize}}" />
    <view class="ab-search-bar__divider" />
    <input class="ab-search-bar__input" type="text" placeholder="{{placeholder}}" value="{{value}}" bindinput="_searchInput" bindconfirm="_searchConfirm" confirm-type="search" />
    <view class="ab-search-bar__icon-clear" wx:if="{{value.length > 0}}" bindtap="_searchClear">
      <icon type="clear" size="{{iconSize}}" />
    </view>
  </view>
  <view class="ab-search-bar__search-btn" bindtap="_searchConfirm" data-key="{{value.length > 0?'search':'back'}}">{{value.length > 0?'搜索':'返回'}}
  </view>
</view>
.ab-search-bar {
  position: relative;
  display: flex;
  width: 100%;
  padding: 9rpx 15rpx;
  box-sizing: border-box;
  border-top: 1rpx solid #d7d6dc;
  border-bottom: 1rpx solid #d7d6dc;
  background-color: #ececec;
}

.ab-search-bar__box {
  position: relative;
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  padding-left: 15rpx;
  padding-right: 15rpx;
  box-sizing: border-box;
  border-radius: 4px;
  border: 1rpx solid #e6e6ea;
  background: #fff;
}

.ab-search-bar__icon {
  position: relative;
  margin-right: 15rpx;
  font-size: 0;
}

.ab-search-bar__divider {
  position: relative;
  width: 1px;
  height: calc(100% - 20rpx);
  margin-right: 15rpx;
  background-color: #aaa;
}

.ab-search-bar__input {
  width: 100%;
  height: 50rpx;
  font-size: 25rpx;
  line-height: 50rpx;
  color: #2e2e2e;
}

.ab-search-bar__icon-clear {
  position: relative;
  display: flex;
  align-items: center;
  height: 100%;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  padding-left: 15rpx;
  box-sizing: content-box;
}

.ab-search-bar__search-btn {
  font-size: 32rpx;
  line-height: 64rpx;
  text-align: center;
  margin-left: 15rpx;
  color: #2e2e2e;
  white-space: nowrap;
}
{
  "component": true,
  "usingComponents": {}
}
Component({
  properties: {
    // 搜索框的提示字
    placeholder: {
      type: String,
      value: '请输入搜索内容',
    },
    // 搜索框的初始内容
    value: {
      type: String,
      value: ''
    }
  },

  data: {
    // icon 的大小
    iconSize: 15
  },

  attached() {
    try {
      let _screenWidth = wx.getSystemInfoSync().screenWidth;
      this.setData({
        iconSize: Math.round(_screenWidth / 750 * 25)
      });
    } catch (e) {
      console.error(e);
    }
  },

  methods: {
    /**
     * 输入事件
     */
    _searchInput: function(e) {
      // 输入的内容
      let _value = e.detail.value;
      this.setData({
        value: _value
      });
      this.triggerEvent('input', {
        value: _value
      });
    },
    /**
     * 清除输入内容事件
     */
    _searchClear: function(e) {
      this.setData({
        value: ''
      });
      this.triggerEvent('clear', {});
    },
    /**
     * 搜索/返回 事件
     */
    _searchConfirm: function(e) {
      let _key = e.target.dataset.key;
      if (_key === 'back') {
        this.setData({
          value: ''
        });
      }
      this.triggerEvent('search', {
        key: _key,
        value: this.data.value
      });
    }
  }
})
上一篇下一篇

猜你喜欢

热点阅读