element ui el-avatar 源码解析零基础逐行解析

发布时间:2023年12月20日

avatar功能介绍

快捷配置头像的样式

avatar 的参数配置

属性说明参数
size尺寸type string 类型 (‘large’,‘medium’,‘small’)number类型
validator 校验
shape形状circle (原型) square(方形)
icon传入的icon
src传入的图片string类型 可以是本地图片(本地图片需要在js中requir导入,不可直接使用相对路劲引用)
也可以是网络地址
srcSet是一种响应式网页设计,它允许开发者为图像提供不同大小和分辨率的版本,以便根据设备的屏幕大小和像素密度自动选择最适合的图像进行显示例如srcset=“image1.jpg 1x, image2.jpg 2x, image3.jpg 3x” 属性接受一组逗号分隔的描述符和图像路径
浏览器会根据设备的像素密度选择合适的图像进行加载,例如在像素密度为2x的设备上,会选择加载 image2.jpg。
error传入的图片异常函数图片加载失败时,触发的异常函数
fitobject-fit 的参数 img图片自适应方案,类似于background-size的属性fill 默认,不保证保持原有的比例,内容拉伸填充整个内容容器
contain 保持原有尺寸比例。内容被缩放。
cover 保持原有尺寸比例。但部分内容可能被剪切。
none 保留原有元素内容的长度和宽度,也就是说内容不会被重置。
scale-down 保持原有尺寸比例。内容的尺寸与 none 或 contain 中的一个相同,取决于它们两个之间谁得到的对象尺寸会更小一些。

avatar的样式类名根据传入的参数处理

  computed: {
    avatarClass() {
      // 类名 集合
      const { size, icon, shape } = this;
      console.log("size",size)
      // size avatar 图标的尺寸
      // icon 图标
      // shpe形状
      let classList = ['el-avatar'];
            // classList 类名 集合
      if (size && typeof size === 'string') {
        classList.push(`el-avatar--${size}`);
      }

      if (icon) {
        classList.push('el-avatar--icon');
      }

      if (shape) {
        classList.push(`el-avatar--${shape}`);
      }
      // classList.join(" ") 就是将名的数组以空格为连接符拼接到一起
      return classList.join(' ');
    }
  },

代码逻辑

  • 定义默认的 classList = 为 [‘el-avatar’]
  • 根据size、icon、shape 和 el-avatar 拼接成类名
  • 然后将拼接好的类名数组用join(’ ')拼接成字符串
  • 返回 并渲染到 html的class上

头像异常的处理逻辑

    handleError() {
      const { error } = this;
      const errorFlag = error ? error() : undefined;
      // 图片类头像加载失败的回调, 返回 false 会关闭组件默认的 fallback 行为
      if (errorFlag !== false) {
        this.isImageExist = false;
      }
    }

renderAvatar 渲染头像的主体逻辑

    renderAvatar() {
      const { icon, src, alt, isImageExist, srcSet, fit } = this;
        console.log("=======================",icon, src, alt, isImageExist, srcSet, fit)
      if (isImageExist && src) {
        // 图片路径存在,就渲染图片
        return <img
          src={src}
          onError={this.handleError}
          alt={alt}
          srcSet={srcSet}
          style={{ 'object-fit': fit }}/>
      }
      // src 图片的路径
     // onError 图片异常触发的钩子函数    
     //srcSet   srcset="image1.jpg 1x, image2.jpg 2x, image3.jpg 3x"
     //srcSet 属性接受一组逗号分隔的描述符和图像路径    
     //浏览器会根据设备的像素密度选择合适的图像进行加载,例如在像素密度为2x的设备上,会选择加载 image2.jpg。
      if (icon) {
        //如果icon存在 就渲染 传入的icon
        return (<i class={icon} />);
      }

      return this.$slots.default;//如果没有传入icon url  就渲染组件的默认插槽 如果组件引用标签内没有包裹东西,就是空的
    }

代码细节

  • 返回一个html片段
  • 如果传入的src存在就渲染图片 alt 是图片不显示时 显示的文本
  • 如果icon存在,就渲染icon图标
  • 入宫src和icon都不存在就渲染组件的默认插槽
  • this.$slots.default是组件的默认插槽

render函数里的代码

  render() {
    const { avatarClass, size } = this;//使用解构,获取到avatarClass 和size 
    const sizeStyle = typeof size === 'number' ? {
      height: `${size}px`,
      width: `${size}px`,
      lineHeight: `${size}px`
    } : {};
    //如果传入的 size 是number类型的 就直接拼接px形成style对象
    
    return (
      <span class={ avatarClass } style={ sizeStyle }>
        {
          this.renderAvatar()
        }
      </span>
    );
  }

render函数里的代码逻辑

  • 使用解构赋值 获取到组件里的avatarClass(类名)和size(尺寸)
  • 如果size的类型时 number 则使用模板字符串组装 height ,width,lineHeight组成的sizeStyle对象
  • 将 avatarClass 和 sizeStyle 挂载到span上 使类名和 style生效,这种写法非常不错,逻辑和模板分离
  • 最后调用renderAvatar()函数,使得函数中定义的逻辑模板渲染在html中
  • render函数可以替代template实现模板的渲染,并且效率比直接写template更高

全部代码

<script>
export default {
  name: 'ElAvatar',

  props: {
    size: {
      type: [Number, String],//type 
      validator(val) {
        // validator 可以是一个函数 返回值是 boolean true表示传入有效,false表示传入的数据格式不对,会提示格式不对
        if (typeof val === 'string') {
          return ['large', 'medium', 'small'].includes(val);
        }
        return typeof val === 'number';
      }
    },
    shape: {//形状 circle圆形 square 方形 
      type: String,
      default: 'circle',
      validator(val) {
        return ['circle', 'square'].includes(val);
      }
    },
    icon: String,//传入的图标 icon
    src: String,//传入的路径
    alt: String,//图片不显示时 显示的替代文本
    srcSet: String,//是一种响应式网页设计,它允许开发者为图像提供不同大小和分辨率的版本,以便根据设备的屏幕大小和像素密度自动选择最适合的图像进行显示
    error: Function,//图片加载失败,触发的异常函数
    fit: {
      type: String,
      default: 'contain'
    }
  },
  // object-fit
  // img标签的图片自适应方案
  // fill 默认,不保证保持原有的比例,内容拉伸填充整个内容容器。
  // contain  保持原有尺寸比例。内容被缩放。
  // cover 保持原有尺寸比例。但部分内容可能被剪切。
  // none	 保留原有元素内容的长度和宽度,也就是说内容不会被重置。
// scale-down	保持原有尺寸比例。内容的尺寸与 none 或 contain 中的一个相同,取决于它们两个之间谁得到的对象尺寸会更小一些。
  data() {
    return {
      isImageExist: true
    };
  },

  computed: {
    avatarClass() {
      // 类名 集合
      const { size, icon, shape } = this;
      console.log("size",size)
      // size avatar 图标的尺寸
      // icon 图标
      // shpe形状
      let classList = ['el-avatar'];
            // classList 类名 集合
      if (size && typeof size === 'string') {
        classList.push(`el-avatar--${size}`);
      }

      if (icon) {
        classList.push('el-avatar--icon');
      }

      if (shape) {
        classList.push(`el-avatar--${shape}`);
      }
      // classList.join(" ") 就是将名的数组以空格为连接符拼接到一起
      return classList.join(' ');
    }
  },
  methods: {
    handleError() {
      const { error } = this;
      const errorFlag = error ? error() : undefined;
      // 图片类头像加载失败的回调, 返回 false 会关闭组件默认的 fallback 行为
      if (errorFlag !== false) {
        this.isImageExist = false;
      }
    },
    renderAvatar() {
      const { icon, src, alt, isImageExist, srcSet, fit } = this;
        console.log("=======================",icon, src, alt, isImageExist, srcSet, fit)
      if (isImageExist && src) {

        // 图片路径存在,就渲染图片
        return <img
          src={src}
          onError={this.handleError}
          alt={alt}
          srcSet={srcSet}
          style={{ 'object-fit': fit }}/>
      }
      // src 图片的路径
     // onError 图片异常触发的钩子函数    
     //srcSet   srcset="image1.jpg 1x, image2.jpg 2x, image3.jpg 3x"
     //srcSet 属性接受一组逗号分隔的描述符和图像路径    
     //浏览器会根据设备的像素密度选择合适的图像进行加载,例如在像素密度为2x的设备上,会选择加载 image2.jpg。
      if (icon) {
        //如果icon存在 就渲染 传入的icon
        return (<i class={icon} />);
      }

      return this.$slots.default;//如果没有传入icon url  就渲染组件的默认插槽 如果组件引用标签内没有包裹东西,就是空的
    }
  },

  render() {
    const { avatarClass, size } = this;//使用解构,获取到avatarClass 和size 
    const sizeStyle = typeof size === 'number' ? {
      height: `${size}px`,
      width: `${size}px`,
      lineHeight: `${size}px`
    } : {};
    //如果传入的 size 是number类型的 就直接拼接px形成style对象
    
    return (
      <span class={ avatarClass } style={ sizeStyle }>
        {
          this.renderAvatar()
        }
      </span>
    );
  }

};
</script>


文章来源:https://blog.csdn.net/qq_42389674/article/details/135117180
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。