钉钉E应用(小程序)之自定义组件开发(计数器)

文前唠叨几句:这个计数器demo虽然小,但也涵盖了整个开发自定义组件的流程和页面与组件之间的相互传值的问题。 (并且这个小demo是从支付宝小程序这个大demo里面抠出来的,他两除了api和一些小细节不同之外,自定义组件这方面也还是相通的,有兴趣的朋友可以自己研究下)

官方文档:https://open-doc.dingtalk.com/microapp/dev/develop-custom-component

最终效果 && 目录:

先说说开发自定义组件Counter的开发:

1、json:

component 声明当前的是组件 ;

( 可选 ) usingComponents 声明所依赖的组件 ( 即当前的组件需要使用到另外一个自定义组件 ) 所在的位置。

 

2、axml:

( 其实跟写平常的axml没什么不同 )

<dd-test /> :只是展示所需要的组件怎样插入到当前组件

<view 
  class="am-stepper-content {{className}}"
  style="opacity:{{disabled ? '0.4' : '1'}}"
  max="{{max}}"
  min="{{min}}"
  onChange="{{callBackFn}}"
  step="{{step}}"
  disabled="{{disabled || readOnly}}"
>
  <view class="am-stepper-reduce" style="opacity:{{opaReduce}}" data-type="reduce" onTap="changeFn"><text class="iconfont icon-sub"></text></view>
  <input
    class="am-stepper-input"
    style="display:{{showNumber ? 'inline-block' : 'none'}};"
    value="{{value}}"
    onBlur="onBlur"
    disabled="{{disabled || readOnly}}"
    type="number"
  />
  <view class="am-stepper-add" style="opacity:{{opaAdd}}" data-type="add" onTap="changeFn"><text class="iconfont icon-iconjia"></text></view>

<dd-test />  </view>

3、js:

调用Component定义组件

Component({
  data: {   //定义组件内所需要的变量  
    opaReduce: 1,
    opaAdd: 1
  },
  props: {  //设置默认值 && 接收传过来的值   通过this.props.xx 获取到默认值 && 传过来的值
    className: '',
    min: 1,    //若没有值传进来,就使用该默认值 ;若传有值进来,传过来的值便覆盖默认值
    max: 100,
    disabled: false,
    value: 10,   
    readOnly: false,
    showNumber: false,
    step: 1,
    onChange: function onChange() { }    //触发该组件的事件
  },
  didMount: function didMount() { //页面渲染完毕后执行 (组件的生命周期函数)
    var _props = this.props,
      value = _props.value,
      min = _props.min,
      max = _props.max;
    this.setData({
      value: Math.min(Math.max(min, value), max)   //更新value值
    });
  },
  // 官方解释:didUpdate 为更新后回调,每次组件数据变更的时候都会调用(组件的生命周期函数)。
  // 鄙人解释:一有神马动作就立刻执行 
  didUpdate: function didUpdate(preProps) {   
    var _props2 = this.props,
      value = _props2.value,
      min = _props2.min,
      max = _props2.max;
    if (preProps.value !== value) {
      var newValue = Math.min(Math.max(min, value), max);
      this.setData({
        value: newValue
      });
      this.resetFn(newValue);
    }
  },
  methods: {
    changeFn: function changeFn(ev) {
      var _props3 = this.props,
        min = _props3.min,
        max = _props3.max,
        onChange = _props3.onChange,
        disabled = _props3.disabled,
        readOnly = _props3.readOnly,
        step = _props3.step;

      var evType = ev.target.dataset.type;
      var _data = this.data,
        opaReduce = _data.opaReduce,
        opaAdd = _data.opaAdd,
        value = _data.value;

      var enable = disabled || readOnly;
      if (!enable) {
        if (evType === 'reduce') {
          if (value > min) {
            opaAdd = 1;
            value = Math.max(min, +value - +step);
            opaReduce = value === min ? 0.4 : 1;
          }
        } else {
          /* eslint-disable no-lonely-if */
          if (value < max) {
            opaReduce = 1;
            value = Math.min(+value + +step, max);
            opaAdd = value === max ? 0.4 : 1;
          }
        }
        this.setData({
          value: value,
          opaAdd: opaAdd,
          opaReduce: opaReduce
        });
        // 值通过 this.props.onChange(xxx)将值传出去
        onChange(value);
      }
    },
    onBlur: function onBlur(event) {  //失焦事件函数
      var value = event.detail.value;

      this.resetFn(value);
    },
    resetFn: function resetFn(value) {
      var _props4 = this.props,
        max = _props4.max,
        min = _props4.min,
        onChange = _props4.onChange;

      var calculatedVal = value;
      var opaAdd = 1;
      var opaReduce = 1;
      if (value >= max) {
        calculatedVal = max;
        opaAdd = 0.4;
      } else if (value <= min) {
        calculatedVal = min;
        opaReduce = 0.4;
      }
      this.setData({
        value: calculatedVal,
        opaAdd: opaAdd,
        opaReduce: opaReduce
      });
      onChange(calculatedVal);
    }
  }
});

4、acss

.am-stepper-content {
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  line-height: 70rpx;
  font-size: 40rpx;
  height: 70rpx;
  width: 280rpx;
  color: #000;
  border: 1rpx solid #dcdfe6;
}

.am-stepper-reduce,
.am-stepper-add {
  box-sizing: border-box;
  flex: 3;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 66rpx;
  background-color: #f5f7fa;
  border-top: none;
  border-bottom: none;
  border-left: 1rpx solid #dcdfe6;
  border-right: 1rpx solid #dcdfe6;
}

.am-stepper-input {
  box-sizing: border-box;
  flex: 3;
  height: 64rpx;
  padding-left: 53rpx;
  color: #000;
}

准备就绪,调用就简单很多了

1、json:

2、axml:

<view class="page">
  <view class="page-description">Counter </view>

  <!-- 需要传递的值一定要用{{}}包起来 ;<dd-counter />:调用自定义组件 -->
  <dd-counter onChange="callBackFn" step="{{1}}" showNumber readOnly="{{false}}" value="{{5}}" min="{{2}}" max="{{12}}"/>
  
  <view style="padding-top: 10px;font-size: 30rpx;">当前的值为: {{val}}</view>
</view>

3、js:

Page({
  data:{
    val:''
  },
  callBackFn(e){   //e:自定义组件传过来的数据
    this.setData({
      val: e
    })
  }
})

自定义组件还有神马

  插槽:slot (用过vue都知道这是啥吧...)

  生命周期:1、didMount(组件渲染完毕后回调);2、didUpdate(组件数据更改后回调);3、didUnmount(组件删除后回调);

  mixins:用来装公共的逻辑的,例(官网例子改造):

  ;

等就不细说了,正在开发相关功能或还感兴趣的朋友可移驾官方文档,官方文档有更详细的说明和例子可以参考...

另,还封装了几个组件可加以参考:

https://github.com/wunuolin/dingdingU

 

 

 

ok,文章就到这了,有神马不足的地方,请务必指正,谢谢各位大佬看到此处...

注:转载请标明出处...

posted @ 2019-07-25 14:02  Nuolin  阅读(2669)  评论(0编辑  收藏  举报