微信小程序 标题栏封装

141 阅读1分钟

wxml

<view class="navigation-bar">
  <view class="navigation-bar__inner {{ios ? 'ios' : 'android'}}" style="margin-top: {{statusBarHeight}}px; color: {{color}};background: {{background}}">
    <view class='navigation-bar__left' style="width: {{sideWidth}}px;">
      <block wx:if="{{back}}">
        <view class="navigation-bar__buttons" bindtap="back">
          <image class="navigation-bar__button navigation-bar__btn_goback" hover-class="active" src="../../images/back-arrow.png"></image>
        </view>
      </block>
      <block wx:else>
        <slot name="left"></slot>
      </block>
    </view>
    <view class="navigation-bar__center {{title ? 'title' : ''}}">
      <view wx:if="{{loading}}" class="navigation-bar__loading">
        <view class="loading"></view>
      </view>
      <block wx:if="{{title}}">{{title}}</block>
      <block wx:else>
        <slot name="center"></slot>
      </block>
    </view>
    <view class='navigation-bar__right' style="width: {{sideWidth}}px;">
      <slot name="right"></slot>
    </view>
  </view>
</view>

js

Component({
  options: {
    multipleSlots: true, // 在组件定义时的选项中启用多slot支持
  },
  /**
   * 组件的属性列表
   */
  properties: {
    title: {
      type: String,
      value: '',
    },
    background: {
      type: String,
      value: '',
    },
    color: {
      type: String,
      value: '',
    },
    back: {
      type: Boolean,
      value: true,
    },
    loading: {
      type: Boolean,
      value: false,
    },
    // back为true的时候,返回的页面深度
    delta: {
      type: Number,
      value: 1,
    },
    sideWidth: {
      type: Number,
      value: 0,
    },
  },

  attached() {
    const isSupport = !!wx.getMenuButtonBoundingClientRect;
    const rect = wx.getMenuButtonBoundingClientRect ? wx.getMenuButtonBoundingClientRect() : null;
    wx.getSystemInfo({
      success: (res) => {
        const ios = !!(res.system.toLowerCase().search('ios') + 1);
        const sideWidth = isSupport ? res.windowWidth - rect.left : 0;

        this.setData({
          ios,
          sideWidth: this.data.sideWidth || sideWidth,
          statusBarHeight: res.statusBarHeight,
        });
      },
    });
  },
  /**
   * 组件的方法列表
   */
  methods: {
    back() {
      const { data } = this;
      if (data.delta) {
        wx.navigateBack({
          delta: data.delta,
        });
      }
      this.triggerEvent('back', { delta: data.delta }, {});
    },
  },
});

css

.navigation-bar {
  background-color: #f7f7f7;
}

.navigation-bar .android {
  height: 48px;
}

.navigation-bar__inner {
  height: 44px;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.navigation-bar__inner .navigation-bar__left {
  position: relative;
  padding-left: 16px;
  height: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.navigation-bar__inner .navigation-bar__left .navigation-bar__buttons {
  height: 100%;
  flex-direction: row;
  align-items: center;
  min-width: 50px;
}

.navigation-bar__inner .navigation-bar__left .navigation-bar__btn {
  display: inline-block;
  vertical-align: middle;
  background-repeat: no-repeat;
  height: 100%;
  flex-direction: row;
  align-items: center;
}

.navigation-bar__inner .navigation-bar__left .navigation-bar__btn_goback {
  width: 8px;
  height: 14px;
}

.navigation-bar__inner .navigation-bar__center {
  font-size: 17px;
  text-align: center;
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.navigation-bar__inner .navigation-bar__center.title {
  display: inline-block;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

.navigation-bar__inner .navigation-bar__loading {
  margin-right: 4px;
  display: inline-flex;
  align-items: center;
}

.navigation-bar__inner .navigation-bar__loading .loading {
  margin-left: 0;
}

.navigation-bar__inner .navigation-bar__right {
  padding-right: 16px;
}