微信小程序全局组件的定义

项目场景:

在做项目中,当我们写到一些共用的js代码时,为了去耦合实现模块化,会把共用js代码提取出来封装好,哪里需要使用到的引用一下就好了。同理的,在小程序开发中,为了精简化项目,我们可以把共用的一部分代码(比如说登录弹窗、活动状态弹窗等)提取出来,写成组件,需要用到的页面引入一下就好了。


Demo演示:

为了方便演示父页与子组件间的数据传输,我写了个简化版的全局登录弹窗,具体可以看下面的GIF

在这里插入图片描述


代码部分:

项目结构: 我们先看下目录的具体结构,一般情况下创建的组件都会放到components文件夹下,需要注意的是创建组件时右键点击的是新建Component,别点错了不是Page。
在这里插入图片描述

① page(父页)

index.json: 当我们创建好组件后,想要引入它,那么需要在父页的json文件里引入它,需要注意一下文件夹路径

{
  "usingComponents": {
    "login": "../../components/login/login"
  },
  "navigationBarTitleText": "全局登录"
}

index.wxml:引入之后,我们就可以以标签的形式去使用了,text:为自定义的组件属性,用于演示把父页的参数传到组件中;updateUserData:当登录成功想要把数据从子组件传回父页的,就需要用bind绑定一个函数来接收参数

<view class="body">
  <view class="row">名字:{{userData.name}}</view>
  <view class="row">爱好:{{userData.hobby}}</view>
  <button bindtap="clickLogin" type="primary">点击登录</button>
</view>

<!-- 自定义组件-登录弹窗 -->
<login id="login" text="222" bind:updateUserData="updateUserData"></login>

index.js:接着来看下js部分,当点击登录按钮时,需要调用子组件的方法把弹窗打开,那么就需要用到selectComponent()来指定组件,之后用.的形式调用子组件的方法就行了。要更新父页的参数,只需要在绑定的函数(updateUserData)的形参里接收一下更新就好

Page({

  /**
   * 页面的初始数据
   */
  data: {
    // 用户信息
    userData: {}
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

  },

  // 点击登录按钮
  clickLogin() {
    // 调用子组件方法,调起获取用户数据弹窗
    this.selectComponent("#login").openLoginWin("111")
  },

  /*
   * 登录弹窗子组件拿到用户信息后触发的事件
   * 用于更新父组件的用户信息
   */
  updateUserData(e) {
    console.log("子组件函数传过来的值:" +  JSON.stringify(e.detail.userData))
    this.setData({
      userData: e.detail.userData
    })
  },

})

index.wxss:

.body{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

.row{
  margin-bottom: 40rpx;
}

② component(子组件)

login.json:

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

login.wxml:弹窗的图片自己下载一下,重命名放到images文件夹就好

<!-- 遮罩层 -->
<view class="mask-layer" wx:if="{{isShowLoginWin}}" bindtap='closeLoginWin'></view>
<!-- 授权微信弹窗 -->
<view class='login-block' wx:if="{{isShowLoginWin}}" animation='{{animationTranslateY}}'>
  <!-- 内容 -->
  <view class="container">
    <image bindtap='closeLoginWin' class="close" src="../../images/close.png"></image>
    <button bindtap="getUserData" class="btn">
      <image class="logo" src="../../images/wx.png"></image>
      微信快速登录
    </button>
  </view>
</view>

login.js:接着来看下组件的js,properties属性列表就是用来存放父页中子标签传过来的值,需要注意的是每一个属性都需定义类型,之后就可以在子组件中直接使用了;接着有个专门用来放方法的地方methods,当父页调用开启弹窗的方法(openLoginWin)后,就可以在形参里获取到父页穿过来的值,同样的也可以直接使用组件的属性值,弹窗的上下滑动动画可以忽略;最后当用户点击确认获取到数据后,使用triggerEvent("函数名","参数")方法就可以调用父页的函数把参数传回去了。

Component({
  /**
   * 组件的属性列表
   */
  properties: {
    text: {
      type: String, // 属性需定义类型
      value: ''
    },
    // text: String // 简写
  },

  /**
   * 组件的初始数据
   */
  data: {
    // 是否显示登录弹窗
    isShowLoginWin: false
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 打开上滑弹窗
    openLoginWin: function (e) {
      console.log("父页函数传过来的值:" + e)
      console.log("父页中子标签绑定的值:" + this.properties.text)

      // 自定义上滑开启动画
      let animation = wx.createAnimation({
        duration: 300,
        timingFunction: 'linear'
      })
      animation.translateY(300).step()
      this.setData({
        animationTranslateY: animation.export(),
        isShowLoginWin: true
      })
      //实现有感觉的滑动
      setTimeout(() => {
        animation.translateY(0).step()
        this.setData({
          animationTranslateY: animation.export(),
        })
      }, 100)
    },

    //关闭上滑弹窗
    closeLoginWin: function () {
      // 自定义下滑关闭动画
      var animation = wx.createAnimation({
        duration: 300,
        timingFunction: 'linear'
      })
      this.animation = animation
      animation.translateY(500).step()
      this.setData({
        animationTranslateY: animation.export(),
      })
      // 让动画执行完再关闭
      setTimeout(() => {
        animation.translateY(0).step()
        this.setData({
          animationTranslateY: animation.export(),
          isShowLoginWin: false
        })
      }, 300)
    },

    // 获取用户信息
    getUserData(e) {
      /**
       * do something ···
       * 从这开始假设已经获取到用户信息
       */
      let userData = {
        name: 'weianl',
        hobby: '睡大觉'
      }
      // 关闭弹窗
      this.setData({
        isShowLoginWin: false,
      })
      // 调用父页函数并把信息传回去
      this.triggerEvent('updateUserData', {
        userData: userData
      })
      wx.showToast({
        title: '登录成功!',
      })
    }

  }

})

login.wxss:

/* 遮罩 */
.mask-layer {
  z-index: 9998;
  position: fixed;
  top: 0;
  width: 100%;
  height: 100%;
  background-color: #000;
  opacity: 0.5;
}

/* 滑块高度 */
.login-block {
  z-index: 9999;
  position: fixed;
  bottom: 0;
  width: 100%;
  height: 240rpx;
  background-color: #fff;
  border-radius: 40rpx 40rpx 0 0;
}

/* 滑块内容 */
.login-block .container {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  margin: 0 auto;
  box-sizing: border-box;
  background-color: #fff;
  border-radius: 40rpx 40rpx 0 0;
}

.login-block .container .close {
  position: absolute;
  top: 0;
  left: 50%;
  margin-left: -45rpx;
  margin-top: -135rpx;
  width: 90rpx;
  height: 90rpx;
}

.login-block .container .btn {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 540rpx !important;
  height: 100rpx !important;
  background-color: #46BB36;
  color: white;
  border-radius: 100rpx;
}

.login-block .btn .logo {
  width: 50rpx;
  height: 50rpx;
  margin-right: 15rpx;
}

over~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值