Vue造轮子——Grid布局详解

2,922 阅读4分钟

前言

    我最近在学习vue源码的同时,一直在不停的造Vue轮子,目前了Button、Input两个最基础的轮子,也已经做了一些小的测试,在这个过程中,我发现,其实单纯比用组件库,完成一个简单的项目更加考验vue的基础知识呢~。

    在接下来的一段时间,我会分享自己写组件过程中的一些记录和心得,以及涉及到的一些vue中的问题,如果可以的话,后期会完善遇到的问题中对应的源码部分内容,希望可以和大家交流学习呐` biubiu❤


>>>那么下面开始正文啦<<<

基础功能的实现

首先创建行的容器,用来装每一行的多个列
template内容

<div class="row">
   <slot></slot>
  </div>


css部分(用flex布局)

 	.row{
   	display: flex;
   }

然后就是每一列,以及他们的关系的体现啦

<template>
	<!-- span可以用来表示一行的几个g-col的分布比例  不对称的时候需要写-->
	<!-- 添加属性 设置偏移量 -->
	<div class="col" :class="[`col-${span}`,offset&&`offset-${offset}`]">
		<slot></slot>
	</div>
</template>

<script>
	export default{
		name:"GuluCol",
		props:{
			span:[Number,String],
			offset:[Number,String]
		}
	}
</script>

<style lang="scss" scoped>
	$bg-color: #FFFFCC;
	$border-color:#99CCCC;	
	.col{
		height: 100px;
		background-color:$bg-color;
		width:50%;
		border:1px solid $border-color;
		$class-prefix:col-;
		@for $n from 1 through 24{
			&.#{$class-prefix}#{$n}{
				width: ($n/24)*100%;
			}
		};
		$class-prefix:offset-;
		@for $n from 1 through 24{
			&.#{$class-prefix}#{$n}{
				margin-left: ($n/24)*100%;
			}
		}
	}
</style>


嘿嘿,在这里我们基本就可以实现一个简单的轮子了(如下图所示),可以自己设置每一行中的列数,以及每一列所占的比例~

Vue钩子函数实现网格之间的空隙

    其实实现这个功能,最考验的还是css的功底了~然后就是会涉及到父子组件之间传值的问题

首先,如果想要在其中加空隙的话,大家首先想到的自然就是 margin来一波~ 但是其实存在一些潜在的风险

  • 和我们之前设置的margin用来表示offset的情况冲突了,那么就会存在margin重叠的情况,导致不能达到预期的效果
  • 其次就是用padding来表示间隙的大小啦(组件默认是:border-box)所以那就是可以的哦~


    其实,这还真的可以(hhh),不过存在一点小问题,那就是最边上的元素 会和内容区 有padding的宽度,所以下面就是思考怎么解决这个常见的布局问题了~


    从子元素上下手其实不容易,那么我们就从父元素下手,也就是row容器:

 	.row{
		display: flex;
		margin:0 -10px;
	}

    并且这里就涉及到一个问题,我们从用户那里获得gutter的值,但是怎么将值传给col呢,也就是说,那就涉及到父子组件之间的传值了
    那怎么传值呢,选择在父组件的mounted函数阶段获取子组件,并且设置其gutter值为当前的gutter值

mounted(){
this.$children.gutter.forEach((vm)=>{
vm.gutter=this.gutter)
}

在子组件中的data中设置gutter变量就好,毕竟data中没有gutter值的话,父组件怎么也拿不到的嘿嘿~
    如下:

data(){
 return {
	gutter:0
	}
}//至于为什么要return 应该大家都是知道的吧,每个组件都要保持其独立性


    这样就完成了中间有间隙的设置如下:

涉及到的Vue知识点


     一、createdmounted的区别

  • created阶段,这个时候实例对象已经被创建,组件被创建好,但是还没挂载到页面上
  • mounted阶段,页面已经渲染完成,el被创建的实例对象给替代了(经历了编译-渲染-挂载 el.append()

二、$children$parent的使用,以及父子组件之间的生命周期执行顺序

  • 其实这个问题是十分好理解的,不需要去特意记住,只要明确知道一个点父组件存在的时候,子组件才可以挂载,子组件挂载完成之后,父组件才算挂载完成
  • 结论就是:父created——>子created——>子mounted——>父mounted
  • 更新过程和销毁过程都是一样的原理(其实真的非常符合人之常情,一点不抽象hhh)

总结


    以上就是这个简单轮子的大概情况啦~具体代码可以参考github的vue-ui仓库啦~(还有一些简单的测试用例哒)
    这个只是初步完成了功能,代码还有很多问题,会进行修改哒~如果有什么好的想法,也可以一起交流哦~
    大佬忽略···
    hhhh最后说一句,有21届一起毕业的小伙伴可以一起哈!

❤组件制作参考了方方的课程~大家多多关注哒