Introduction to the

The so-called layout container is the overall structure of the page, generally speaking, it is

,

,

container

The Container components

As the name implies, it is a container component that hosts child components. What characteristics should container components have? Blocky, highly adaptive, etc. Element adds a rule: If the child element contains

or

, all child elements will be vertically arranged up and down, otherwise horizontally arranged left and right. This is not surprising

<template>
  <section class="el-container" :class="{ 'is-vertical': isVertical }">
    <slot></slot>
  </section>
</template>

<script>
  export default {
    name: 'ElContainer'// Custom attributes are used for other components:'ElContainer',
    props: {
      direction: String
    },
    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; }}}; </script>Copy the code

This is a typical single-file vUE component, but the style part has been separated out. If you look at the Template part, you will see that it is just a

wrapper. The following components have seO-good semantic tag tags instead of divs, which are essentially block elements. The function of div is the same as that of div. Notice the

in

, this is the slot that holds the child component. If you don’t write it, there will be no child element and it will be an anonymous slot


@import "mixins/mixins"; @include b(container) { display: flex; flex-direction: row; flex: 1; flex-basis: auto; box-sizing: border-box; min-width: 0; @include when(vertical) { flex-direction: column; }}Copy the code

is a Flex layout, and the default orientation is landscape, where flex-basis:auto sets its base length to adaptive, where flex:1 means that if the container is surrounded by the parent container, So it’s going to allocate the remaining width or height and then we’re going to look at the JS part,isVertical is a calculation property, and first it checks if it has a direction property, and if it does, it just returns the horizontal or vertical layout, and if it doesn’t, it determines the layout direction by judging the child elements, and the focus is on the code here

isVertical() {...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;
}
Copy the code

This.$slots&& this.$slots.default returns false if it does not exist, then the child element is empty. This.$slots is an instance attribute of a component. A component is an instance of a reusable Vue, just like new Vue(), so it has the following attributes

this.$slots.default
some
<el-header>
<el-footer>
some
every

This.$slots.default is an array. Each element is a VNode. Vnodes are virtual nodes in the virtual DOM. > generates a virtual node, roughly as shown in the following figure

componentOptions

const vnode = new VNode(
    `vue-component-${Ctor.cid}${name ? `-${name}` : ' '}`,
    data, undefined, undefined, undefined, context,
    { Ctor, propsData, listeners, tag, children },
    asyncFactory
  )
Copy the code

ComponentOptions are {Ctor, propsData, listeners, tag, children} componentOptions are componentlisteners Printing out the VNode proves the above statement

So here’s a heuristic for how to determine the type of child elements. In summary, the function that evaluates attributes can determine its own Flex layout direction from child elements

Footer component

Since the rest of the components are very similar, I’ll analyze a Footer as follows

<template>
  <footer class="el-footer" :style="{ height }">
    <slot></slot>
  </footer>
</template>

<script>
  export default {
    name: 'ElFooter'// custom attributes to make it easier for other components to get the componentName componentName:'ElFooter',
    props: {
      height: {
        type: String,
        default: '60px'}}}; </script>Copy the code

This still encapsulates the native

and has a default height. Footer is essentially a block element, so let’s look at the SCSS code

@import "mixins/mixins";
@import "common/var";

@include b(footer) {
  padding: $--footer-padding;
  box-sizing: border-box;
  flex-shrink: 0;
}
Copy the code

Note the flex-shrink:0 code, which means that when the parent container becomes too small, the footer will not shrink but keep its original width. In other words, the footer will never shrink, even if it exceeds the container. Flex-shrink defaults to 1, which is equal scale shrinkage of all elements, for a layout like the one shown below

flex-shrink
flex:1
flex:grow:1,flex:shrink:1,flex-basis:auto
flex:grow

conclusion

All in all, the layout is essentially a wrapper around native containers, and if the browser does not support Flex, the layout will not work