菜鸟读element源码四el-container

组件Container

官网上对于Container布局容器的描述以下图vue

Container是一个容器组件,根据官网的描述它的子元素只能是 el-headel-asideel-mainel-footer四者,而四者的父元素也只能是 Container。咱们先来模仿 el-container源码

模仿代码中均以el-test 替换el, 目的是为了边模仿边测试和el组件的效果对比node

<template>
  <section class="el-test-container" :class="{'el-test-is-vertical': isVertical}">
    <slot></slot>
  </section>
</template>
<script>
export default {
  name: 'ElTestContainer',

  componentName: 'ElTestContainer',

  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 => {
        let tag = vnode.componentOptions && vnode.componentOptions.tag
        return tag === 'el-test-header' || tag === 'el-test-footer'
      }) : false
    }
  },
}
</script>
复制代码

container组件算是一个最基本的tempalte形式的vue文件。浏览器

isVertical是为了判断是否须要垂直布局,若是未设置,则根据子元素是否包含el--headerel-footer来决定。this.$slots是组件的实例属性,由于组件是能够复用的VUE实例,所以和 new Vue()同样,均还有如下属性bash

先判断 this.$slots是否存在,若是存在,遍历 this.$slots.default,即遍历 <slot></slot>中的子元素,若是子元素中存在tag为 el-header || el-footer则返回为true。此处 some函数的使用是在若是有一个为 true则返回 truethis.slots this.$slots.default 的关系以下

console.log(this.$slots)
console.warn(this.$slots.default)
复制代码

this.$slots.defaullts中的每个元素都是一个 VNode,vue的节点,包含该元素的 全部信息,咱们所须要的 tag属性,放在 componentOptions.tag中。 VNode的信息基本以下

子组件header

<template>
  <header class="el-test-header" :style="{height}">
    <slot></slot>
  </header>
</template>
<script>
export default {
  name: 'ElTestHeader',

  componentName: 'ElTestHeader',

  props: {
    height: {
      type: String,
      default: '60px'
    }
  }
}
</script>


复制代码

几个子组件的样式均长得差很少,不一样的在于样式文件中,el-headel-footer均设置了flex-shrink = 0表示子组件el-headerel-footer均不会被压缩。ide

总结

container 组件基本简单,感受核心在于flex语法的应用,特别是flex-grow flex-shrink flex-basis的应用。所以最后对于flex-grow, flex-shrink, flex-basis作个总结函数

flex-grow 扩展比例布局

flex-shrink 收缩比例测试

flex-basis 伸缩基准值flex

当父元素设置了display:flex属性的时候,子元素设置flex便可生效。在flex的三个属性当中,flex-basis是做为基准值,是计算最后展示出来的子元素宽度的决定性因素,grow shrink是否起做用须要依赖于basisui

假设咱们的样例代码

<div style="display:flex">
    <div style="flex:1;border:1px solid red;height:30px;"></div>
    <div style="flex:2;border:1px solid green;height:30px;"></div>
</div>
复制代码

此时flex在浏览器中展示以下

此时两个子元素的basis属性之和小于父元素的宽度,此时grow会起做用。此时除了子元素自己宽度以外,剩余宽度将按照1:2的比例分配给两个子元素。 计算公式以下

(剩余空间m) = (父元素宽度width) - (子元素basic之和)
(当前子元素最终宽度final) =  (剩余宽度m) * (当前子元素的grow值) / (因此子元素的grow值之和)  +   (当前子元素的basis)
复制代码

样例代码

<div style="display:flex">
      <div style="flex:0 1 1000px;border:1px solid red;height:30px;"></div>
      <div style="flex:0 4 1000px;border:1px solid green;height:30px;"></div>
    </div>
复制代码

此时两个子元素的basis属性之和大于父元素的宽度,此时shrink会起做用。此时子元素basis之和大于父元素宽度,basis之和减去父元素宽度,获得的溢出宽度将按照1:4的比例压缩两个子元素。

计算公式以下

(溢出宽度m) = (子元素basis之和) -  (父元素宽度width)
(当前子元素最终宽度final) = (当前子元素的basis) -  (溢出宽度m) * (当前子元素的shrink值) / (因此子元素的shrink值之和)
复制代码

google看到了flex存在三个关键字 none initial auto 以下所示

相关文章
相关标签/搜索