菜鳥讀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 以下所示

相關文章
相關標籤/搜索