微信小程序component父子组件传值

在某些场景,用到组件还是比较多的。例如,在页面的底部有一个悬浮,悬浮分两种,每种里边有四个按钮,每个按钮分为登录和没登录两个状态,点击每个按钮绘根据后台传的值的状态不同分别请求不同的接口(当然了,有些处理完页面也可能是跳转,或者跳转webview,或者reLaunch某个页面......)。总之一句话,这个底部悬浮比较麻烦,考虑的场景比较多,然后呢,好多页面都会用到,不用写那么多的重复代码,写好一个组件,大家都来调用,用的简单,维护也简单。

下边我用一个简单的场景来举例,复杂场景原理相同,只不过是根据业务场景再做处理即可。

我的场景:页面中的按钮存在登录和未登录两个状态,组件中的按钮也存在这两个状态,任何一处授权登录过了,整个小程序的登录状态都会改变。此时若把父组件的登录状态改变,就要传给子组件;子组件的登录状态改变,父组件也跟着变。但父子组件又相互独立,此时就要通过某种方式来相互传值。

1.组件('component/btn/btn’)

1.1.wxml

<view wx:if="{{isLogin}}" class='btn' catchtap='clickme'>子  组件的view</view>

<button wx:if="{{!isLogin}}" class='btn' open-type="getPhoneNumber" lang="zh_CN" bindgetphonenumber="getPhoneNumber">子 组件的button</button>

1.2.wxss

.btn{
  width: 250rpx;
  height: 50rpx;
  line-height: 50rpx;
  text-align: center;
  background-color: orange;
  font-size: 20rpx;
  color: #fff;
  margin-left: 0;
  border-radius: 10rpx;
  padding: 0 20rpx;
  box-sizing: border-box;
  margin: 20rpx 20rpx;
}

.btn::after{
  border: 0;
}

1.3js

const app = getApp();
Component({
  behaviors: [],
  // 属性定义(详情参见下文)
  properties: {
    isLogin: {
      type: Number,
      value: 0,
    }
  },
  data: {

  }, // 私有数据,可用于模板渲染

  lifetimes: {
    // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
    attached: function () {
      // console.log(111111111111)
      var that = this;
    },
    moved: function () {
      // console.log(2222222222222)
    },
    detached: function () {
      // console.log(3333333333333)
    },
  },

  // 生命周期函数,可以为函数,或一个在methods段中定义的方法名
  attached: function () {
    // console.log(4444444444444)
  }, 
  ready: function () {
    // console.log(5555555555555555)

  },

  pageLifetimes: {
    // 组件所在页面的生命周期函数
    show: function () {
      // console.log(666666666666666666)
      var that = this;
    },
    hide: function () {
      // console.log(777777777)
    },
    resize: function () {
      // console.log(88888888888888)
    },
  },

  methods: {
    clickme(e,aa='子请求接口'){
      console.log(aa)
    },
    getPhoneNumber: function (e) {
      var that = this;
      if (e.detail.errMsg == "getPhoneNumber:ok") {
        var param = {
          iv: e.detail.iv,
          encryptedData: e.detail.encryptedData,
          logintype: 2
        }

        /**logintype:2时授权登录**/
        that.setData({
          isLogin: true,
        });

        that.clickme(e,'子授权后请求接口')

        var loginState = {
          isLogin: 1
        };
        that.triggerEvent("triggerBottom", loginState);
      } else {
        wx.showToast({
          title: '子授权失败',
          icon: 'none',
          duration: 3000
        });
      }

    },
  },
});

1.4json

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

2.调用组件的文件

2.1wxml

<view wx:if="{{isLogin}}" class='btn'>父  组件的view</view>

<button wx:if="{{!isLogin}}" class='btn' open-type="getPhoneNumber" lang="zh_CN" bindgetphonenumber="getPhoneNumber">父  组件的button</button>

<fixbottom isLogin="{{isLogin}}" bind:triggerBottom="triggerBottom"></fixbottom>

2.2wxss

.btn{
  width: 250rpx;
  height: 50rpx;
  line-height: 50rpx;
  text-align: center;
  background-color: orange;
  font-size: 20rpx;
  color: #fff;
  margin-left: 0;
  border-radius: 10rpx;
  padding: 0 20rpx;
  box-sizing: border-box;
  margin: 20rpx 20rpx;
}

.btn::after{
  border: 0;
}

2.3js

var that;
Page({

  /**
   * 页面的初始数据
   */
  data: {
    isLogin: 0
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    that = this;
  },

  triggerBottom(e) {
    var isLogin = e.detail.isLogin == 1 ? e.detail.isLogin : 0;
    that.setData({
      isLogin: isLogin
    });
  },
  clickme(e, aa = '父请求接口') {
    console.log(aa)
  },
  getPhoneNumber: function(e) {
    var that = this;
    if (e.detail.errMsg == "getPhoneNumber:ok") {
      var param = {
        iv: e.detail.iv,
        encryptedData: e.detail.encryptedData,
        logintype: 2
      }

      /**logintype:2时授权登录**/
      that.setData({
        isLogin: true,
      });

      that.clickme(e, '父授权后请求接口')

    } else {
      wx.showToast({
        title: '父授权失败',
        icon: 'none',
        duration: 3000
      });
    }

  },
})

2.4json

{
  "usingComponents": {
    "fixbottom": "/component/btn/btn"
  }
}

3.说明

3.1小程序和vue类似,双向数据绑定,组件其实就是一个标签,在这个标签上可以绑定一个数据,可以绑定一个事件,当然了,这个绑定的数据(或者事件)都须要遵从组件的规则。

3.2 父集向子集传值,直接传就好了,父集变子集跟着变。子集的值变,要想派发给父集,必须通过‘triggerEvent’来实现,派发出去。

3.3 现在的组件生命周期好像存在一些问题,第一次进入只执行了lifetimes里的attached和ready两个,pageLifetimes里的show没执行,看文档的意思pageLifetimes应该是和页面的声明周期同步,但没有(可能是个bug吧,嘻嘻)。但当页面被back时会执行show生命周期(感觉还是有点不靠谱)。

3.4对于一进页面和back回来都需要检测登状态(或者其他的状态值的)建议在attached中执行一次接口请求,然后再show中也执行一次(如果这个值在缓存中,可以做一个判断,如果为真就不再请求,否则会请求),不然就会不靠谱,哈哈。

3.5在写回调方法时,注意一下写法,否则会出现意想不到的惊喜哦

  dayin(aa='默认参数'){
    console.log(aa)
  },
  dioyong(cb) {
    typeof cb == "function" && cb();
  },

  right(cb) {
    var that = this;
    this.dioyong(function(){
      that.dayin('this is right')
    });
  },
  wrong() {
    var that = this;
    this.dioyong(that.dayin('this is wrong'))
  }

例如上边的right方法和wrong方法,看着好像都对,你自己在本地调用运行一下。

直接写结论了,right方法确确实实是当回调函数来执行的,wrong方法并不是,尤其是在接口调用,涉及接口调用顺序的情况就会出错。wrong里的调用,加了括号,相当于函数调用语句直接执行了,就没走  typeof cb == "function" && cb() 。而right确实是一个function(哈哈,应该是这个原因吧)。

猜你喜欢

转载自blog.csdn.net/hangGe0111/article/details/101193892
今日推荐