elment-ui组件源码分析学习(1)

笔者分析了自己的专栏数据,发现使用知识 专栏数据明显好于认知知识专栏,也就是说读者更感兴趣的是笔者的使用知识专栏,也就是具体的知识使用场景。笔者想这大概是因为这种文章能够直接或间接解决问题,能够有获得感。

笔者在《技术并一定不比其他高级》中写到技术实际是有重复单元的,而UI组件库正是功能单元的代表,所以笔者决定改变策略,先集中精力写好重复单元。

在教育学中,母题是各门学科包含若干知识点的基本题、典型题,也是中高考命题所参照的原型题。笔者把上述的重复单元也叫母场景。其他学科也可以如此分析。

因为实际开发中涉及element-ui比较多,优先从elment-ui组件开始分析并学习。element-ui版本:2.15.14。

首先笔者从所有组件中选出简单的20个组件,也是此次分析学习的对象。这些组件基本上没有引入其他依赖。

基本分析&模拟原生

原生html5标签是构建功能单元的基础,在没有Vue、React这类框架时,有jqueryUi、bootstrap等,这些为什么会存在?因为原生的标签离业务较远。

不管是jqueryUi、bootstrap封装的功能单元还是基于Vue、React封装的功能单元,一定不是完全符合业务要求的,但相对于原生html5标签来说,距离业务更近。

组件介绍

容器组件:container、main、aside、header和footer。快捷容器。

  1. button按钮组件和按钮组button-group:按钮是页面上允许点击的面积
  2. alert弹出组件:条形提示
  3. backtop回到顶部:当滚动过长方面回到顶部
  4. icon图标显示:图标快捷使用
  5. avatar头像组件:快捷头像
  6. badge标记组件:标记显示
  7. tag标签组件:标签显示
  8. progress进度条组件:进度条显示
  9. link链接文字:链接文字显示
  10. card卡片组件:卡片形式显示
  11. divider分割线组件:就是段落之间的分割线
  12. breadcrumb面包屑导航和breadcrumb-item面包屑导航内容:快捷面包屑导航
  13. page-header页头:快捷页头

本次分析学习的20个组件,相对来说都比较简单,传入对应的prop和绑定封装好的绑定方法就可以设置组件属性和处理组件方法。

至于封装了哪些属性,要结合组件的功能定位和业务定位。要逐渐记住每个组件对应的业务应用场景,这样才能理解为什么如此封装,才能更高效的使用。其他UI组件库也可以这样分析学习。

Vue组件的属性设置

都知道Vue组件可以通过prop输入参数,且所有参数都可以通过this.$props获取到。另外,Vue组件上也可以直接写属性值,只不过这个时候不是通过prop获取,而是通过this.$attrs

js 复制代码
<my-component custom-attr="hello" />
export default {
  name: 'MyComponent',
  created() {
    console.log(this.$attrs['custom-attr']); // 输出:hello
  }
}

而组件的class和style属性,Vue会将它们特殊处理,不包含在$attrs中,而是分别提供$el.className$el.style来访问,且需要在组件的mounted生命周期函数中才能获取到。

Vue组件的事件绑定

一般来说组件的事件绑定是通过this.$emit触发的。对于v-model这种双向数据绑定,默认触发的是this.$emit('input')

Vue组件的ref设置

Vue组件ref设置,可以类比html5原生标签的类或者id,通过选择器选择到这个标签之后,就可以拿到标签的样式、className等属性和方法。

ref类似于此,可以拿到组件内部的属性和方法。这就是Vue组件对原生标签的模仿。

this.$options

还有在Vue组件中,this.$options包含了传递给Vue实例的所有选项。这包括了props、methods、data、computed等等。

学到知识点

判断slot里组件标签

slot在Vue中是插槽,可以通过this.$slots获取到,默认是this.$slots.default。看到UI组件源码中的container组件里面这行代码

js 复制代码
 computed: {
    isVertical() {
      if (this.direction === "vertical") {
        return true;
      } else if (this.direction === "horizontal") {
        return false;
      }
      return this.$slots && this.$slots.default
        ? this.$slots.default.some((vnode) => {
            // 注意这行注意这行注意这行注意这行注意这行
            const tag = vnode.componentOptions && vnode.componentOptions.tag;
            return tag === "unit-header" || tag === "unit-footer";
          })
        : false;
    },

这个计算属性里面竟然可以通过vnode.componentOptions && vnode.componentOptions.tag拿到slot内的组件的组件名,如果里面有 "unit-header" || tag === "unit-footer",就返回true。真是学到了。

provide和inject

在button组件内部,有

js 复制代码
  inject: {
    elForm: {
      default: "",
    },
    elFormItem: {
      default: "",
    },
  },

inject是注入,这里面注入了elFormelFormItem,然后在计算属性中使用

js 复制代码
 computed: {
    _elFormItemSize() {
      return (this.elFormItem || {}).elFormItemSize;
    },
    buttonSize() {
      return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
    },
    buttonDisabled() {
      // this.$options.propsData.hasOwnProperty("disabled")
      return this.$options.propsData.hasOwnProperty("disabled")
        ? this.disabled
        : (this.elForm || {}).disabled;
    },
  },

熟悉element-ui的应该可以看出来,这里就是可以通过给elment-ui的el-form组件设置尺寸大小的方式设置el-form内部组件的大小。

组件中使用render以及jsx语法

在Vue源码里,如果组件同时存在template和render,render的优先级是大于template的。

如果不想使用render的渲染函数方法h,可以使用jsx语法,只不过这个时候需要下载相应的依赖支持。element-ui的avatar组件和tag组件,就使用了jsx。

具体开发中到底是采用template还是render写模板,要看组件的具体特点。

函数式组件slot和prop获取

在上面20个组件中,divider分割线组件是一个函数式组件,然后再函数式组件里面没有生命周期函数,没有this,有段代码

js 复制代码
    <div
        v-if="slots().default && props.direction !== 'vertical'"
        :class="['el-divider__text', `is-${props.contentPosition}`]"
       >
        <slot />
      </div>

通过使用props而不是this.$props获取prop传入参数。还有slots().default可以用$slots.default替代。

代码地址

github:github.com/zhensg123/v...

(本文完)

相关推荐
adminIvan几秒前
Element plus使用menu时候如何在折叠时候隐藏掉组件自带的小箭头
前端·javascript·vue.js
会发光的猪。19 分钟前
【 ElementUI 组件Steps 步骤条使用新手详细教程】
前端·javascript·vue.js·elementui·前端框架
我家媳妇儿萌哒哒20 分钟前
el-table合并单元格之后,再进行隔行换色的且覆盖表格行鼠标移入的背景色的实现
前端·javascript·elementui
baiduguoyun36 分钟前
react的import 导入语句中的特殊符号
前端·react.js
前端青山37 分钟前
webpack指南
开发语言·前端·javascript·webpack·前端框架
NiNg_1_2341 小时前
ECharts实现数据可视化入门详解
前端·信息可视化·echarts
程序媛小果1 小时前
基于java+SpringBoot+Vue的桂林旅游景点导游平台设计与实现
java·vue.js·spring boot
励志前端小黑哥2 小时前
有了Miniconda,再也不用担心nodejs、python、go的版本问题了
前端·python
喵叔哟2 小时前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特2 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts