Element-UI Container 布局容器源码

6 篇文章 0 订阅

Element-UI Container 布局容器源码

用于布局的容器组件,方便快速搭建页面的基本结构:

<el-container>:外层容器。当子元素中包含 <el-header><el-footer> 时,全部子元素会垂直上下排列,否则会水平左右排列。

<el-header>:顶栏容器。

<el-aside>:侧边栏容器。

<el-main>:主要区域容器。

<el-footer>:底栏容器。

以上组件采用了 flex 布局,使用前请确定目标浏览器是否兼容。此外,<el-container> 的子元素只能是后四者,后四者的父元素也只能是 <el-container>

ElContainer组件

模板:

<template>
//is-vertical 判断是是否为垂直布局
//section 利于`SEO`的语义化`tag`标签
  <section class="el-container" :class="{ 'is-vertical': isVertical }">
    <slot></slot> //通过内容分发
  </section>
</template>

<script>
  export default {
    name: 'ElContainer',

    componentName: 'ElContainer', //自定义属性

    props: {
      direction: String	//方向  horizontal =》 水平  vertical =》垂直
    },

    computed: {
      isVertical() {
        if (this.direction === 'vertical') {
          return true;
        } else if (this.direction === 'horizontal') {
          return false;
        }
    //this.$slots.default是个数组,里面的每个元素都是一个VNode,VNode是虚拟dom中的虚拟节点,当组件被编译时,每个<...>就会生成一个虚拟的节点,
    //通过 vnode.componentOptions.tag 来判断这个 vnode 是不是 <el-header> 或者是 <el-footer>。
        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>

首先判断this.$slots&& this.$slots.defaultthis.$slots.default为默认插槽】,如果不存在直接返回false,不存在的情况就是子元素为空。this.$slots是组件的实例属性,组件是可复用的Vue的实例,和 new Vue()一样是实例,因此有以下属性

vue 实例 传送门

CSS部分:

@include b(container) {
  display: flex;
  flex-direction: row;
  flex: 1;
  flex-basis: auto;
  box-sizing: border-box;
  min-width: 0;
}

@include when(vertical) { //当是垂直方向排列,则设置为 column
  flex-direction: column;
}

display:flex 创建了一个 flex 容器,flex-direction:row 指定了内部元素是在水平方向排列。这里为什么还有 flex:1 呢,因为 <el-container> 容器是支持嵌套的,并且我们知道 flex:1 相当于 flex-grow:1;flex-shrink:1;flex-basis:0,也就是当 <el-container> 被嵌套的时候,它会占满剩余空间。flex-basis:auto 表示分配空间之前会先跟父容器预约自身内容大小的空间,然后剩下的才会归入到剩余空间。

ElHeader组件

模板:

<template> 
//header 便于 SEO
  <header class="el-header" :style="{ height }">
      //  height  这里传入的 height 是需要带单位的
    <slot></slot>
  </header>
</template>

<script>
  export default {
    name: 'ElHeader',

    componentName: 'ElHeader',

    props: { //通过属性来控制 header 高度
      height: {
        type: String,
        default: '60px'
      }
    }
  };
</script>

CSS部分

@include b(header) {
  padding: $--header-padding; //packages/theme-chalk/src/common/var.scss scss变量
  box-sizing: border-box;
  flex-shrink: 0; //表示即使空间不够,也不会缩小 <el-header> 所占空间。
}

ElMain组件

模板:

<template>
// main SEO
  <main class="el-main"> 
    <slot></slot>
  </main>
</template>

<script>
  export default {
    name: 'ElMain',
    componentName: 'ElMain'
  };
</script>

CSS部分:

@include b(main) {
  // IE11 supports the <main> element partially https://caniuse.com/#search=main
  // IE 支持11 以上
  display: block;
  flex: 1;
  flex-basis: auto;
  overflow: auto;
  box-sizing: border-box;
  padding: $--main-padding;
}

通常 <main> 中包裹的内容完全由它的子元素来决定,所以并不会设置高和宽,只是通过 flex:1 来分配 <el-container> 容器的剩余空间。

ElFooter组件

模板:

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

<script>
  export default {
    name: 'ElFooter',

    componentName: 'ElFooter',

    props: { //属性传值 控制高度
      height: {
        type: String,
        default: '60px'
      }
    }
  };
</script>

CSS部分:

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

flex-shrink: 0; 表示即使空间不够,也不会缩小 所占空间。

ElAside组件

模板:

<template>
//aside SEO
  <aside class="el-aside" :style="{ width }">
    <slot></slot>
  </aside>
</template>

<script>
  export default {
    name: 'ElAside',

    componentName: 'ElAside',

    props: { //属性传值
      width: {
        type: String,
        default: '300px'
      }
    }
  };
</script>

CSS部分:

@include b(aside) {
  overflow: auto; // 如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。
  box-sizing: border-box;
  flex-shrink: 0; //表示即使空间不够,也不会缩小 <el-aside> 所占空间。
}

总结

element-uiContainer 布局容器组件的实现还是很简单的:创建了一些语义化的标签,利用插槽做内容分发,通过 flex实现布局效果。

其中headerfooterasideflex-shrink都是0,也就是不会压缩,而main中的代码flex:1表示了只有main会被压缩或者扩张,flex:1flex:grow:1,flex:shrink:1,flex-basis:auto的简写,又因为flex:grow默认值为0,所以只有main会被压缩或扩张,headerfooteraside 都不变

整个布局其实就是对原生的封装,主要就是container的处理,如果浏览器不支持flex,则上述布局无效

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值