前端高手养成计划

  前端高手养成前端全栈开发大型项目 - 彻底理解CSS Flexbox布局

  一、Flexbox布局的概念

  下栽ke呈:lexuecode.com/6258.html

  

  Flexbox布局也叫Flex布局,弹性盒子布局。它的目标是提供一个更有效地布局、对齐方式,并且能够使父元素在子元素的大小未知或动态变化情况下仍然能够分配好子元素之间的间隙。主要思想是使父元素能够调整子元素的宽度、高度、排列方式,从而更好的适应可用的布局空间。设定为flex布局的元素能够放大子元素使之尽可能填充可用空间,也可以收缩子元素使之不溢出。

  Flex布局更适合小规模的布局,可以简便、完整、响应式的实现各种页面布局。但是,设为Flex布局以后,其子元素的float、clear和vertical-align属性将失效。Flex弹性盒模型的优势在于只需声明布局应该具有的为,不需要给出具体的实现式,浏览器负责完成实际布局,当布局涉及到不定宽度,分布对的场景时,就要优先考虑弹性盒布局。

  Flex布局是一个完整的模块,它包括了一套完整的属性。其中采用 Flex 布局的元素,称为 Flex 容器,简称"容器"。它的所有子元素就是容器成员,称为 Flex 项目,简称"项目"。

  容器默认存在两个轴:水平轴(main axis)和垂直轴(cross axis),项目默认沿主轴排列(水平轴):

  这里面涉及到了几个概念,下面来看一下:

  main axis: Flex 父元素的主轴是指子元素布局的主要方向轴,它由属性flex-direction来确定主轴是水平还是垂直的,默认为水平轴。

  main-start & main-end: 分别表示主轴的开始和结束,子元素在父元素中会沿着主轴从main-start到main-end排布。

  main size: 单个项目占据主轴的长度大小。

  cross axis: 交叉轴,与主轴垂直。

  cross-start & cross-end: 分别表示交叉轴的开始和结束。子元素在交叉轴的排布从cross-start开始到cross-end。

  cross size: 子元素在交叉轴方向上的大小。

  二、父元素属性

  想要使用flex布局,首先需要给父元素指定为flex布局,这样容器内的元素才能实现flex布局:

  <div class="container"></div>

  .container {

  display: flex | inline-flex;

  }

  复制代码

  这里有两种方式可以设置flex布局,使用display: flex;会生成一个块状的flex容器盒子,使用display: inline-flex;会生成一个行内的flex容器盒子。如果我们使用块状元素,比如div标签,就可以使用flex,如果使用行内元素,就可以使用inline-flex。多数情况下,我们会使用display: flex;。

  父元素(容器)可以设置以下六个属性:

  flex-direction

  flex-wrap

  flex-flow

  justify-content

  align-items

  align-content

  1. flex-direction

  flex-direction:主轴方向,它决定了容器内元素排列方向,它有四个属性值:

  .container {

  flex-direction: row | row-reverse | column | column-reverse;

  }

  复制代码

  (1)flex-direction: row:默认值,沿水平主轴从左到右排列,起点在左沿

  (2)flex-direction: row-reverse:沿水平主轴从右到左排列,起点在右沿

  (3)flex-direction: column:沿垂直主轴从上到下排列,起点在上沿

  (4)flex-direction: column-reverse:沿垂直主轴从下到上排列,起点在下沿

  2. flex-wrap

  flex-wrap:容器内元素是否可以换行,它有三个属性值:

  .container {

  flex-wrap: nowrap | wrap | wrap-reverse;

  }

  复制代码

  (1)flex-wrap: nowrap:默认值,不换行。当主轴的长度是固定并且空间不足时,项目尺寸会随之进行调整,而不会换行。

  (2)flex-wrap: wrap:换行,第一行在上面

  (3)flex-wrap: wrap-reverse:换行,第一行在下面

  3. flex-flow

  flex-flow 是 flex-direction 属性和flex-wrap属性的简写,默认为:flex-flow:row nowrap,用处不大,最好还是分开来写。该属性的书写格式如下:

  .container {

  flex-flow: <flex-direction> <flex-wrap>;

  }

  复制代码

  4. justify-content

  justify-content:元素在主轴的对齐方式,它有五个属性值:

  .container {

  justify-content: flex-start | flex-end | center | space-between | space-around;

  }

  复制代码

  这里以水平方向为主轴进行举例,即flex-direction: row。

  (1)justify-content : flex-start:默认值,元素在主轴上左对齐(上对齐)

  (2)justify-content : flex-end:元素在主轴上右对齐(下对齐)

  (3)justify-content : center :元素在主轴上居中对齐

  (4)justify-content : space-between:元素在主轴上两端对齐,元素之间间隔相等

  (5)justify-content : space-around :每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。

  5. align-items

  align-item:元素在交叉轴上的对齐方式,它有五个属性值:

  .container {

  align-items: flex-start | flex-end | center | baseline | stretch;

  }

  复制代码

  这里以水平方向为主轴进行举例,即flex-direction: row。

  (1)align-item:flex-start:交叉轴的起点对齐(上面或左边)。设置容器高度为 100px,项目高度分别为 20px、40px、60px、80px、100px,效果如图所示:

  (2)align-item:flex-end:交叉轴的终点对齐(下面或右边)。设置容器高度为 100px,项目高度分别为 20px、40px、60px、80px、100px,效果如图所示:

  (3)align-item:center:交叉轴的中点对齐。设置容器高度为 100px,项目高度分别为 20px、40px、60px、80px、100px,效果如图所示:

  (4)align-item:stretch:默认值、如果元素未设置高度或设为auto,将占满整个容器的高度。假设容器高度设置为 100px,而项目没有设置高度,则项目的高度也为 100px:

  (5)align-item:baseline:以元素的第一行文字的基线对齐

  6. align-content

  align-content:多根轴线对齐方式。如果元素只有一根轴线,该属性不起作用。它有六个属性值:

  .container {

  align-content: flex-start | flex-end | center | space-between | space-around | stretch;

  }

  复制代码

  那这个轴线数怎么确定呢?实际上这主要是由flex-wrap属性决定的,当flex-wrap 设置为 nowrap 时,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线。当 flex-wrap 设置为 wrap 时,容器可能会出现多条轴线,这时就需要去设置多条轴线之间的对齐方式。

  这里以水平方向为主轴时举例,即:flex-direction: row; flex-wrap: wrap;

  (1)align-content: stretch:默认值,轴线占满整个交叉轴。这里我们先设置每个项目都是固定宽度,效果如下:

  下面就去掉每个项目的高度,它会占满整个交叉轴,效果如下:

  (2)align-content: flex-start:从交叉轴开始位置填充

  (3)align-content: flex-end:从交叉轴结尾位置填充

  (4)align-content: center:与交叉轴中点对齐

  (5)align-content: space-between:与交叉轴两端对齐,轴线之前的间隔平均分布

  (6)align-content: space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍

  三、子元素属性

  子元素有以下六个属性:

  order

  flex-grow

  flex-shrink

  flex-basis

  flex

  align-self

  1. order

  order属性用来定义项目的排列顺序。数值越小,排列越靠前,默认为0。使用形式如下:

  .item {

  order: <integer>;

  }

  复制代码

  2. flex-basis

  flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间,浏览器会根据这个属性来计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。使用形式如下:

  .item {

  flex-basis: <length> | auto;

  }

  复制代码

  当主轴设置为水平时,当设置了 flex-basis,设置的项目宽度值会失效,flex-basis 需要跟 flex-grow 和 flex-shrink 配合使用才能生效。有两种特殊的值:

  当 flex-basis 值为 0 % 时,项目尺寸会被认为是0,因此无论项目尺寸设置多少都用;

  当 flex-basis 值为 auto 时,则跟根据尺寸的设定值来设置大小。

  3. flex-grow

  flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间时也不放大。

  当容器中所有的项目都设置了flex-basis属性时,如果仍有是剩余的空间,设置的 flex-grow 属性才能生效。

  如果所有项目的flex-grow属性都设置为1,那么它们会均分剩余的空间,如下图所示:

  如果其中一个项目的flex-grow属性设置为2,其他均为1,那么它占据的剩余空间就是其他项目的两倍,如下图所示:

  3. flex-shrink

  flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。不能设置负值,使用形式如下:

  .item {

  flex-shrink: <number>;

  }

  复制代码

  如果所有项目的 flex-shrink 属性都为 1,当空间不足时,都将等比例缩小,如下图所示:

  如果一个项目的 flex-shrink 属性为 0,其他项目都为 1,则空间不足时,前者不缩小,如下图所示:

  5. flex

  flex属性是flex-grow, flex-shrink 和 flex-basis的简写,后两个属性可选。默认值为:flex:0 1 auto。使用形式如下:

  .item{

  flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]

  }

  复制代码

  对于flex的取值有几种常用的特殊情况:

  (1)默认值:flex:0 1 auto,即在有剩余空间时,只放大不缩小

  .item {

  flex:0 1 auto;

  }

  .item {

  flex-grow: 0;

  flex-shrink: 1;

  flex-basis: auto;

  }

  复制代码

  (2)flex: none,即有剩余空间时,不放大也不缩小,最终尺寸通常表现为最大内容宽度。

  .item {

  flex:0 0 auto;

  }

  .item {

  flex-grow: 0;

  flex-shrink: 0;

  flex-basis: auto;

  }

  复制代码

  (3)flex: 0,即当有剩余空间时,项目宽度为其内容的宽度,最终尺寸表现为最小内容宽度。

  .item {

  flex:0 1 0%;

  }

  .item {

  flex-grow: 0;

  flex-shrink: 1;

  flex-basis: 0%;

  }

  复制代码

  (4)flex: auto,即元素尺寸可以弹性增大,也可以弹性变小,具有十足的弹性,但在尺寸不足时会优先最大化内容尺寸。

  .item {

  flex:1 1 auto;

  }

  .item {

  flex-grow: 1;

  flex-shrink: 1;

  flex-basis: auto;

  }

  复制代码

  (5)flex: 1,即元素尺寸可以弹性增大,也可以弹性变小,具有十足的弹性,但是在尺寸不足时会优先最小化内容尺寸,

  .item {

  flex:1 1 0%;

  }

  .item {

  flex-grow: 1;

  flex-shrink: 1;

  flex-basis: 0%;

  }

  复制代码

  6. align-self

  align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

  .item {

  align-self: auto | flex-start | flex-end | center | baseline | stretch;

  }

  复制代码

  这个属性和align-items属性的效果是一样的,只不过这个属性只对单个项目生效,而align-items是对容器中所有的项目生效。

  设置容器的align-items属性为flex-start,容器中第三个项目的align-self属性为flex-end,效果如下:

  Flex布局的基本使用主要就是这些了,flex布局可能是目前最好用的布局方式之一

  前端高手养成计划-前端加载更多图书分页实现

  在移动端开发中经常会运用到上拉加载更多来实现分页的操作,不仅可以增加用户良好的体验,也可以让自己的项目看起来更加的丝滑~

  那么具体要怎么做呢?

  准备一个容器来设置滚动事件

  如果要设置固定高度容器则设置ref

  <template>

  <div class="container" ref="scroll">

  <!-- 滚动内容代码 -->

  </div>

  </template>

  复制代码

  写一个滚动事件方法

  onScroll(){

  //可滚动容器的高度

  let innerHeight = this.$el.clientHeight;

  //屏幕尺寸高度

  let outerHeight = document.documentElement.clientHeight;

  //可滚动容器超出当前窗口显示范围的高度

  let scrollTop = document.documentElement.scrollTop;

  //避免切换时读取到异常高度

  if(scrollTop==0){

  innerHeight=10000

  }

  //scrollTop在页面为滚动时为0,开始滚动后,慢慢增加,滚动到页面底部时,出现innerHeight < (outerHeight + scrollTop)的情况,严格来讲,是接近底部。

  console.log(innerHeight + " " + outerHeight + " " + scrollTop);

  if(this.isLoad){

  console.log(1)

  if(innerHeight <= outerHeight + scrollTop){

  //此处添加自定义操作

  }

  }

  },

  复制代码

  如果设置了ref则将 $el换成$refs.scroll即可

  设置滚动事件开关

  data () {

  return {

  isLoad:true,

  msg:"正在加载"

  };

  },

  复制代码

  在生命周期函数 添加滚动事件和移除滚动事件

  mounted(){

  //开启滚动事件

  window.addEventListener("scroll", this.onScroll);

  },

  destroyed(){

  //关闭滚动事件

  window.removeEventListener("scroll",( this.onScroll));

  }

  复制代码

  值得一提的是如果该页面用了keepalive则会没有destroyed生命周期则用新增的两个生命周期来添加和移除滚动事件

  activated(){

  //开启滚动事件

  window.addEventListener("scroll", this.onScroll);

  },

  deactivated(){

  //关闭滚动事件

  window.removeEventListener("scroll",( this.onScroll));

  },

  1.简介

  Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。具有以下特点:从浏览器中创建 XMLHttpRequests,从 node.js 创建 http 请求,支持 Promise API,拦截请求和响应,转换请求数据和响应数据,取消请求,自动转换 JSON 数据,客户端支持防御 XSRF。

  它封装了一些简易API方便快速使用,如axios.get、axios.post,也支持原始用法 axios({}),这点和JQuery还挺像的。

  2.基本用法

  (1). 形如axios.get().then().catch();

  在then中通过 ret.data获取返回值,特别注意这里的返回值会自动转换为json,因为responseType: 'json'(默认的), 错误会进入catch,这里和fetch不一样,像400、415、500等网络错误都可以进入到catch,不需要再单独处理。

  代码分享:

  复制代码

  axios.get('https://localhost:44387/api/First/GetInfor3?userName=ypf&pwd=123456')

  .then(function(response) {

  console.log(response);

  })

  .catch(function(error) {

  console.log(error);

  console.log(error.response.status + '---' + error.response.statusText);

  });

  复制代码

  (2).Get请求

  A.用axios.get写法,可以直接在参数上拼接,也可以通过params属性写数据,当然也可附加一下额外的参数,如:headers、timeout等等。

  B.用axios原始写法, 利用params传递参数,实际上和直接拼接是完全一样的,当然也可附加一下额外的参数,如:headers、timeout等等。

  代码分享:

  复制代码

  1 //用法1

  2 // axios.get('https://localhost:44387/api/First/GetInfor1?userName=123&pwd=hhh').then(function(ret) {

  3 // console.log(ret.data)

  4 // });

  5 //用法2

  6 axios.get('https://localhost:44387/api/First/GetInfor1', {

  7 params: {

  8 userName: 'ypf',

  9 pwd: '1234'

  10 },

  11 //下面是一些额外参数

  12 headers: {

  13 'token': 'xxsdfsdfxx'

  14 },

  15 timeout: 3000,

  16

  17 }).then(function(ret) {

  18 console.log(ret.data)

  19 })

  20

  21 //get的原始写法

  22 axios({

  23 method: 'get',

  24 url: 'https://localhost:44387/api/First/GetInfor1',

  25 params: {

  26 userName: 'lisi',

  27 pwd: 123

  28 },

  29 headers: {

  30 'token': 'xxsdfsdfxx'

  31 },

  32 }).then(function(ret) {

  33 console.log(ret.data)

  34 });

  复制代码

  (3).Post请求

  PS:其中Post请求有两种,分别是: "application/x-www-form-urlencoded"表单提交的方式 和 "application/json" Json格式提交的方式。

  (1). Post的表单提交的格式为:"userName=admin&pwd=123456"。

  (2). Post的Json的提交格式为:将实体(类)转换成json字符串。

  A.用axios.Post写法(附带传递额外参数)

  a.表单提交:需要借助URLSearchParams参数进行传递。

  b.JSON提交:直接拼接,即为json提交 {userName: 'lisi', pwd: 123}

  代码分享:

  复制代码

  //表单提交

  var params = new URLSearchParams();

  params.append('userName', 'zhangsan');

  params.append('pwd', '111');

  axios.post('https://localhost:44387/api/First/Login3', params).then(function(ret) {

  console.log(ret.data)

  })

  //JSON提交

  //默认是json格式传参的

  axios.post('https://localhost:44387/api/First/Login2', {

  userName: 'lisi',

  pwd: 123

  }).then(function(ret) {

  console.log(ret.data)

  })

  //axios.post 传递额外参数 (json格式的提交)

  axios.post('https://localhost:44387/api/First/Login2', {

  userName: 'lisi',

  pwd: 123

  }, {

  //下面是一些额外参数

  headers: {

  'token': 'xxsdfsdfxx'

  },

  timeout: 3000,

  }).then(function(ret) {

  console.log(ret.data)

  });

  复制代码

  B.用axios原始写法 (附带传递额外参数)

  a.表单提交: 借助URLSearchParams提交; 或者在data里写,但是用transformRequest转换一下也能达到效果。

  b.JSON提交: 直接在data属性里写就是JSON提交。

  代码分享:

  复制代码

  1 //1.原始写法 post(JSON提交)

  2 axios({

  3 method: 'post',

  4 url: 'https://localhost:44387/api/First/Login2',

  5 data: {

  6 userName: 'lisi',

  7 pwd: 123

  8 },

  9 headers: {

  10 'token': 'xxsdfsdfxx'

  11 },

  12 }).then(function(ret) {

  13 console.log(ret.data)

  14 });

  15

  16 //2. 原始写法 post(表单提交)用法1

  17 var params = new URLSearchParams();

  18 params.append('userName', 'zhangsan');

  19 params.append('pwd', '111');

  20 axios({

  21 method: 'post',

  22 url: 'https://localhost:44387/api/First/Login3',

  23 data:params,

  24 headers: {

  25 'token': 'xxsdfsdfxx'

  26 },

  27 }).then(function(ret) {

  28 console.log(ret.data)

  29 });

  30

  31 //3. 原始写法 post(表单提交) 用法2

  32 axios({

  33 method: 'post',

  34 url: 'https://localhost:44387/api/First/Login3',

  35 //允许在向服务器发送前,修改请求数据

  36 transformRequest: [function(data) {

  37 let ret = ''

  38 for (let it in data) {

  39 ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'

  40 }

  41 return ret;

  42 }],

  43 data: {

  44 userName: 'lisi',

  45 pwd: 123

  46 },

  47 headers: {

  48 'token': 'xxsdfsdfxx',

  49 'Content-Type': 'application/x-www-form-urlencoded'

  50 },

  51 }).then(function(ret) {

  52 console.log(ret.data)

  53 });

  复制代码

  4. 其它详细配置

  这里只分析几个常用的,其它的详见上面的Api文档。

  (1).url: 用于请求URL

  (2).method: 请求方式,默认为get请求

  (3).params: 用于向URL上拼接地址,和直接在地址上拼接效果一样,用于get请求

  (4).data:作为请求主体被发送的数据,多用于POST请求

  (5).headers:请求表头

  (6).timeout:请求超时时间,单位毫秒

  (7).withCredentials:表示跨域请求时是否需要使用凭证,默认是false

  (8).responseType:表示服务器响应的数据类型,可以是 'arraybuffer', 'blob', 'document', 'json'(默认), 'text', 'stream'

  (9).baseURL: 拼接在url的前面

  (10).transformRequest: 允许在向服务器发送前,修改请求数据

  (11).transformResponse: 在传递给 then/catch 前,允许修改响应数据

  5.全局默认设置

  全局配置baseUrl、全局配置Header、全局配置过期时间等等。

  代码分享:

  复制代码

  1 // 配置请求的基准URL地址

  2 axios.defaults.baseURL = 'https://localhost:44387';

  3 // 配置请求头信息

  4 axios.defaults.headers['mytoken'] = 'hello';

  5 axios.get('/api/First/GetInfor1', {

  6 params: {

  7 userName: 'ypf',

  8 pwd: '1234'

  9 },

  10 }).then(function(ret) {

  11 console.log(ret.data)

  12 })

  复制代码

  6. 拦截器

  (1).可以在请求发送前拦截,比如添加header。

  (2).在响应后进行拦截,比如返回: ret.data(), 后面就可以直接用了。

  复制代码

  1 //请求前拦截

  2 axios.interceptors.request.use(function(config) {

  3 // console.log(config.url)

  4 config.headers.mytoken = 'nihao'; //设置一下header

  5 return config;

  6 }, function(err) {

  7 console.log(err)

  8 });

  9 //响应后拦截

  10 axios.interceptors.response.use(function(res) {

  11 var data = res.data;

  12 return data;

  13 }, function(err) {

  14 console.log(err)

  15 });

  16 //这样这里可以直接使用data了

  17 axios.get('https://localhost:44387/api/First/GetInfor1', {

  18 params: {

  19 userName: 'ypf',

  20 pwd: '1234'

  21 },

  22 }).then(function(data) {

  23 console.log(data)

  24 });

  复制代码

  7. 其它用法补充: 取消请求和并发请求

  详见Api文档。  axios.all(iterable) axios.all(iterable)

  二. async异步编程

  1.async作为一个关键字放到函数前面,任何一个 async 函数都会隐式返回一个 promise。

  2.await 关键字只能在使用 async 定义的函数中使用,后面可以直接跟一个 Promise实例对象,await函数不能单独使用。

  3.async/await 让异步代码看起来、表现起来更像同步代码。

  复制代码

  1 var vm = new Vue({

  2 el: '#myApp2',

  3 methods: {

  4 handle1: async function() {

  5 var ret1 = await axios.get('https://localhost:44387/api/Third/GetInfor4?userName=ypf&pwd=123456');

  6 var userName = ret1.data.userName;

  7 var pwd = ret1.data.pwd;

  8 //可以直接在后面捕捉错误

  9 var ret2 = await axios.post('https://localhost:44387/api/First/Login2', {

  10 userName: userName+'001',

  11 pwd: pwd+'001'

  12 }).catch(error=>{

  13 console.log(error);

  14

  15 });

  16 // console.log(ret2.data);

  17 return ret2.data;

  18 }

  19 }

  20 });

  复制代码

  举报/反馈