ElementUI 简要源码解析——Basic篇
Layout 布局
row
布局组件中的父组件,用于控制子组件。很简单的一个布局标签,主要通过 justify 和 align 控制子元素的对齐方式,使用 render 函数通过传入的 tag 属性控制生成的标签。
在这里推荐学习下 render 函数和 JSX 的写法,因为之后比较复杂的组件都是通过 render函数 + JSX 的方式来写的。
// 核心代码
render(h) {
return h(this.tag, {
class: [
'el-row',
this.justify !== 'start' ? `is-justify-${this.justify}` : '',
this.align !== 'top' ? `is-align-${this.align}` : '',
{ 'el-row--flex': this.type === 'flex' }
],
style: this.style
}, this.$slots.default);
}
col
布局组件中的子组件,通过传入的props控制占据的列数、偏移、大小等,通过 forEach 对每个属性进行处理,生成包含对应样式的 classList。
最后将 classList 传入 createElement 函数(h)中的第二个参数(标签选项)中,如此,就生成了所需要的布局。
// 核心代码
render (h) {
// 省略,通过props计算classList
return h(this.tag, {
class: ['el-col', classList],
style
}, this.$slots.default);
}
Container 布局容器
container
父容器组件,根据传入的direction字段,决定样式是水平还是垂直。当没有传入direction字段时,根据插槽中子组件是否含有 header 或 footer组件,如果含有则为垂直,否则为水平。
// 核心代码
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 === 'el-header' || tag === 'el-footer';
})
: false;
}
}
header
最简单的组件之一,通过传入的 height 参数定义 style 高度。
aside
最简单的组件之一,通过传入的 width 参数控制 style 宽度。
main
真正意义上的最简单容器组件,包含插槽的纯容器。
el-footer
最简单的组件之一,通过传入的 height 参数定义 style 高度。
布局容器总结
何为容器?在我的理解中,容器就是一个限制大小的盒子。布局容器通过属性定义 header、aside、footer 的高宽的行内样式,接下来只需要定义 main 为 flex: 1 即可实现自适应布局。
Icon 图标
感觉比较没有意义的一个组件,通过传入的 name 来组成类似于 el-icon-name 格式的类,然后将这个类定义在 i 标签内。不过大多数人都不会用这个组件,为什么?因为连官网推荐写法都是直接在 i 标签内添加对应图标的类。
Button 按钮
Button 组件是 Basic 里面唯一一个稍微复杂一点的组件。它与其他 Basic 组件的最大区别在于,通过 provide/inject 获取了祖先组件,然后参照祖先组件的尺寸参数,将 Button 组件的尺寸参数设为一致。
Button 组件的尺寸由三个因素决定:
- 直接设置组件的 size 属性,该因素具有最高优先级,类比于样式中的行内样式。
- 当 Button 运用在 Form 组件中,可以通过配置 Form 组件的 size 属性来决定,当没有直接设置 Button 组件的 size 属性时,由该因素决定 Button 组件的尺寸,类比于样式中的样式继承。
- 当前两种因素都不存在时,由
this.$ELEMENT对象中的 size 属性决定。What?this.$ELEMENT什么鬼?它是接收初始化 ElementUI 时传入的尺寸参数的对象,包含两个属性:size 以及 zIndex,方便全局定义各种组件的尺寸。类比于样式中的 body 样式继承。
// 核心代码
export default {
name: 'ElButton',
// 通过 inject 获取 elForm 以及 elFormItem 这两个组件
inject: {
elForm: {
default: ''
},
elFormItem: {
default: ''
}
},
// ...
computed: {
_elFormItemSize() {
return (this.elFormItem || {}).elFormItemSize;
},
buttonSize() {
// 三种因素决定按钮的尺寸
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;
},
//...
},
// ...
};
Link 文字链接
和一般文字链接区别不大的一个组件,主要区别在于两点:
- 可以通过 disabled 属性设置禁用,原理是当 disabled 属性为 false 时,将 a 标签的 href 属性置为 null,同时阻止阻止其向上抛出 click 事件。
- 灵活运用插槽,看似该组件只有一个插槽,实则拥有两个插槽,一个是匿名插槽,一个是名为 icon 的具名插槽,通过合理的设置可以快速实现各种需求。
值得一提的是,该组件还使用了一个通用组件开发的小技巧:通过 v-bind="$attrs" 进行快速属性赋值。为什么要这样做?因为 a 标签可以含有各种 html 属性,而这些属性我们不可能一一通过 props 接收然后赋值到 a 标签的属性上。
因此,我们可以通过 v-bind="$attrs" 无视传入的属性是什么,一股脑将其赋值到 a 标签上。这相当于,开发者可以直接像操作 a 标签一样操作 Link 组件,大大方便了组件的使用。
<template>
<a
:class="[
'el-link',
type ? `el-link--${type}` : '',
disabled && 'is-disabled',
underline && !disabled && 'is-underline'
]"
:href="disabled ? null : href"
v-bind="$attrs"
@click="handleClick"
>
<i :class="icon" v-if="icon"></i>
<span v-if="$slots.default" class="el-link--inner">
<slot></slot>
</span>
<template v-if="$slots.icon"><slot v-if="$slots.icon" name="icon"></slot></template>
</a>
</template>
总结
通读了 Basic 系列的源码,可以发现,这一部分的源码其实相对比较简单,但是,却又很多的小细节点值得学习,比如:通过 v-bind=$attrs 定义标签属性、通过组合插槽方便组件使用、通过多种因素设定属性以及各种缺省设计等等。
ElementUI 简要源码解析——Basic篇的更多相关文章
- jQuery2.x源码解析(缓存篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...
- jQuery2.x源码解析(构建篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 笔者阅读了园友艾伦 Aaron的系列博客< ...
- jQuery2.x源码解析(设计篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...
- jQuery2.x源码解析(回调篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...
- Shiro源码解析-Session篇
上一篇Shiro源码解析-登录篇中提到了在登录验证成功后有对session的处理,但未详细分析,本文对此部分源码详细分析下. 1. 分析切入点:DefaultSecurityManger的login方 ...
- myBatis源码解析-类型转换篇(5)
前言 开始分析Type包前,说明下使用场景.数据构建语句使用PreparedStatement,需要输入的是jdbc类型,但我们一般写的是java类型.同理,数据库结果集返回的是jdbc类型,而我们需 ...
- Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析
一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...
- myBatis源码解析-数据源篇(3)
前言:我们使用mybatis时,关于数据源的配置多使用如c3p0,druid等第三方的数据源.其实mybatis内置了数据源的实现,提供了连接数据库,池的功能.在分析了缓存和日志包的源码后,接下来分析 ...
- myBatis源码解析-反射篇(4)
前沿 前文分析了mybatis的日志包,缓存包,数据源包.源码实在有点难顶,在分析反射包时,花费了较多时间.废话不多说,开始源码之路. 反射包feflection在mybatis路径如下: 源码解析 ...
随机推荐
- 如何获取app配置文件内容
App.config: <appSettings> <add key="FCPConnection" value="Data Source=192.16 ...
- sqlserver从xlsx读取数据
exec sp_configure 'show advanced options',1 reconfigure exec sp_configure 'Ad Hoc Distributed Querie ...
- p批处理替换目录下文本中的字符串
@echo off rem 进入批处理文件所在的路径 cd C:\Users\zxh\Desktop\ " as "abc" ***** rem 定义要替换的新旧字符串 ...
- git pull和fetch的区别
详解git pull和git fetch的区别: - weixin_41975655的博客 - CSDN博客 https://blog.csdn.net/weixin_41975655/article ...
- 微信小程序把玩(二十)slider组件
原文:微信小程序把玩(二十)slider组件 slider滑动组件用的不太多,在其他平台反正我是用的不多 主要属性: wxml <slider max="100" step= ...
- DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS & PUBLISHING THEM TO THE MICROSOFT STORE
原文: DEPLOYING NATIVE UWP (UNIVERSAL WINDOWS PLATFORM) APPS FOR JAVA DEVELOPERS & PUBLISHING THEM ...
- 获取UWP配置文件中的版本信息
原文:获取UWP配置文件中的版本信息 在一般的软件中,我们都会显示当前软件的版本信息.以前作者都是在发版的时候修改一下UWP的配置文件中的版本信息和软件中的版本信息.但是每次这样很麻烦,有时间忘记修改 ...
- AngularJS的简单使用(入门级)
AngularJS诞生于2009年,由Misko Hevery 等人创建,后为Google所收购.是一款优秀的前端JS框架,已经被用于Google的多款产品当中. AngularJS有着诸多特性,最为 ...
- Linux升级OpenSSL版本
安装nginx的时候,出现了这样的问题: nginx : Depends: libssl1.0.0 (>= 1.0.2~beta3) but 1.0.1f-1ubuntu2.11 is to b ...
- Lamda一行代码实现"36选7"随机自动选号
南粤风采36选7是广东的一种彩票玩法.非常简单的从1-36个数字选7个. 今天在同事面前炫耀了一把,只用一行Lamda代码实现随机自动选号 Enumerable.Range(, ).Select(x ...