This is the 15th day of my participation in the August More Text Challenge

0 x00 profile

The previous 📚 Layout (raster) Layout system component source code analysis in detail explains the component code generation logic, this article on the basis of in-depth analysis, patience to read, I believe that will help you.

For more component profiling see 👉 📚 Element 2 source profiling Component Overview.


0x01 Column Gutter implementation principle

Layouts can be freely combined through row and COL components, and through the SPAN property of the COL component. Use
to create two columns of equal width. Use the row component to provide the gutter attribute to specify the space between each column. The default unit is px.

The following code creates a row with two equally wide columns spaced 24px apart.

<el-row :gutter="24">
  <el-col :span="12"><div>col</div></el-col>
  <el-col :span="12"><div>col</div></el-col>
</el-row>
Copy the code

The page rendered looks like 👇 :

The space between columns is equal to the attribute value gutter. The space to the left of the first column and to the right of the trailing column is gutter/2. The layout is as follows 👇 :

The calculated attribute gutter in the col component gets the gutter value of the parent component row and calculates the column’s padding-left padding-right in render() based on the gutter value of the calculated attribute, with a value of gutter / 2 + ‘px’.

// packages\col\src\col.js
computed: {
  // Get the gutter value of el-row
  gutter() {
    // The parent instance is the component EL-row according to the compontName attribute
    let parent = this.$parent;
    while(parent && parent.$options.componentName ! = ='ElRow') {
      parent = parent.$parent;
    }
    return parent ? parent.gutter : 0; }},render(h) {
  let classList = [];
  let style = {};
  
  // Calculate the left and right padding of your gutter to separate col
  if (this.gutter) {
    style.paddingLeft = this.gutter / 2 + 'px';
    style.paddingRight = style.paddingLeft;
  }

  / / class

  return h(this.tag, {
    class: ['el-col', classList],
    style
  }, this.$slots.default);
}
Copy the code

Gutter = padding-right of the left column plus padding-left of the right column; The left interval value of the first column is padding-left; The right spacing value of the trailing column is padding-right. The effect is as follows 👇 :

Other 3 column, 4 column,…… , 24 and so on, the feeling is not very well understood! Margin-left margin-right = margin-left; margin-right = margin-left;

// packages\row\src\row.js
computed: {
  style() {
    const ret = {};  
    if (this.gutter) {
      ret.marginLeft = ` -The ${this.gutter / 2}px`;
      ret.marginRight = ret.marginLeft;
    } 
    returnret; }},Copy the code

As mentioned above, the row calculation attribute style offsets the padding of the COL component by setting a negative margin for the component, which indirectly cancels out the padding for the column contained in the row.

Next, it is illustrated by examples and diagrams.

Insert a row (containing two equal-width columns) in the first row, first column in the previous example, with the following code 👇 :

<! -- row1 -->
<el-row :gutter="24">
  <! -- col1 -->
  <el-col :span="12">
    <el-row :gutter="24">
      <el-col :span="12"><div>col</div></el-col>
      <el-col :span="12"><div>col</div></el-col>
    </el-row>
  </el-col>
  <! -- col2 -->
  <el-col :span="12"><div>col</div></el-col>
</el-row>
Copy the code

Assume that component row is not set to negative value and margin is 0. In the first row, in the first column, the space between the two columns nested has one more padding (gutter/2) than the default setting. Gutter /2 * 3 between the two columns. Nest one more layer, increase the gutter/2. The implementation effect is as follows 👇 :

If the component row calculation attribute style is set to a negative margin for the component, the absolute value is gutter/2. The width of the row in the nest increases the gutter, which cancels out the padding for the COL component. This column has no padding. The implementation effect is as follows 👇 :

Based on this logic, no matter how many levels of nesting you do, you can guarantee consistent spacing between columns. The actual rendering of the code looks like 👇 :


0x02 Row Component style

SCSS uses mixed instructions B, M, utils-clearfix to generate component styles.

/ / generated. El - row
@include b(row) {
  position: relative;
  box-sizing: border-box;
  // Generate.el-row::after,.el-row::before using the clear float directive
  @include utils-clearfix;
  
  // Flex layout is generated. El-row --flex
  @include m(flex) {
    display: flex; 
    El-row --flex:after,. El-row --flex:before
    &:before,
    &:after {
      display: none;
    }
    // Alignment
    / / generated. El - row - flex. Is the justify - center
    @include when(justify-center) {
      justify-content: center;
    }
    // Generates.el-row-- flex.is-context-end
    @include when(justify-end) {
      justify-content: flex-end;
    }
    / / generated. El - row - flex. Is - the justify - space - between
    @include when(justify-space-between) {
      justify-content: space-between;
    }
    / / generated. El - row - flex. Is - the justify - space - around
    @include when(justify-space-around) {
      justify-content: space-around;
    }
    / / generated. El - row - flex. Is - align - middle
    @include when(align-middle) {
      align-items: center;
    }
    / / generated. El - row - flex. Is - align - bottom
    @include when(align-bottom) {
      align-items: flex-end; }}}Copy the code

Gulpfile. js is used to compile SCSS files and convert them to CSS. After browser compatibility and format compression, packages\theme-chalk\lib\row. CSS is generated.

.el-row { / *... * / }
/ *... clearfix... * /
.el-row::after..el-row::before { / *... * / }
.el-row::after { / *... * / }
/ *... flex... * /
.el-row--flex { / *... * / }
.el-row--flex:after, .el-row--flex:before { /*... * /}/ *... justify-content... * /
.el-row--flex.is-justify-center { / *... * / }
.el-row--flex.is-justify-end { / *... * / }
.el-row--flex.is-justify-space-between { / *... * / }
.el-row--flex.is-justify-space-around { / *... * / }
/ *... align-items... * /
.el-row--flex.is-align-middle { / *... * / }
.el-row--flex.is-align-bottom { / *... * / }
Copy the code

0x03 Col Component Style

SCSS generates component styles to implement column, interval, offset, and responsive functions.

Column, interval, offset

Use the @for loop to generate styles 0 through 24:

  • spanThe number of columns occupied by the grid, as specified by width, corresponds to the style.el-col-[n] 。
  • offsetThe number of spaced grids to the left of the grid, implemented by margin-left, corresponding to the style.el-col-offset-[n] 。
  • pushThe grid moves the number of grids to the right by left, corresponding to the style.el-col-push-[n] 。
  • pullThe grid moves the number of cells to the left by right, corresponding to the style.el-col-pull-[n] 。

The component grid system uses 24 columns, all with a baseline width of (1/24 * 100) * 1% per column.

[class*="el-col-"] {
  float: left;
  // How to calculate the total width and height of an element
  box-sizing: border-box;
}
// Components are not rendered
.el-col-0 {
  display: none;
}

@for $i from 0 through 24 {
  / / generated. El - col - [24] 0 -
  .el-col-#{$i} {
    width: (1 / 24 * $i * 100) * 1%;
  }
  / / generated. El - col - offset - [24] 0 -
  .el-col-offset-#{$i} {
    margin-left: (1 / 24 * $i * 100) * 1%;
  }
  / / generated. El - col - pull - [24] 0 -
  .el-col-pull-#{$i} {
    position: relative;
    right: (1 / 24 * $i * 100) * 1%;
  }
  / / generated. El - col - push - [24] 0 -
  .el-col-push-#{$i} {
    position: relative;
    left: (1 / 24 * $i * 100) * 1%; }}Copy the code

Responsive layout

The system has five preset response sizes: XS SM MD LG XL. Reactive design is achieved by generating media queries using the directive RES.

// 'xs', 'sm', 'md', 'lg', 'xl' 
// Generate @media only screen and (max-width: 767px) {... }
@include res(xs) {
  / / generated. El - col - xs - 0
  .el-col-xs-0 {
    display: none;
  }
  @for $i from 0 through 24 {
    / / generated. El - col - xs - [24] 0 -
    .el-col-xs-#{$i} {
      width: (1 / 24 * $i * 100) * 1%;
    }
    / / generated. El - col - xs - offset - [24] 0 -
    .el-col-xs-offset-#{$i} {
      margin-left: (1 / 24 * $i * 100) * 1%;
    }
    / / generated. El - col - xs - pull - [24] 0 -
    .el-col-xs-pull-#{$i} {
      position: relative;
      right: (1 / 24 * $i * 100) * 1%;
    }
    / / generated. El - col - xs - push - [24] 0 -
    .el-col-xs-push-#{$i} {
      position: relative;
      left: (1 / 24 * $i * 100) * 1%; }}}@media only screen and (min-width: 768px) {// generate @media only screen and (min-width: 768px) {... }
@include res(sm) { / *... * / }
@media only screen and (min-width: 992px) {// generate @media only screen and (min-width: 992px) {... }
@include res(md) { / *... * / }
@media only screen and (min-width: 1200px) {// generate @media only screen and (min-width: 1200px) {... }
@include res(lg) { / *... * / }
@media only screen and (min-width: 1920px) {// generate @media only screen and (min-width: 1920px) {... }
@include res(xl) { / *... * / }
Copy the code

0 x04 📚 reference

“Media Inquiry “,MDN

0x05 Attention column

This article has been included in the column 👇, you can directly follow.