GithubHelp home page GithubHelp logo

article's Introduction

Hi there 👋

article's People

Contributors

defaultprops avatar

Watchers

 avatar

article's Issues

element-ui 之 el-button 源码分析

<template>
  <button
    class="el-button"
    @click="handleClick"
    :disabled="buttonDisabled || loading"
    :autofocus="autofocus"
    :type="nativeType" // 原生type: submit | reset | button | menu(废弃)
    :class="[
      // computed缺少type类型校验
      type ? 'el-button--' + type : '',
      // computed缺少size类型校验
      buttonSize ? 'el-button--' + buttonSize : '',
      
      {
        'is-disabled': buttonDisabled, 
        // 在联调UED设置的主题中,局部使用少量属性配置主题。
        // 其他属性屏蔽使用或使其不生效(工作量较大)
        'is-loading': loading,
        'is-plain': plain,
        'is-round': round,
        'is-circle': circle
      }
    ]"
  >
    <i class="el-icon-loading" v-if="loading"></i> // 图标前置
    <i :class="icon" v-if="icon && !loading"></i>
    <span v-if="$slots.default"><slot></slot></span>
  </button>
</template>
<script>
  export default {
    name: 'ElButton', // 通常而言,不建议使用name属性,定位难还容易重名

    inject: { // 当然,更不建议使用这种穿透形式的inject
      elForm: {
        default: ''
      },
      elFormItem: {
        default: ''
      }
    },

    props: { // 建议使用严格模式的,required 和 default
      type: {
        type: String,
        default: 'default'
      },
      size: String,
      icon: {
        type: String,
        default: ''
      },
      nativeType: {
        type: String,
        default: 'button'
      },
      loading: Boolean,
      disabled: Boolean,
      plain: Boolean,
      autofocus: Boolean,
      round: Boolean,
      circle: Boolean
    },

    computed: {
     // 下划线的声明写法一般是内部私有变量,建议统一风格。本人不习惯使用该写法。
     // level el-form-item > el-form
      _elFormItemSize() {
        return (this.elFormItem || {}).elFormItemSize;
      },
      // level: button-size > el-form-item-size 
      // > el-form-size > global size (Vue.prototype.$ELEMENT)
      buttonSize() {
        return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
      },
      buttonDisabled() {
      // new 实例中使用propsData情况少见,可以不考虑这种情况。v3抛弃
      // el-form 全局disabled属性
        return this.$options.propsData.hasOwnProperty('disabled') ? this.disabled : (this.elForm || {}).disabled;
      }
    },

    methods: {
     // 非常不喜欢这种写法,handle就包含click,这么写有点重复意思
      handleClick(evt) {
        this.$emit('click', evt);
      }
    }
  };
</script>

el-button-group源码

<template>
  <div class="el-button-group">
    <slot></slot>
  </div>
</template>
<script>
  export default {
    name: 'ElButtonGroup'
  };
</script>

element-ui 之 el-alert 源码分析

<template>
// 增加动画效果,透明度
// .el-alert-fade-enter,.el-alert-fade-leave-active {opacity: 0;}
  <transition name="el-alert-fade">
   // 我更习惯 classname 静态和动态一起写
   // role这种增强语义的方式,感觉怪怪的,有种四不像的赶脚
   // 必须使用v-show,不然动画效果不生效。
   // todo: BEM className命名规范
    <div
      class="el-alert"
      :class="[typeClass, center ? 'is-center' : '', 'is-' + effect]"
      v-show="visible"
      role="alert"
    >
      <i class="el-alert__icon" :class="[ iconClass, isBigIcon ]" v-if="showIcon"></i>
      <div class="el-alert__content">
        <span class="el-alert__title" :class="[ isBoldTitle ]" v-if="title || $slots.title">
          <slot name="title">{{ title }}</slot>
        </span>
        // $slots.default && !description 写入 computed 变量更直观一点
        <p class="el-alert__description" v-if="$slots.default && !description"><slot></slot></p>
        <p class="el-alert__description" v-if="description && !$slots.default">{{ description }}</p>
        // 这个也可以写入 computed 变量成 className
        // closeText == '' ? 'el-icon-close' : 'is-customed']
        // 习惯增加 eslint-plugin-vue vue/attributes-order 属性排序
        <i class="el-alert__closebtn" :class="{ 'is-customed': closeText !== '', 'el-icon-close': closeText === '' }" v-show="closable" @click="close()">{{closeText}}</i>
      </div>
    </div>
  </transition>
</template>

<script type="text/babel">
  const TYPE_CLASSES_MAP = {
    'success': 'el-icon-success',
    'warning': 'el-icon-warning',
    'error': 'el-icon-error'
  };
  export default {
    // 习惯增加 vue/order-in-components 强制顺序关系,更容易 review 和 debug
    name: 'ElAlert',

    props: {
      title: {
        type: String,
        default: ''
      },
      description: {
        type: String,
        default: ''
      },
      type: {
        type: String,
        default: 'info'
      },
      closable: {
        type: Boolean,
        default: true
      },
      closeText: {
        type: String,
        default: ''
      },
      showIcon: Boolean,
      center: Boolean,
      effect: {
        type: String,
        default: 'light',
        validator: function(value) {
        //  advise: includes api is better
          return ['light', 'dark'].indexOf(value) !== -1;
        }
      }
    },

    data() {
      return {
        visible: true
      };
    },

    methods: {
      // 语义化一点
      close() {
        this.visible = false;
        this.$emit('close');
      }
    },

    computed: {
      typeClass() {
        return `el-alert--${ this.type }`;
      },

      iconClass() {
        return TYPE_CLASSES_MAP[this.type] || 'el-icon-info';
      },

      isBigIcon() {
        return this.description || this.$slots.default ? 'is-big' : '';
      },

      isBoldTitle() {
        return this.description || this.$slots.default ? 'is-bold' : '';
      }
    }
  };
</script>

element-ui 之 el-avatar 源码分析

<script>
export default {
  // 不建议使用name属性,后期定位组件难
  name: 'ElAvatar',

  props: {
    size: {
      type: [Number, String],
      // 以前用得少这种校验方式,这种校验方式可能会丢失上一级真实传递的数据
      // 但是确实是一个有趣的方法
      // validator 校验props类型,false控制台告警
      validator(val) {
        if (typeof val === 'string') {
          return ['large', 'medium', 'small'].includes(val);
        }
        return typeof val === 'number';
      }
    },
    // 展示类型,默认circle圆形头像, square方形头像
    // 看来都是看心情写validator啊
    shape: {
      type: String,
      default: 'circle',
      validator(val) {
        return ['circle', 'square'].includes(val);
      }
    },
    icon: String,
    src: String,
    alt: String,
    srcSet: String,
    error: Function,
    fit: {
      type: String,
      default: 'cover'
    }
  },

  data() {
    return {
      isImageExist: true
    };
  },

  computed: {
    avatarClass() {
      const { size, icon, shape } = this;
      let classList = ['el-avatar'];

     // add class-size
      if (size && typeof size === 'string') {
        classList.push(`el-avatar--${size}`);
      }
      // add class-icon
      if (icon) {
        classList.push('el-avatar--icon');
      }
      
      // add class-shape
      if (shape) {
        classList.push(`el-avatar--${shape}`);
      }

      return classList.join(' ');
    }
  },

  methods: {
    // handleError 这名字怪怪的,手动报错?? 写 loadErrorImg 语义化一点
    handleError() {
    //  const errorFlag = this.error?.() || undefined 简单点
      const { error } = this; 
      const errorFlag = error ? error() : undefined;
      if (errorFlag !== false) {
        this.isImageExist = false;
      }
    },
    renderAvatar() {
      // 个人习惯更喜欢使用this, this在vue2代表自定义的vue变量或者方法
      // 这种解构方式容易误会成函数内部局部变量而不是vue变量
      // 而且后期扩展容易重名
      const { icon, src, alt, isImageExist, srcSet, fit } = this;
      
      // todo 学习css: object-fit

      if (isImageExist && src) {
        return <img
          src={src}
          onError={this.handleError}
          alt={alt}
          srcSet={srcSet}
          style={{ 'object-fit': fit }}/>;
      }

      if (icon) {
        return (<i class={icon} />);
      }
     
      // 应该增加一个具名插槽。联调UED的主题头像时,还要我自己封装。唉...
      return this.$slots.default;
    }
  },

  render() {
    const { avatarClass, size } = this;

    const sizeStyle = typeof size === 'number' ? {
      height: `${size}px`,
      width: `${size}px`,
      lineHeight: `${size}px`
    } : {};

    return (
      <span class={ avatarClass } style={ sizeStyle }>
        {
          this.renderAvatar()
        }
      </span>
    );
  }

};
</script>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.