当前位置: 移动技术网 > IT编程>开发语言>JavaScript > element-ui inputNumber、Card 、Breadcrumb组件源码分析整理笔记(三)

element-ui inputNumber、Card 、Breadcrumb组件源码分析整理笔记(三)

2018年11月30日  | 移动技术网IT编程  | 我要评论

澳洲投资移民条件,民权县人民医院,遗失过往

inputnumber组件

<template>
    <!--@dragstart.prevent禁止input中数字的拖动-->
  <div
    @dragstart.prevent
    :class="[
      'el-input-number',
      inputnumbersize ? 'el-input-number--' + inputnumbersize : '',
      { 'is-disabled': inputnumberdisabled },
      { 'is-without-controls': !controls },
      { 'is-controls-right': controlsatright }
    ]">
    <span
      class="el-input-number__decrease"
      role="button"
      v-if="controls"
      v-repeat-click="decrease"
      :class="{'is-disabled': mindisabled}"
      @keydown.enter="decrease">
      <i :class="`el-icon-${controlsatright ? 'arrow-down' : 'minus'}`"></i>
    </span>
    <span
      class="el-input-number__increase"
      role="button"
      v-if="controls"
      v-repeat-click="increase"
      :class="{'is-disabled': maxdisabled}"
      @keydown.enter="increase">
      <i :class="`el-icon-${controlsatright ? 'arrow-up' : 'plus'}`"></i>
    </span>
    <el-input
      ref="input"
      :value="currentinputvalue"
      :placeholder="placeholder"
      :disabled="inputnumberdisabled"
      :size="inputnumbersize"
      :max="max"
      :min="min"
      :name="name"
      :label="label"
      @keydown.up.native.prevent="increase"
      @keydown.down.native.prevent="decrease"
      @blur="handleblur"
      @focus="handlefocus"
      @change="handleinputchange">
    </el-input>
  </div>
</template>
<script>
  import elinput from 'element-ui/packages/input';
  import focus from 'element-ui/src/mixins/focus';
  //repeatclick,用来控制左键按下时不断触发事件
  import repeatclick from 'element-ui/src/directives/repeat-click';

  export default {
    name: 'elinputnumber',
    mixins: [focus('input')],
    inject: {
      elform: {
        default: ''
      },
      elformitem: {
        default: ''
      }
    },
    directives: {
      repeatclick: repeatclick
    },
    components: {
      elinput
    },
    props: {
      step: { //计数器步长
        type: number,
        default: 1
      },
      max: { //设置计数器允许的最大值
        type: number,
        default: infinity
      },
      min: { //设置计数器允许的最小值
        type: number,
        default: -infinity
      },
      value: {}, //绑定值
      disabled: boolean, //是否禁用计数器
      size: string, //计数器尺寸
      controls: { //是否使用控制按钮
        type: boolean,
        default: true
      },
      controlsposition: { //控制按钮位置
        type: string,
        default: ''
      },
      name: string, //原生属性
      label: string, //输入框关联的label文字
      placeholder: string, //输入框默认 placeholder
      precision: { //数值精度
        type: number,
        validator(val) {
          return val >= 0 && val === parseint(val, 10);
        }
      }
    },
    data() {
      return {
        currentvalue: 0
      };
    },
    watch: {
      value: {
        //确认是否以当前的初始值执行handler的函数。
        immediate: true,
        handler(value) {
          //number() 函数把对象的值转换为数字。
          let newval = value === undefined ? value : number(value);
          if (newval !== undefined) {
            if (isnan(newval)) {
              return;
            }
            if (this.precision !== undefined) {
              //如果数值精度存在,将数字按精度转换
              newval = this.toprecision(newval, this.precision);
            }
          }
          if (newval >= this.max) newval = this.max;
          if (newval <= this.min) newval = this.min;
          this.currentvalue = newval;
          this.$emit('input', newval);
        }
      }
    },
    computed: {
      // 返回当前减号是否被禁用
      mindisabled() {
        // 当前值-计数器步长<最小值时,减号被禁用,不能再继续减
        return this._decrease(this.value, this.step) < this.min;
      },
      maxdisabled() {
        return this._increase(this.value, this.step) > this.max;
      },
      //返回数值的精度
      numprecision() {
         // precision 的值必须是一个非负整数,并且不能小于 step 的小数位数。
        const { value, step, getprecision, precision } = this;
        const stepprecision = getprecision(step);
        if (precision !== undefined) {
          //如果step 的小数位数大于数值精度时,控制台输出警告并返回数值精度
          if (stepprecision > precision) {
            console.warn('[element warn][inputnumber]precision should not be less than the decimal places of step');
          }
          return precision;
        } else {
            //如果step 的小数位数小于数值精度时,再比较数值的精度和step的精度,取最大值
          return math.max(getprecision(value), stepprecision);
        }
      },
      // 控制按钮的位置
      controlsatright() {
        //  当控制按钮存在,并且控制按钮的位置为right时,此处通过添加is-controls-right类来改变控制按钮的位置,使控制按钮在右边显示。
        return this.controls && this.controlsposition === 'right';
      },
      _elformitemsize() {
        return (this.elformitem || {}).elformitemsize;
      },
      //计数器的大小
      inputnumbersize() {
        return this.size || this._elformitemsize || (this.$element || {}).size;
      },
      // 是否禁用计数器
      inputnumberdisabled() {
        return this.disabled || (this.elform || {}).disabled;
      },
      currentinputvalue() {
        const currentvalue = this.currentvalue;
        if (typeof currentvalue === 'number' && this.precision !== undefined) {
          return currentvalue.tofixed(this.precision);
        } else {
          return currentvalue;
        }
      }
    },
    methods: {
      //按精度转换数值
      toprecision(num, precision) {
        if (precision === undefined) precision = this.numprecision;
         //tofixed() 方法可把 number 四舍五入为指定小数位数的数字,返回字符串;parsefloat()函数可解析一个字符串,并返回一个浮点数。
        return parsefloat(parsefloat(number(num).tofixed(precision)));
      },
      //获取value的小数位数
      getprecision(value) {
        if (value === undefined) return 0;
        const valuestring = value.tostring();
        const dotposition = valuestring.indexof('.');
        let precision = 0;
        if (dotposition !== -1) {
          //valuestring.length减去小数点前面的位数,剩下的就是小数点后面的位数
          precision = valuestring.length - dotposition - 1;
        }
        return precision;
      },
      _increase(val, step) {
        if (typeof val !== 'number' && val !== undefined) return this.currentvalue;
        const precisionfactor = math.pow(10, this.numprecision);
        return this.toprecision((precisionfactor * val + precisionfactor * step) / precisionfactor);
      },
      //返回value减去step后的值
      _decrease(val, step) {
        if (typeof val !== 'number' && val !== undefined) return this.currentvalue;
        //math.pow()计算10的this.numprecision次方
        const precisionfactor = math.pow(10, this.numprecision);
        //这里主要是为了减少误差
        return this.toprecision((precisionfactor * val - precisionfactor * step) / precisionfactor);
      },
      increase() {
        if (this.inputnumberdisabled || this.maxdisabled) return;
        const value = this.value || 0;
        const newval = this._increase(value, this.step);
        this.setcurrentvalue(newval);
      },
       //点击减号时触发的事件
      decrease() {
        if (this.inputnumberdisabled || this.mindisabled) return;
        const value = this.value || 0;
        const newval = this._decrease(value, this.step);
        this.setcurrentvalue(newval);
      },
      handleblur(event) {
        this.$emit('blur', event);
        this.$refs.input.setcurrentvalue(this.currentinputvalue);
      },
      handlefocus(event) {
        this.$emit('focus', event);
      },
      setcurrentvalue(newval) {
        const oldval = this.currentvalue;
        if (typeof newval === 'number' && this.precision !== undefined) {
          newval = this.toprecision(newval, this.precision);
        }
        if (newval >= this.max) newval = this.max;
        if (newval <= this.min) newval = this.min;
        if (oldval === newval) {
          //改变input的当前值
          this.$refs.input.setcurrentvalue(this.currentinputvalue);
          return;
        }
        this.$emit('input', newval);
        this.$emit('change', newval, oldval);
        this.currentvalue = newval;
      },
      handleinputchange(value) {
        const newval = value === '' ? undefined : number(value);
        if (!isnan(newval) || value === '') {
          this.setcurrentvalue(newval);
        }
      },
      select() {
        this.$refs.input.select();
      }
    },
    mounted() {
      let innerinput = this.$refs.input.$refs.input;
      innerinput.setattribute('role', 'spinbutton');
      innerinput.setattribute('aria-valuemax', this.max);
      innerinput.setattribute('aria-valuemin', this.min);
      innerinput.setattribute('aria-valuenow', this.currentvalue);
      innerinput.setattribute('aria-disabled', this.inputnumberdisabled);
    },
    updated() {
      if (!this.$refs || !this.$refs.input) return;
      const innerinput = this.$refs.input.$refs.input;
      innerinput.setattribute('aria-valuenow', this.currentvalue);
    }
  };
</script>

解析:
(1)先看下html结构

 <div class="el-input-number">
        <!--左边的减号-->
       <span class="el-input-number__decrease">
           <i class="el-icon-minus"></i>
       </span>
        <!--右边的加号-->
       <span class="el-input-number__increase">
          <i class="el-icon-plus"></i>
       </span>
        <!--中间的输入框-->
       <el-input ref="input"></el-input>
</div>


左边的减号和右边的加号是通过绝对定位,设置在input左右的padding位置的,input的css代码如下:

.el-input-number .el-input__inner {
    -webkit-appearance: none;
    padding-left: 50px;
    padding-right: 50px;
    text-align: center;
}

这个inputnumber源码还算简单,多看几遍就懂了

card 组件

<template>
  <div class="el-card" :class="shadow ? 'is-' + shadow + '-shadow' : 'is-always-shadow'">
      <!--头部:设置 header,也可以通过 slot#header 传入 dom-->
    <div class="el-card__header" v-if="$slots.header || header">
      <slot name="header">{{ header }}</slot>
    </div>
      <!--内容部分-->
    <div class="el-card__body" :style="bodystyle">
      <slot></slot>
    </div>
  </div>
</template>

<script>
  export default {
    name: 'elcard',
    props: {
      header: {}, //设置 header,也可以通过 slot#header 传入dom
      bodystyle: {}, //设置 body 的样式
      shadow: {  //设置阴影显示时机
        type: string
      }
    }
  };
</script>
<template>
  <span class="el-breadcrumb__item">
    <span
      :class="['el-breadcrumb__inner', to ? 'is-link' : '']"
      ref="link"
      role="link">
      <!--插入文字-->
      <slot></slot>
    </span>
      <!--图标分隔符-->
    <i v-if="separatorclass" class="el-breadcrumb__separator" :class="separatorclass"></i>
      <!--分隔符-->
    <span v-else class="el-breadcrumb__separator" role="presentation">{{separator}}</span>
  </span>
</template>
<script>
  export default {
    name: 'elbreadcrumbitem',
    props: {
      to: {}, //路由跳转对象,同 vue-router 的 to
      replace: boolean //在使用 to 进行路由跳转时,启用 replace 将不会向 history 添加新记录
    },
    data() {
      return {
        separator: '',
        separatorclass: ''
      };
    },

    inject: ['elbreadcrumb'],

    mounted() {
      //获取父组件的separator
      this.separator = this.elbreadcrumb.separator;
      //获取父组件的separatorclass
      this.separatorclass = this.elbreadcrumb.separatorclass;
      const link = this.$refs.link;
      link.setattribute('role', 'link');
      //添加点击事件
      link.addeventlistener('click', _ => {
        const { to, $router } = this;
        if (!to || !$router) return;
        //根据replace的值确定是replace还是push,replace 将不会向 history 添加新记录
        this.replace ? $router.replace(to) : $router.push(to);
      });
    }
  };
</script>

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网