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

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 传入的图片异常函数 图片加载失败时,触发的异常函数
fit object-fit 的参数 img图片自适应方案,类似于background-size的属性 fill 默认,不保证保持原有的比例,内容拉伸填充整个内容容器 contain 保持原有尺寸比例。内容被缩放。 cover 保持原有尺寸比例。但部分内容可能被剪切。 none 保留原有元素内容的长度和宽度,也就是说内容不会被重置。 scale-down 保持原有尺寸比例。内容的尺寸与 none 或 contain 中的一个相同,取决于它们两个之间谁得到的对象尺寸会更小一些。

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

javascript 复制代码
  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上

头像异常的处理逻辑

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

renderAvatar 渲染头像的主体逻辑

javascript 复制代码
    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函数里的代码

javascript 复制代码
  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更高

全部代码

javascript 复制代码
<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>
相关推荐
涵涵(互关)3 小时前
Naive-ui树型选择器只显示根节点
前端·ui·vue
测试员周周6 小时前
【Appium 系列】第13节-混合测试执行器 — API + UI 的协同执行
开发语言·人工智能·python·功能测试·ui·appium·pytest
莽夫搞战术6 小时前
【Google Stitch】AI原生画布重新定义设计,让想法变成可交互界面
前端·人工智能·ui
ZC跨境爬虫9 小时前
跟着 MDN 学CSS day_3:(为一个传记页面添加样式)
前端·javascript·css·ui·音视频·html5
UI设计兰亭妙微11 小时前
兰亭妙微|打破色彩对比度迷思:UI设计公司中的无障碍设计灵活之道
ui·b端界面设计·高端网站设计
轻口味12 小时前
HarmonyOS 6.1 全栈实战录 - 14 渲染树透镜:FrameNode 渲染状态感知与高性能 UI 调优实战
ui·华为·harmonyos
ZC跨境爬虫14 小时前
跟着 MDN 学CSS day_5:掌握属性选择器的存否匹配与子字符串匹配
前端·javascript·css·ui·html
ZC跨境爬虫14 小时前
模块化烹饪小程序开发日记 Day5:(后端Flask接口开发与AI智能解析菜谱的实现)
前端·人工智能·后端·python·ui·flask
薛定猫AI1 天前
【深度解析】Gemini Omni 多模态生成与 Agent 化创作工作流:从视频编辑到 UI 生成的技术演进
人工智能·ui·音视频
赏金术士1 天前
第七章:状态管理实战与架构总结
android·ui·kotlin·compose