element源码(二)Layout 布局组件

系列文章目录

第一章 element源码(一)简要介绍
第二章 element源码(二)Layout 布局组件


一、layout布局组件介绍

是响应式布局的常见方式。官方介绍是 ”通过基础的 24 分栏,迅速简便地创建布局“,也很好理解。在这里插入图片描述

二、组件组成

el-row,el-col两个组件,然后简单介绍一下element源码的组件结构。所有组件放在packages文件夹下,下属每一个文件夹对应element中的组件。然后组件文件夹结构分src和index,src下是组件代码,index引入并定义函数注册组件,主要是为了实现element的按需导入。
在这里插入图片描述


三、组件按需导入

先看一下index.js源码

import ElCol from './src/col';

/* istanbul ignore next */
ElCol.install = function(Vue) {
  Vue.component(ElCol.name, ElCol);
};

export default ElCol;

从src中引入col组件代码,然后定义install 方法(vue的知识不了解的看一下源码),该方法中注册了全局的组件el-col。在vue的main.js中使用Vue.use(Component)会调用install方法注册全局的组件,就实现了组件的按需导入


四、col组件

先看一下/src/col.js源码

	render (h) {
		//这里删除了一些属性上的处理,先理解基础的结构
		return h(this.tag, {
			class: ['el-col', classList],
			style
		}, this.$slots.default);
	}

简单介绍一下vue的render函数参数h方法,h(标签名,属性,内容)。这里内容this.$slots.default,涉及到slot插值的知识,<slot></slot>也是具名插槽知识默认为default,等同于<slot name="default"></slot>
在render函数中定义,与在template中定义差不多,使用template最后也会转换成render,所以vue也支持直接用render定义组件。这里element用render主要是为了this.tag可以自定义

	<template>
		<div class="el-col">
			<slot></slot>
		</div>
	</template>

如果template定义,tag只能是div,用父组件用props传tag就可以自定义tag,默认为div

props: {
		tag: {
			type: String,
			default: 'div'
		},
	},

五、row组件

与el-col组件相同,不做详细介绍


六、组件的属性 feature

element在组件上定义了很多属性,实现组件的个性化也扩展了组件的使用。有文章称之为feature特征,下面我挑一些常用的feature解析,达到学习element编程思路的目的即可,有时间我会把所有feature的解析做全

1.span

官方介绍”栅格占据的列数“。挺好理解的,总共24份:span="1"就是占1/24
在这里插入图片描述
老规矩,先看一下src/col源码

props: {
    span: {
      type: Number,
      default: 24
    },
   ...//文中省略号,均是与当前解析不相关的;以后不再赘述
  },
  render(h) {
    let classList = [];
    let style = {};
	...
    ['span', 'offset', 'pull', 'push'].forEach(prop => {
      if (this[prop] || this[prop] === 0) {
        classList.push(
          prop !== 'span'
            ? `el-col-${prop}-${this[prop]}`
            : `el-col-${this[prop]}`
        );
      }
    });
	...
    return h(this.tag, {
      class: ['el-col', classList],
      style
    }, this.$slots.default);
  }

这片代码就干一件事,父组件传过来的:span="1"转化为类名el-col-1,代码的实现过程,大家自己理解吸收一下。那现在el-col有了类型el-col-1还不够,还要定义类名样式.el-col-1{width:4%}
下面给大家介绍一下element对样式的处理,样式源码都在/package/theme-chalk/src下面基本上可以找到组件对应的文件,例如col.scss
先看一下col.scss源码

[class*="el-col-"] {
  float: left;
  box-sizing: border-box;
}

.el-col-0 {
  display: none;
}

@for $i from 0 through 24 {
  .el-col-#{$i} {
    width: (math.div(1 , 24) * $i * 100) * 1%;
  }
  ...
}

涉及到scss中@for循环,我以后开个栏目专门介绍scss,我也是在读源码的同时理解了很多scss的使用,
这里就是0-24循环,$i是索引号,#{}实在类名中插值类似vue中{{}}将变量插入,这段代码编译出来就是.el-col-1到.el-col-24的样式。与col.js的处理对应上,到处就属性span就实现了。push,pull,offset都是类似的处理只是样式上是对margin的设置。

2.gutter

官方介绍"栅格间隔",el-col的间隔。
在这里插入图片描述
其实与上面的span很类似,就是:gutter="2"在el-col左右margin为1就可以,然后el-row再向外margin拉开1px(这个自己理解一下)。但是这里有个特殊的地方是:gutter设置在el-row上,我们看一下element是怎么处理的这种情况。

computed: {
		gutter () {
			let parent = this.$parent;
			while (parent && parent.$options.componentName !== 'ElRow') {
				parent = parent.$parent;
			}
			return parent ? parent.gutter : 0;
		}
	},

在computed中循环去找父节点一直找到根节点。拿到el-row中的gutter,没有就默认为0。
这里有看见过文章介绍可以用provide/inject替代,el-row中provide传参,el-col中inject接收,这种方法可能更优

3.对齐方式

官方介绍:”通过 flex 布局来对分栏进行灵活的对齐“
将 type 属性赋值为 ‘flex’,可以启用 flex 布局,并可通过 justify 属性来指定 start, center, end, space-between, space-around 其中的值来定义子元素的排版方式。
在这里插入图片描述
这里的处理很简单根据属性传参,确定display:flex以及对齐方式。但是在scss中的处理,我感觉值得借鉴,这里element的应用了bem规范 即block__element–modifier 块__元素–修饰,然后也涉及到scss中的@mixin。
看一下三段源码

// /pages/theme-chalk/src/mixins/config.scss
$namespace: 'el';
$element-separator: '__';
$modifier-separator: '--';
$state-prefix: 'is-';

// /pages/theme-chalk/src/mixins/mixins.scss
/* BEM
 -------------------------- */
@mixin b($block) {
  $B: $namespace+'-'+$block !global;

  .#{$B} {
    @content;
  }
}


@mixin e($element) {
  $E: $element !global;
  $selector: &;
  $currentSelector: "";
  @each $unit in $element {
    $currentSelector: #{$currentSelector + "." + $B + $element-separator + $unit + ","};
  }

  @if hitAllSpecialNestRule($selector) {
    @at-root {
      #{$selector} {
        #{$currentSelector} {
          @content;
        }
      }
    }
  } @else {
    @at-root {
      #{$currentSelector} {
        @content;
      }
    }
  }
}

@mixin m($modifier) {
  $selector: &;
  $currentSelector: "";
  @each $unit in $modifier {
    $currentSelector: #{$currentSelector + & + $modifier-separator + $unit + ","};
  }

  @at-root {
    #{$currentSelector} {
      @content;
    }
  }
}

@mixin when($state) {
  @at-root {
    &.#{$state-prefix + $state} {
      @content;
    }
  }
}

// /pages/theme-chalk/src/row.scss
@include b(row) {
  position: relative;
  box-sizing: border-box;
  @include utils-clearfix;

  @include m(flex) {
    display: flex;

    &:before,
    &:after {
      display: none;
    }

    @include when(justify-center) {
      justify-content: center;
    }
  }
}

这里的三段代码很长,涉及到scss的东西有点多,不是很好懂。我会分析带大家一起读懂。
1,首先是/pages/theme-chalk/src/mixins/config.scss,这就是一个config文件,用来定义4个常量,英语不好的用词典翻译一下也知道是什么意思。$namespace名字空间el,很多element中的类名都是el-xxx就是用这个常量定义;$element-separator$modifier-separator分别是bem规范中__元素分割和–修饰分割;$state-prefix是用来确定属性的,例如el-row中的属性justify="center"会转变成类名is-center,后面详细介绍。
2,/pages/theme-chalk/src/mixins/mixins.scss,只是@mixin处理的文件,要想弄明白element中scss的运用,就必须看懂这个文件。有四个@minx,分别是@mixin b()@mixin e()@mixin m()@minxin when()

@mixin b($block) {
  $B: $namespace+'-'+$block !global;

  .#{$B} {
    @content;
  }
}

@mixin b($block){ } block是参数@include b(row) { } 引入时block就是row。
$B: $namespace+'-'+$block !global; 定义变量B:el-row。namespace就是上分文件中的el; !global就是提升变量B为全局的不仅@mixin b(){}中能使用
.#{$B} {@content;} #{}前面解释过,@content类似与插槽,@include b(row) {position: relative; box-sizing: border-box; }中间的内容插入替换@content

@include b(row) {
	position: relative; box-sizing: border-box;
}
// => 编译为以下
.el-row{
	position: relative; box-sizing: border-box;
}

另外三个@mixin不带大家解析,其中有一个scss@root语法查一下文档就行,其他都能看懂

3,/pages/theme-chalk/src/row.scss中el-row的class定义直接@include引用mixin,

@mixin b(row) {
  @include m(flex) {
    @include when(justify-center) {
      justify-content: center;
    }
  }
}
// => 编译为以下
.el-row--flex.is-justify-center {
  justify-content: center;
}

父组件中传参type和justify,el-col组件设置对应的class。到此el-row中对齐方式就实现了。

总结

以上就是有关layout布局组件的解析。有一些属性没有展开细讲,大家看源码理解吸收,有不懂的欢迎交流讨论

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值