This is the 14th day of my participation in the August More Text Challenge. For details, see: August More Text Challenge
0 x00 profile
The component provides a Grid Layout system for creating layouts quickly and easily from a basic 24 columns. The system is created using the Row and Col grid components. This article will in-depth analysis of the source code, analysis of its implementation principle, patience to read, I believe that you will be helpful.
Component document Layout
Gitee source line component Row. js
gitee source line component col.js
For more component profiling see
Element 2 Source Code Profiling Component Overview.
0x01 Grid Layout
Rasterization improves the consistency and reusability of the page layout and the efficiency of the entire design and development process. At the same time, make the layout of the web page more standardized and concise, improve user experience.
Grid.Guide, you can freely set the maximum width, number of columns and white margin automatically generate a variety of optimal Grid scheme for selection.
Bootstrap provides a responsive, mobile-first streaming raster system that automatically divides into up to 12 columns as the screen or viewport size increases.
Element 2 adopts Ant Design’s Design concept: Based on the 12-grid system, the entire proposed Design area is divided into 24 equal sections to solve the problem of large amount of information in the Design area.
The rasterization layout system defines the external framework of the information block through a series of rows and columns to ensure that each area of the page is robustly arranged. Here’s how a grid system works:
- through
row
Create a group in the horizontal directioncolumn
(col). - Content should be placed in
col
Inside, and onlycol
Can be used as arow
Direct elements of. - The columns in a grid system have values from 1 to 24 to indicate the range they span. For example, three columns of equal width can be used
<col :span="8" />
To create. - If a
row
In thecol
If the sum is more than 24, then the extracol
It will be lined up as a whole.
Component rows (ROW) and columns (COL) are discussed next.
0x02 Row Row component
/row/ SRC /row.js uses rendering functions to build components that can be rendered into custom element tags. This is used as a container for col.
render()
The component renders the label node according to the specified custom element, dynamically calculates the value of the component prop property to add classes and custom styles (calculates the property style), and internally provides an anonymous slot for distributing content.
render(h) {
return h(this.tag, {
class: [
'el-row'.this.justify ! = ='start' ? `is-justify-The ${this.justify}` : ' '.this.align ! = ='top' ? `is-align-The ${this.align}` : ' ',
{ 'el-row--flex': this.type === 'flex'}].style: this.style
}, this.$slots.default);
}
Copy the code
In JSX syntax, h is used as an alias for createElement. The second parameter is a data object, VNodeData, that contains template-related properties, as follows.
{
// Same API as' v-bind:class ',
// Accept a string, object, or array of strings and objects
'class': {
foo: true.bar: false
},
// Same API as' v-bind:style ',
// Accept a string, object, or array of objects
style: {
color: 'red'.fontSize: '14px'
},
// ...
}
Copy the code
If the custom element tag is
<template>
<div
:style="style"
:class="[ 'el-row', justify !== 'start' ? 'is-justify-' + justify : '', align !== 'top' ? 'is-align-' + align : '', { 'el-row--flex': type === 'flex' } ]"
>
<slot></slot>
</div>
</template>
Copy the code
Component props
This component defines five prop: Tag, gutter, Type, justify, and align.
tag
Supports components to render as custom HTML tags, which default to div as the first argument to the createElement method.
props: {
tag: {
type: String.default: 'div'}},Copy the code
gutter
Grid interval setting, used to specify the interval between each column. The default interval is 0. The COL component calculates its left and right padding by taking the gutter of its parent row.
props: {
gutter: Number,},Copy the code
Flex Layout Settings
Type Sets the layout mode. Flex is optional and only works in modern browsers.
props: {
type: String,},Copy the code
If type is flex, {‘el-row–flex’: type === ‘flex’} will add class el-row–flex, enabling the Flex layout.
.el-row--flex {
display: flex;
}
Copy the code
The value of justify is used to set the horizontal arrangement in the Flex layout. The value can be start/end/center/space-around/space-between. The generated style is-justify-[justify], which is used to set the inter-content attribute. Other values generate invalid styles.
Align is used to set the vertical arrangement in the Flex layout. The optional values top/middle/bottom and the resulting style is-align-[align] are used to set the align-items property. Other values generate invalid styles.
props: {
// Flex layout horizontal arrangement of text -content
justify: {
type: String.default: 'start'
},
// Flex layout align-items
align: {
type: String.default: 'top'}},Copy the code
The default layout of the element does not generate the Flex style justify! == ‘start’ ? ‘is- ‘+ text: ‘,, align! == ‘top’ ? Align -‘ + align: ‘,.
The system is based on a Flex layout that allows horizontal alignment of child elements within the parent node – left, center, right, equal-width, scattered. Child elements can be aligned at the top, vertical center, or bottom.
Flex layout, a simple, complete, and responsive implementation of a variety of page layouts. This article does not elaborate on the syntax, see “Flex Layout Tutorial”, Ruan Yifeng.
Calculate attribute
The style property is calculated to cancel out the padding for the COL component by setting negative margin for the ROW component, and indirectly to cancel out the padding for the columns contained in the row.
computed: {
style() {
const ret = {};
// Calculate the actual left and right margins from the gutter
if (this.gutter) {
ret.marginLeft = ` -The ${this.gutter / 2}px`;
ret.marginRight = ret.marginLeft;
}
returnret; }},Copy the code
0x03 Col Column component
Use rendering functions to build components that support rendering custom element tags.
render()
The component renders the label node according to the specified custom element, adds classes and custom styles dynamically calculated by the component prop property value, and provides an anonymous slot internally for distributing content.
render(h) {
let classList = [];
let style = {};
/ / sytle
/ / class
return h(this.tag, {
class: ['el-col', classList],
style
}, this.$slots.default);
}
Copy the code
If the custom element tag is
<template>
<div
:style="style"
:class="['el-col', classList]"
>
<slot></slot>
</div>
</template>
Copy the code
Component props
10 prop are defined. See the Chinese annotation for the specific functions. Span defaults to 24, which corresponds to 24 columns of the grid system.
props: {
// Customize the element tag
tag: {
type: String.default: 'div'
},
// The number of columns occupied by the grid, 24 in total, if set to 0, will not render
span: {
type: Number.default: 24
},
// The number of spacers to the left of the grid
offset: Number.// Move the grid to the right
pull: Number.// Move the grid to the left
push: Number.// Reactive layout Settings
// Reactive grid number or grid attribute object number/object (for example: {span: 4, offset: 4})
// xs <768px sm ≥768px MD ≥992px LG ≥1200px xl ≥1920px
xs: [Number.Object].sm: [Number.Object].md: [Number.Object].lg: [Number.Object].xl: [Number.Object]},Copy the code
Calculate attribute
Calculate the gutter property to get the gutter value of the parent row. Use the custom property of the row component to judge the rows. = = ‘ElRow’.
computed: {
gutter() {
// GetCompontName (compontName)
let parent = this.$parent;
while(parent && parent.$options.componentName ! = ='ElRow') {
parent = parent.$parent;
}
return parent ? parent.gutter : 0; }},// packages\row\src\row.js
export default {
name: 'ElRow'.// Customize the property
componentName: 'ElRow',}Copy the code
Component padding
If the gutter value is not zero, calculate the left and right paddings of the COL.
render(h) {
let style = {};
/ / sytle
if (this.gutter) {
style.paddingLeft = this.gutter / 2 + 'px'; style.paddingRight = style.paddingLeft; }}Copy the code
The component class
Column, interval, left and right deviation
Dynamic calculation of grids, intervals, and left and right offsets.
// span Specifies the number of columns occupied by the grid
// Offset the number of spacing cells on the left of the grid, achieved by margin-left
// Push the grid to the right by left
// Pull the grid to the left
['span'.'offset'.'pull'.'push'].forEach(prop= > {
if (this[prop] || this[prop] === 0) { classList.push( prop ! = ='span'
? `el-col-${prop}-The ${this[prop]}`
: `el-col-The ${this[prop]}`); }});Copy the code
Col component style SCSS implementation. When span is set to 0, the component display value is None and will not be rendered.
[class*="el-col-"] {
float: left;
// How to calculate the total width and height of an element
box-sizing: border-box;
}
// The component does not render
.el-col-0 {
display: none;
}
@for $i from 0 through 24 {
// Generate.el-col-0,.el-col-1,... ,el-col-24
.el-col-# {$i} {
width: (1 / 24 * $i * 100) * 1%;
}
// Generate.el-col-offset-0,.el-col-offset-1,... ,el-col-offset-24
.el-col-offset-# {$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
// Generate.el-col-pull-0,.el-col-pull-1... ,el-col-pull-24
.el-col-pull-# {$i} {
position: relative;
right: (1 / 24 * $i * 100) * 1%;
}
// Generate.el-col-push-0,.el-col-push-1... ,el-col-push-24
.el-col-push-# {$i} {
position: relative;
left: (1 / 24 * $i * 100) * 1%; }}Copy the code
Responsive layout
Reactive layout styles are dynamically computed. Preset four response sizes: XS, SM, MD, LG. We can also pass in objects {span: 4, offset: 4} with optional span/offset/pull/push attributes.
// xs <768px reactive grid number or grid property object
// sm ≥768px Response grid number or grid attribute object
// md ≥992px Response grid number or grid attribute object
// LG ≥1200px response grid number or grid attribute object
// xl ≥1920px Response grid number or grid property object
['xs'.'sm'.'md'.'lg'.'xl'].forEach(size= > {
if (typeof this[size] === 'number') {
classList.push(`el-col-${size}-The ${this[size]}`);
} else if (typeof this[size] === 'object') {
let props = this[size];
Object.keys(props).forEach(prop= >{ classList.push( prop ! = ='span'
? `el-col-${size}-${prop}-${props[prop]}`
: `el-col-${size}-${props[prop]}`); }); }});Copy the code
Use the res command to generate the @media media query style. The SCSS implementation is as follows:
// 'xs', 'sm', 'md', 'lg', 'xl'
@media only screen and (min-width: XXX px)
@include res(sm) {
/ / generated. El - col - sm - 0
.el-col-sm-0 {
display: none;
}
@for $i from 0 through 24 {
// Generate.el-col-sm-0,.el-col-sm-1... ,el-col-sm-24
.el-col-sm-# {$i} {
width: (1 / 24 * $i * 100) * 1%;
}
/ / generated. El - col - sm - offset 0, the el - col - sm - offset - 1,... ,el-col-sm-offset-24
.el-col-sm-offset-# {$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
// Generate.el-col-sm-pull-0,.el-col-sm-pull-1... ,el-col-sm-pull-24
.el-col-sm-pull-# {$i} {
position: relative;
right: (1 / 24 * $i * 100) * 1%;
}
// Generate.el-col-sm-push-0,.el-col-sm-push-1... ,el-col-sm-push-24
.el-col-sm-push-# {$i} {
position: relative;
left: (1 / 24 * $i * 100) * 1%; }}}Copy the code
0 x04
reference
“Render function & JSX”, vuejs.org “@media”, MDN
0x05 Watch the column
This article has been included in the column , you can directly follow.