第二篇:自定义组件——购物车控件

本文将结合案例,来阐述自定义组件实现。点击我查看完整项目
先来上图

自定义控件.png

这个是一个购物车的数量组件。主要思路:
1、可以手动的输入具体的数量
2、可自定义设置最小值、和最大值。当是最小值时,“-”号置灰,并不可点击。当是最大值时,“+”号置灰,并不可点击。
3、当手动输入“0”开头的数字时,自行过滤,禁止输入,只值输入非0数字。
4、当手动输入数字大于最大值时,输入框失去焦点,默认将输入值置为最大值。或者当手动输入数字小于最小值时,输入框失去焦点,默认将输入值置为最小值
5、如果属性值minNum最小值、或者maxNum最大值设置为NaN,则表示最小值和最大值的大小没有输入的限制
6、默认最小值和最大值是没有限制的,可以随便输入

一、使用自定义组件的方式

1、js文件中:

输入框数值变化最终响应的函数
  showNumber: function (e) {
    var num = e.detail.num
  },

2、json文件中:

{
  "usingComponents": {
    /**
    *  key:自定义组件的别名,在使用组件时用到。相当于Android自定义控件在xml文件中的申明的命名空间
    *  value: 自定义组件的全路径
    */
    "component-option-num": "/component/optionNumber-component/optionNumber-component"
  }
}

3、wxml文件中:

 1、这里设置了最小值是0,最大值是20。
 2、bindoptionNum:是由bind+"optionNum"自定义组件回调函数的名称组成。当自定义组件的函数回调是,这个属性指定的方法bindoptionNum将被响应。并可以获取传入的值
 <component-option-num bindoptionNum="showNumber" minNum="0" maxNum="20"></component-option-num>

一、自定义组件的定义

1、 对外提供的自定义属性值

  /**
   * 组件的属性列表
   */
  properties: {
  //最小值
     minNum:{
       type:Number,
       value: NaN
     },
//最大值
     maxNum:{
       type:Number,
       value:NaN
     },
  },

2、 组件内部使用的数据

  /**
   * 组件的初始数据
   */
  data: {
    num: 0,                //输入框显示的数量
    disabledMin: false,    //"-"是否可点击,true 不能点击
    disabledMax:false    //"+"是否可点击,true 不能点击
  },

3、 增加数量方法

   _add: function (e) {
      let num = parseInt(this.data.num) + 1
      if (this.checkIsMaxNum(num)) {       
     /**
       * 大于最大数值,将输入框的值设置为最大值,
       * 且"+"不能点击、"-"可点击
       */ 
        num = this.data.maxNum
        this.data.disabledMax = true 
        this.data.disabledMin = false
      }else {
        this.data.disabledMin = false
        this.data.disabledMax = false 
      }
      
      this.setData({
        num: num,
        disabledMin: this.data.disabledMin,
        disabledMax: this.data.disabledMax
      })
      //回调optionNum方法,将输入框num值传递给使用该组件的函数
      this.triggerEvent('optionNum', { num: num })
    },

4、减少数量

    _reduce: function (e) {
      let num, disabledMin, disabledMax
      num = parseInt(this.data.num) - 1
      if (this.checkIsMinNum(num)) { //小于最小数
       /**
     * 小于最小数值,将输入框的值设置为最小值,
     * 且"-"不能点击、"+"可点击
     */ 
        num = this.data.minNum
        disabledMin = true
        disabledMax = false
      }else{
        disabledMin = false
        disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: disabledMin,
        disabledMax: disabledMax
      })
      //回调optionNum方法,将输入框num值传递给使用该组件的函数
      this.triggerEvent('optionNum',{num:num})
    },

5、手动输入数量

    _input: function (e) {
      let val = e.detail.value
      //1、先用正则校验输入的第一个数字,当手动输入“0”开头的数字时,自行过滤,禁止输入,只值输入非0数字
      var num = val.replace(/^[0]+[0-9]*$/gi, "")
       /**
     * 大于最大数值,将输入框的值设置为最大值,且"+"不能点击、"-"可点击。反之亦然
     */ 
      if (this.checkIsMinNum(num)) {  //小于最小数
        this.data.disabledMin = true
        this.data.disabledMax = false
      } else if (this.checkIsMaxNum(num)) {    //大于最大数
        this.data.disabledMax = true
        this.data.disabledMin = false
      } else {
        this.data.disabledMin = false
        this.data.disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: this.data.disabledMin,
        disabledMax:this.data.disabledMax
      })
      this.triggerEvent('optionNum', { num: num })
    },

6、失去焦点

  _blur:function(e){
      let val = e.detail.value
      let num = val.replace(/^[0]+[0-9]*$/gi, "")
      let disabledMin, disabledMax
      if (this.checkIsMinNum(num)) {    //输入的数量 小于最小的数,则输入框显示最小值
        num = this.data.minNum
        disabledMin = true
        disabledMax = false
      } else if (this.checkIsMaxNum(num)) {     //输入的数量 大于最大的数,则输入框显示最大值
        this.data.disabledMax = true
        num = this.data.maxNum
        disabledMin = false
        disabledMax = true
      } else {     //输入的数量 大于最小的数,则输入框显示输入值
        disabledMin = false
        disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: disabledMin,
        disabledMax: disabledMax
      })
      this.triggerEvent('optionNum', { num: num })
    },

附自定义组件的全部代码

1、js中的代码

// component/optionNumber-component/optionNumber-component.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
     minNum:{
       type:Number,
       value: NaN
     },

     maxNum:{
       type:Number,
       value:NaN
     },
  },

  /**
   * 组件的初始数据
   */
  data: {
    num: 0,
    disabledMin: false,
    disabledMax:false
  },

  lifetimes:{
    // 初始化数据
    attached:function(){
      let num, disabledMin, disabledMax
      if (this.checkIsMinNum(this.data.num)) { //小于最小数
        num = this.data.minNum
        disabledMin = true
        disabledMax = false
      } else if (this.checkIsMaxNum(this.data.num)){     //大于最大数
        num = this.data.maxNum
        disabledMax = true
        disabledMin = false
      }else {
        num = this.data.num
        disabledMin = false
        disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: disabledMin,
        disabledMax: disabledMax
      })
    },
  },


  /**
   * 组件的方法列表
   */
  methods: {
    // 减少数量
    _reduce: function (e) {
      // console.log("_reduce======", this.data.maxNum)
      let num, disabledMin, disabledMax
      num = parseInt(this.data.num) - 1
      if (this.checkIsMinNum(num)) { //小于最小数
        num = this.data.minNum
        disabledMin = true
        disabledMax = false
      }else{
        disabledMin = false
        disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: disabledMin,
        disabledMax: disabledMax
      })
      // console.log("disabledMin======", this.data.disabledMin)
      this.triggerEvent('optionNum',{num:num})
    },

    // 增加数量
    _add: function (e) {
      let num = parseInt(this.data.num) + 1
      // console.log("_add======", this.data.maxNum)
      if (this.checkIsMaxNum(num)) {        //大于最大数
        num = this.data.maxNum
        this.data.disabledMax = true 
        this.data.disabledMin = false
      }else {
        this.data.disabledMin = false
        this.data.disabledMax = false 
      }
      this.setData({
        num: num,
        disabledMin: this.data.disabledMin,
        disabledMax: this.data.disabledMax
      })
      this.triggerEvent('optionNum', { num: num })
    },


    // 手动输入数量
    _input: function (e) {
      let val = e.detail.value
      var num = val.replace(/^[0]+[0-9]*$/gi, "")
      if (this.checkIsMinNum(num)) {  //小于最小数
        this.data.disabledMin = true
        this.data.disabledMax = false
      } else if (this.checkIsMaxNum(num)) {    //大于最大数
        this.data.disabledMax = true
        this.data.disabledMin = false
      } else {
        this.data.disabledMin = false
        this.data.disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: this.data.disabledMin,
        disabledMax:this.data.disabledMax
      })
      this.triggerEvent('optionNum', { num: num })
    },

  // 失去焦点
    _blur:function(e){
      // console.log("_confirm======")
      let val = e.detail.value
      let num = val.replace(/^[0]+[0-9]*$/gi, "")
      let disabledMin, disabledMax
      if (this.checkIsMinNum(num)) {    //输入的数量 小于最小的数,则输入框显示最小值
        num = this.data.minNum
        disabledMin = true
        disabledMax = false
      } else if (this.checkIsMaxNum(num)) {     //输入的数量 大于最大的数,则输入框显示最大值
        this.data.disabledMax = true
        num = this.data.maxNum
        disabledMin = false
        disabledMax = true
      } else {     //输入的数量 大于最小的数,则输入框显示输入值
        disabledMin = false
        disabledMax = false
      }
      this.setData({
        num: num,
        disabledMin: disabledMin,
        disabledMax: disabledMax
      })
      this.triggerEvent('optionNum', { num: num })
    },

    // 检查是否是最大数
    checkIsMaxNum: function (checkNum) {
      return this.data.maxNum != "NaN" && checkNum >= this.data.maxNum
    },
    // 检查是否是最小数
    checkIsMinNum: function (checkNum) {
      return this.data.minNum != "NaN" && checkNum <= this.data.minNum
    }
  }
})

2、wxml中的代码

<view class='optionView'>
  <button class="item" bindtap="_reduce" disabled="{{disabledMin}}" style="border:0;background:white" plain='true'>
    <image class="imgReduce" src="{{disabledMin ? '/images/icon/ic_reduce_grey.png' : '/images/icon/ic_reduce.png'}}"></image>
  </button>
  <view class="space">|</view>
  <view class="item">
    <input class="inputNum" type='number' maxlength='3' bindinput="_input" value="{{num}}" placeholder="0" confirm-type="确认" bindblur="_blur" placeholder-style="font-size:26rpx;color:#C81432"></input>
  </view>
  <view class="space">|</view>
  <button class="item" bindtap="_add" disabled="{{disabledMax}}" style="margin-left:6rpx;border:0;background:white" plain='true'>
    <image class="imgAdd" src="{{disabledMax ? '/images/icon/ic_add_grey.png' : '/images/icon/ic_add.png'}}"></image>
  </button>
</view>

3、wxss中的代码

.optionView{
  height: 58rpx;
  width: 240rpx;
  display: flex;
  flex-direction: row;
  border: 1rpx solid #999;
  border-radius: 10rpx;
  justify-content: space-around;
  align-items: center;
  align-content: center;
  background: white;
  margin-right: 64rpx;
}

.item{
  flex: 1;
  display: flex;
  align-items: center;
  align-content: center;
  justify-content: space-around;
}
.space{
  height: 40rpx;
  width: 1rpx;
  color:  #999;
  font-size: 30rpx;
}
.imgAdd{
  width: 16rpx;
  height: 16rpx;
  padding-top: 14rpx;
  padding-bottom: 14rpx
}
.imgReduce{
  width: 16rpx;
  height: 3.5rpx;

  padding-top: 18rpx;
  padding-bottom: 18rpx
}
.inputNum{
    width: 70rpx;
    color: #C81432;
    font-size: 26rpx;
    text-align: center;
    padding-left: 10rpx;
    padding-right: 10rpx;
}
.textMax{
  margin-top: 45rpx;
  margin-bottom: 36rpx;
}

4、json中的代码

{
  "component": true,
  "usingComponents": {}
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,975评论 3 119
  • 亲子日记第158 这几天妞妞一直跟着我去门市,开门后就给我打扫卫生,拖地,拖完地还不让我进去说怕能脏了,等地...
    一年级七班王烁桦妈妈阅读 139评论 0 3
  • 偶是韬华编辑孔澜,现招写手10名,审核题材不限,字数不限『不过,最好是500字以上也不需要太长』,如果有想加入工作...
    噗分离阅读 257评论 1 2
  • 不奉天旨不奉诏, 独立此身自逍遥。 显圣二郎真君在, 不使妖猴上碧霄。
    xueshuai阅读 397评论 0 1
  • 休闲成都,奋进完美。 少不入川老不出蜀,人人都说成都是一座来了就不想离开的城市。 宽窄巷子,留下来的老墙、门洞、拴...
    孔祥延阅读 233评论 0 0