xixijiang的主页


  • Home

  • Archives

  • Tags

es6相关

Posted on 2017-07-20

箭头函数(胖箭头函数)

this

  • 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。
  • 不可以使用yield命令,因此箭头函数不能用作Generator函数。

this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。

另外,由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。

nodejs之koa2框架

Posted on 2017-07-20

koa2会自己吧服务器框架搭建好,如果自己用nodejs,需要引入一些http的包,然后写端口,写一堆乱七八糟的,用koa2的话,都只有一个入口文件,就是路由文件,里面包括几大块:

  • 静态文件目录的生命,告诉服务器那个目录是用来放静态文件的,就是一些html,css,js,image什么。

  • 还有一块就是路由地址的指向,路由文件给每个子路由文件都分配了一个地址,比如smallCourse,给他分配的可能就是/smallCourse/api。

  • 还有一部分是服务器的简单配置,端口号啊等等。

浏览器拿到一个URL地址后,先通过localhost:3000后面的前几个名字去总的路由文件里匹配,找到一样的就去下面的文件下面再匹配,找到一样的地址的函数,就调用。

express

express的入门非常简单,通过创建express的Application就构建了一个expressweb实例。下面我们看看例子来感受一下:

var express = require('express');
var app = express();

app.get('/', function (req, res) {
      res.send('Hello World!');
});

var server = app.listen(3000, function () {
      var host = server.address().address;
      var port = server.address().port;

      console.log('Example app listening at http://%s:%s', host, port);
});

express本身封装了路由模块,因此,可以利用express直接处理各种http路由请求。

在express用四个主要模块:

  • Application:web服务器模块,抽象了web服务器的主要接口,如监听、事件、加载中间件、get\post请求等
  • Request:请求
  • response:响应
  • Router:路由

express用Application、Request、Response、Router四个主要模块,模拟了一个完整的web服务器功能,对了,express还在相当长的一段时期中受到了Connect的影响。在使用express的过程中,你会发现express是一个极简的、灵活的 web 应用开发框架,它提供的这一系列强大的特性,可以帮助你快速创建各种 web 和移动设备应用。

koa

koa 是由 express原班人马打造的(TJ),致力于构建更小、更富有表现力、更健壮的 web 框架。使用 koa 编写 web 应用,通过组合不同的 generator,可以免除重复繁琐的回调函数嵌套,并极大地提升错误处理的效率。koa 不在内核方法中绑定任何中间件,它仅仅提供了一个轻量优雅的函数库,使得编写 koa 应用变得得心应手。
Koa 包含了像 content-negotiation(内容协商)、cache freshness(缓存刷新)、proxy support(代理支持)和 redirection(重定向)等常用任务方法。 与提供庞大的函数支持不同,Koa只包含很小的一部分,因为Koa并不绑定任何中间件。

koa中也包含4个主要模块,Application、Request、Response、Context。此时,router已经被排除在内核之外了。其实,koa只是一个“中间架”,几乎所有的功能都需要由第三方中间件来协同完成。例如koa的router模块,就有20多个,优胜劣汰,自由选择……虽然有不规范之嫌,但是,koa是规范的这就足够了。使用koa,可以最大限度的发挥自己的想象力,利用koa,构建各种个性化的web与移动应用。下面我们看看例子来感受一下:

var koa = require('koa');
var app = koa();

app.use(function *(){
      this.body = 'Hello World';
});

app.listen(3000);

没错,就是这么简单,使用了Generator函数,这也是koa和express最大的不同,express是回调函数,koa是用Generator来作为响应器的。

另外,那个替代了router的context是怎样的呢?下面我们看看例子来感受一下:

app.use(function *(){
      this; // is the Context
      this.request; // is a koa Request
      this.response; // is a koa Response
});

另外,koa中还有co这个工具。co是一个“皮”,通过co来包装Generator和yeild,下面我们看看例子来感受一下:

koa2

目前,koa2结合了async/await已经成为了最好的web开发框架。上一节,已经讲了koa的主要模块和实现原理,此处,我只是简单说说koa2和koa不同之处,下面我们看看例子来感受一下:

const Koa = require('koa');
const app = new Koa();

app.use(ctx => {
      ctx.body = 'Hello World';
});

app.listen(3000);

函数式编程,async/await功能,程序简单,好用,真可谓是居家旅行的不二之选呀。通过查看代码,koa2去除了co中间件,进一步的精简了内核,这一点也正好符合当下性冷淡风格的设计潮流……不禁想赞叹一句,TJ不愧是设计师出身呀……

作者:白昔月
链接:http://www.jianshu.com/p/3806417a1991
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

vue之vuex

Posted on 2017-07-20

Vuex是一种状态管理模式,采用集中式存储管理应用的所有组件的状态。

Vuex的核心——store

store的特点

store包含应用中大部分的状态(state)。

Vuex和单纯的全局对象有以下两点不同:

1. Vuex的状态存储是响应式的。当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么响应的组件也会更新。

2. 不能直接改变store中的状态。唯一途径就是显示提交mutations(commit mutations)。这样设计的目的是:我们能跟踪每一个状态的变化。

store的创建

store创建时包含:

state, getters, mutations, actions, modules

这里给一个例子,在项目里新建store.js,写如下代码

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

// root state object.
// each Vuex instance is just a single state tree.
const state = {
  count: 0
}

// mutations are operations that actually mutates the state.
// each mutation handler gets the entire state tree as the
// first argument, followed by additional payload arguments.
// mutations must be synchronous and can be recorded by plugins
// for debugging purposes.
const mutations = {
  increment (state) {
    state.count++
  },
  decrement (state) {
    state.count--
  }
}

// actions are functions that causes side effects and can involve
// asynchronous operations.
const actions = {
  increment: ({ commit }) => commit('increment'),
  decrement: ({ commit }) => commit('decrement'),
  incrementIfOdd ({ commit, state }) {
    if ((state.count + 1) % 2 === 0) {
      commit('increment')
    }
  },
  incrementAsync ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('increment')
        resolve()
      }, 1000)
    })
  }
}

// getters are functions
const getters = {
  evenOrOdd: state => state.count % 2 === 0 ? 'even' : 'odd'
}

// A Vuex instance is created by combining the state, mutations, actions,
// and getters.
export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations
})

getters创建

getters会暴露为store.getters对象。

getters传入的参数:

第一个是state对象,第二个参数(可选),可以是其他getters,比如

getters: {
      // ...
     doneTodosCount: (state, getters) => {
        return getters.doneTodos.length
      }
}

store里状态的使用

有了store,那么怎么在组件中使用呢?

下面给个例子,新建count.vue文件,

<template>
  <div id="app">
    Clicked: {{ $store.state.count }} times, count is {{ evenOrOdd }}.
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementIfOdd">Increment if odd</button>
    <button @click="incrementAsync">Increment async</button>
  </div>
</template>

<script>
import { mapGetters, mapActions } from 'vuex'

export default {
  // computed: mapGetters([
  //   'evenOrOdd'
  // ]),
  computed: {
    // 使用getters的方式
    evenOrOdd () {
      return this.$store.getters.evenOrOdd;
    }
  },
  methods: mapActions([
    'increment',
    'decrement',
    'incrementIfOdd',
    'incrementAsync'
  ])
}
</script>

下面开始详细介绍

先说怎么获取state

一个组件从store中读取状态的最简单的办法是在计算属性中返回某个状态:

比如上面代码中,可以在computed里加上:

count() {
    return this.$store.state.count;
}

当一个组件需要获取多个状态时,可以使用mapState辅助函数帮助我们生成计算属性。

可以把刚才写的count(){}函数替换为:

mapState({
    count: state => state.count,
    countAlias: 'count',
    countPlusLocalState (state) {
          return state.count + this.localCount
    }
})

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([
      // 映射 this.count 为 store.state.count
      'count'
])

再说怎么获getters

也是在computed属性里写,如同count.vue里所写,可以用普通函数的形式,也可以用mapGetters.

mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性,可以使用对象展开运算符将getters混入computed对象中:

computed: {
      // 使用对象展开运算符将 getters 混入 computed 对象中
    ...mapGetters([
          'doneTodosCount',
          'anotherGetter',
          // ...
    ])
  }

mutations和actions区别

mutations只支持同步函数。

每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用 —— 实质上任何在回调函数中进行的的状态的改变都是不可追踪的。

Action 类似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

action里面的方法可以通过store.dispatch(‘increment’)触发。

css浮动float属性

Posted on 2017-07-19

浮动的本意

让文字像流水一样环绕浮动元素。

怎么才能实现该效果呢

用包裹性和高度欺骗

特性一:包裹性

代码:

<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
    <img src="img/25/2.jpg" />
</div>

block元素不指定width的话,默认是100%,一旦让该div浮动起来,立刻会像inline元素一样产生包裹性,宽度会随内容自适应。这也是通常float元素需要手动指定width的原因。

再加一个div的话,效果如下:

<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;float:left;">
    <img src="img/25/2.jpg" />
</div>
<div style="border:4px solid green;">
    <img src="img/25/3.jpg" /> 
</div>

效果非常近似与display:inline-block,但相比之下,浮动能设定为左浮和右浮,display:inline-block都是从左到右排列的。(还有些细微差别,两个display:inline-block间会有空隙,但两个float间没有。这不是本篇的主题,暂时略过)。

特性二: 高度欺骗

首先声明:其实是CSS层级在起作用,但CSS层级适合单独写一篇,内容实在太多,不适合在这里展开,就理解为高度欺骗吧)

例1中浮动float被设在了外围div上,因此高度欺骗性没体现出来。现在给内层img元素设定float。所谓一图胜千言:

<div style="border:4px solid blue;">
    <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;">
    <img style="border:4px solid yellow;float:left;" src="img/25/2.jpg" />
</div>

和例子1唯一的区别就是:将外层div的float移到内层img中。这下高度欺骗性体现出来了。例1中给外层div加上浮动,因此外层div会有包裹性,其内容是img图片,所以可以看到红色边框包裹着img。

例2中外层div没有了浮动,因此红色边框宽度默认是100%全屏。其内容img由于加上了float,使得该img具有了欺骗性。float给img施了个障眼法,让该img的inline-height高度塌陷为0了。这样外层div计算高度时,认为img的高度为0,相当于div的content的高度为0,因此红色边框看起来是一条直线。

但请注意障眼法毕竟是障眼法,并不是真的让img的高度塌陷为0了,可以看到上图中img的黄色边框还是有正常高度的。如果给div里加点文字,效果如下:

可以看到,外层div在没有手动设定height的前提下,其高度是由内部content的最大高度决定的,由于img的float使得img具有高度塌陷的欺骗性,让div误以为img的line-height为0,因此div的高度就是文字的匿名inline-box的inline-height。

因此浮动并不是让元素的高度塌陷了,而是让元素具有高度塌陷的欺骗性。骗谁?骗别人!但骗不了自己,元素自身还是有高度的(见上图的黄框)。

回过头再看看浮动float的本意:让文字像流水一样环绕图片。重要的事情多看几遍…给div设定一个width:200px,并加点文字吧:

这就是浮动元素的本意。该效果是很难被其他CSS属性等价地模拟的。

但就像开头说的,CSS强大的灵活性使得很多CSS属性被用于了创造者都没想到的场景。以float为例,就被广泛用于了布局。是好是坏呢?不知道!西红柿臭鸡蛋先别急着扔。既然撸主不知道,还废话什么?先看看float布局的问题。渣浪微博改版前的好友列表用浮动布局,效果如下:

<ul>
  <li style="width:138px;margin:0 10px;text-align: center;float:left;">
      <div><img src="img/25/1.jpg" />尼古拉斯.旺财</div>
  </li>
  <li style="width:138px;margin:0 10px;text-align: center;float:left;">
      <div><img src="img/25/2.jpg" />功夫熊猫</div>
  </li>
  <li style="width:138px;margin:0 10px;text-align: center;float:left;">
      <div><img src="img/25/3.jpg" />月野兔</div>
  </li>
  <li style="width:138px;margin:0 10px;text-align: center;float:left;">
      <div><img src="img/25/4.jpg" />猫女郎</div>
  </li>
</ul>

每个li都设为浮动和定宽,实现了水平布局。但如果好友再长点呢?效果如下:

错行啦!常见的修正方案是手动设定一个高度,让文字固定显示一行,用裁掉超行文字的代价以避免错行问题。在撸主看来这就是让CSS属性用于不合原意处的局限性。设固定高度是OK,但如果哪天设计师觉得姓名需要显示两行呢,那固定高度就需要重新计算重新变。如果设计师觉得需要拓宽俄罗斯市场,姓名要显示三行呢?再把固定高度改大点。如果未来Boss脑袋一拍,咦,能不能高度自适应呢?由姓名最大高度的好友来决定每行的高度。你是不是会有准备一下简历的冲动?

当然现实没这么夸张,高度自适应是个烂大街的技术,将浮动float改成 display:inline-block 就行了,效果如下:

代码只需将上面float:left;替换成display: inline-block;,没对齐只需给li加上个vertical-align: top;(上面提到过,相比float,display:inline-block中间会有空隙,眼神好的可以从图中就能看出来,解决方案不是本篇的主题,可以问度娘)。这下高度自适应了,每行的高度都是以名字最长的高度为准。

回过头看用float来水平布局。是好是坏呢?好处是上手简单,随便什么程度的CSSer都能搞定。坏处是有时需要定高难以自适应。而display:inline-block;属性可是根正苗红的水平布局的属性,可以用其替代float。让float尽量多的干其本职工作:让文字像流水一般环绕浮动元素。所以撸主不知道答案。或许也根本没有正确答案,不停的推翻原有的认识和想法人才能进步。

清除浮动

这个就相对比较简单了,用clear即可,稍微要注意的是,clear是仅用作于当前元素,例如元素A是浮动元素,靠左显示。元素B是block元素,紧跟在A后面。此时要清除浮动,是在B上色设置clear:left。你在A上设置clear:right是没有用的,因为A的右边没有浮动元素。

但真的这么简单吗?

先明确一个概念,用clear确实能达到我们期望的清除浮动的效果,这点没异议。但深入点看,究竟是清除了什么样的浮动呢?一图胜千言:

代码:(给页脚加上clear:left)

<div style="border:4px solid blue;">
    <div style="width:200px;border:4px solid red;float:left;">
        我是浮动元素1
    </div>
    <div style="width:200px;border:4px solid yellow;float:left;">
        我是浮动元素2
    </div>
</div>
<div style="border:4px solid gray;clear:left;">我是页脚</div>

因为浮动元素的高度欺骗性,导致外层div失去了高度(蓝色边框成了一条线)。为了让页脚显示到浮动元素下面,对页脚应用了clear:left。这是常规做法,没有任何新奇之处。但是外层div的高度仍旧处于塌陷状态,我们脑海真真正期望的清除浮动后的样子难道不是下面这样吗?

让清除浮动后,原本被欺骗的外层div获得正确的高度!借用文首大神链接的说法,我们脑中期望的其实并不是上图的清除浮动,而是下图的闭合浮动。

闭合浮动

闭合浮动的实现方法很多,常见的是最后增加一个清除浮动的子元素:

<div style="border:4px solid blue;">
  <div style="width:200px;border:4px solid red;float:left;">
      我是浮动元素1
  </div>
  <div style="width:200px;border:4px solid yellow;float:left;">
      我是浮动元素2
  </div>
  <div style="clear:both;"></div>  //加上空白div节点来闭合浮动
</div>
<div style="border:4px solid gray;">我是页脚</div>

缺点是会增加一个DOM节点。(话说当初撸主不知道在哪里看到这个做法时,作者并未讲这么做的原因,导致撸主不明白明明页脚加一个clear属性就能搞定的事,为何要大动干戈加一个DOM节点)

方法二:同样可以在最后增加一个清除浮动的br:将上面代码中<div style=”clear:both;”></div>替换成<br clear=”all” />即可。语义上比空的div标签稍微好一点,但同样会增加一个DOM节点。

方法三:父元素设置 overflow:hidden(如果你还要兼顾IE6的话,加上*zoom:1;来触发hasLayout)

<div style="border:4px solid blue;overflow:hidden;">
  <div style="width:200px;border:4px solid red;float:left;">
      我是浮动元素1
  </div>
  <div style="width:200px;border:4px solid yellow;float:left;">
      我是浮动元素2
  </div>
</div>
<div style="border:4px solid gray;">我是页脚</div>

这看起来很奇怪。因为子元素的浮动的高度欺骗,导致父元素误认为content高度为0(即蓝色边框为一条线),所以父元素设成overflow:hidden溢出隐藏的话,直觉上应该子元素由于溢出导致不显示才对,即整个页面只显示页脚。但实际效果,父元素设成overflow:hidden溢出隐藏后,竟然神奇地出现了闭合浮动的效果(蓝色边框正确获得了高度)。这是怎么回事呢?靠的是BFC,但BFC说起来又是很长一篇,先略过。你可以先简单地这么理解:浏览器厂商认为要让超出边框部分可以被修剪掉,那么前提就是父元素要正确获得高度,即父元素不能被欺骗导致高度塌陷。浏览器正确获得子元素的高度后给父元素重新设置高度。虽然权威解释肯定是BFC,但撸主这样理解了很久…

方法四:同上面将父元素设置 的overflow:hidden改成auto,不赘述

方法五:父元素也设成float。这样确实实现了闭合浮动,但页脚将上移,所以页脚仍旧需要clear:left。还有个缺点是由于浮动的包裹性,你确定父元素真的设成float对页面布局不会产生影响吗?

方法六:父元素设置display:table。效果OK,页脚也不需要设clear:left,但父元素的盒子模型被改变了,请先确认下这样的改动对页面布局不会产生影响吗?

方法七:用:after伪元素,思路是用:after元素在div后面插入一个隐藏文本”.”,隐藏文本用clear来实现闭合浮动:

.clearfix:after {
  clear: both;
  content: ".";   //你头可以改成其他任意文本如“abc”
  display: block;
  height: 0;      //高度为0且hidden让该文本彻底隐藏
  visibility: hidden;
}
.clearfix {
    *zoom: 1;
}


<div style="border:4px solid blue;" class="clearfix">
  <div style="width:200px; border:4px solid red; float:left;">
      我是浮动元素1
  </div>
  <div style="width:200px; border:4px solid yellow; float:left;">
      我是浮动元素2
  </div>
</div>
<div style="border:4px solid gray;">我是页脚</div>

转载自:http://www.jianshu.com/p/07eb19957991

两列自适应布局

Posted on 2017-07-19

1. float+margin

左列:float:left; width:100px;
右列: margin-left:100px

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
    .left {
        float: left;
        width: 100px;
        background: red;
    }
    .main {
        margin-left: 110px;
        width: 100%; /*可以不加*/
        background: green;
    }
    </style>
</head>
<body>
    <div class="left">这是左栏</div>
    <div class="main">这是右栏</div>
</body>

</html>

缺点:如果想修改.left的宽度,还需要修改.main 的margin-left。

2. float+overflow:hidden(触发BFC)

左列: float:left; width: 100px;
右列: overflow:hidden;

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
    .left {
        float: left;
        width: 100px;
        background: red;
    }
    .main {
        overflow: hidden; /*不能加width:100%;*/
        background: green;
    }
    </style>
</head>
<body>
    <div class="left">这是左栏</div>
    <div class="main">这是右栏</div>
</body>

</html>

优点:可以设置浮动的margin来控制间距,想要修改宽度时只修改宽度就行了

3. 绝对定位

左列:float:left;
右列: 绝对应为left

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <style type="text/css">
    .left {
        float: left;
        /* position: relative; */
        width: 100px;
        background: red;
    }

    .main {
        position: absolute;
        left: 100px;
        width: 100%;
        background: green;
    }
    </style>
</head>

<body>
    <div class="left">这是左栏</div>
    <div class="main">这是右栏</div>
</body>

</html>

4. flex布局

不多说。

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <style type="text/css">
    .wrapper {
      display: flex;
    }
    .left {
        flex: 0 1 100px;
        background: red;
    }

    .main {
        flex: 1;
        background: green;
    }
    </style>
</head>

<body>
  <div class="wrapper">
    <div class="left">这是左栏</div>
    <div class="main">这是右栏</div>
  </div> 
</body>

</html>

5. 让重要内容先渲染

右列:float:left; width: 100%;
左列: display: inline-block; margin-left: -100%;width:100px;

<!DOCTYPE html>
<html>

<head>
    <title></title>
    <style type="text/css">
    .main-wrapper {
      margin-left: 100px;
    }
    .left {
        margin-left: -100%;
        display: inline-block; /*或者float: left;*/
        width: 100px;
        background: red;
    }

    .main {
        float: left;
        width: 100%;
        background: green;
    }
    </style>
</head>

<body>
    <div class="main-wrapper">
      <div class="main">这是右栏</div>
    </div>
    <div class="left">这是左栏</div>
</body>

</html>

绝对定位居中技术(Absolute Centering)

Posted on 2017-07-19

水平垂直居中

实现水平垂直居中,只需要三点:

  • 声明元素宽度
  • 给父元素设置相对定位
  • 给该元素设置类Absolute-Center,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    .Absolute-Center {
    margin: auto;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    overflow: auto; // 建议加上
    }

原理

1. 在普通文档流中,margin:auto 的效果等同于margin-top:0; margin-bottom: 0;。

2. position:absolute;使绝对定位块跳出了文档流,文档流其余部分渲染时绝对定位部分不进行渲染。

3. 为块区域设置top:0;left:0;bottom:0;right:0;将给浏览器重新分配一个边界框,此时该块将填充至其父元素的所有可用空间,父元素一般为body,或者声明为position:relative;的容器。

4. 给内容块设置一个width或者height,能够防止内容块占据所有的可用空间,促使浏览器根据新的边界框重新计算margin:auto;

5. 由于内容块被绝对定位,脱离了正常的文档流,浏览器会给magin-top,margin-bottom相同的值,使元素块在先前定义的边界内居中。

简而言之: 绝对定位元素不在普通文档流中渲染,因此margin-auto可以使内容在通过top:0;left:0;bottom: 0;right:0;设置的边界内垂直居中。

误解的地方

以前一直以为margin:auto; 就是上下左右都是按照可用空间同等分配,这是错的!错的!错的!

margin: 0 auto; 表示左右根据可用空间同等分配,而上下设置为0

居中方式

1. 容器内(within container)

这个不多说,就是给父容器设置position:relative;,该元素设置宽高,并加上.Absolute-Center的类。

2. 视区内(within viewport)

想让内容块一只停留在可视区域?给内容块设置为position:fixed;并设置一个z-index:1;层叠属性值即可。

3. 边栏(offsets)

不懂。。。
(待后续研究)

转载自:http://blog.csdn.net/freshlover/article/details/11579669

水平、垂直居中

Posted on 2017-07-19

接连两次面试被问到水平、垂直居中,答了几种方法,但感觉面试官并不是很满意啊,特意再整理一下各种方法~

该元素宽高已知

1. absolute+负margin

父元素:relative

该元素:absolute, left: 50%, top: 50%, margin-left: 负的该元素宽度的一半,margin-right: 负的该元素高度的一半

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
    .div1 {
      width: 100%;
      height: 200px;
      background-color: gray;
      position:relative;
    }

    .div2 {
      width:50px;
      height:50px;
      background-color:red;
      position:absolute;
      left:50%;
      top:50%;
      margin-left:-25px;
      margin-top:-25px;
    }
</style>

    <div class="div1">
        <div class="div2">A</div>
    </div>


</body>
</html>

2. 绝对定位居中技术(Absolute Centering)absolute, margin:auto

这种方法的原理参见:绝对定位居中技术(Absolute Centering)

父元素设置为:relative

该元素设置为: absolute, left:0, top: 0, right:0,bottom:0, marign:auto

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
    .div1 {
      width: 100%;
      height: 200px;
      background-color: gray;
      position:relative;
    }

    .div2 {
      width:50px;
      height:50px;
      background-color:red;
      margin:auto;
      position:absolute;
      left:0;
      top:0;
      right:0;
      bottom:0;
    }
</style>

    <div class="div1">
        <div class="div2">A</div>
    </div>


</body>
</html>

3. flex布局

父元素:display:flex, justify-content: center, align-items: center

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
    .div1 {
      display:flex;
      width: 100%;
      height: 200px;
      background-color: gray;
      /* flex-direction:row; */
      justify-content:center;
      align-items:center;
    }

    .div2 {
      /* flex: 0 1 auto; */
      width:50px;
      height:50px;
      background-color:red;

    }
</style>

    <div class="div1">
        <div class="div2">A</div>
    </div>


</body>
</html>

该元素宽高未知

1. absolute, transform

父元素相对定位

子元素绝对定位,把定宽的负margin换成transform

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
    .div1 {
      position:relative;
      width: 100%;
      height: 200px;
      background-color: gray;
    }

    .div2 {
      position: absolute;
      background-color:red;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%)
    }
</style>

    <div class="div1">
        <div class="div2">Abfkadf;</div>
    </div>


</body>
</html>

2.flex布局

<!DOCTYPE HTML>
<html>
<head>
<title></title>
<meta http-equiv="content" content="text/html" charset="utf-8">
</head>
<body>
<style>
    .div1 {
      display: flex;
      width: 100%;
      height: 200px;
      background-color: gray;
      justify-content: center;
      align-items: center;
    }

    .div2 {
      /* position: absolute; */
      background-color:red;
    }
</style>

    <div class="div1">
        <div class="div2">hhhhhh;</div>
    </div>


</body>
</html>

其他

table-cell

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Demo001_displayTable</title>
    <style>
    /*** table-cell middle center组合使用 ***/

    .cell {
        display: table-cell;
        vertical-align: middle;
        text-align: center;
        width: 240px;
        height: 180px;
        border: 1px solid #666;
    }
    </style>
</head>

<body>
    <div class="cell">
        <p>我爱你</p>
    </div>
    <div class="cell">
        <p>我爱你</p>
        <p>亲爱的中国</p>
    </div>
    <div class="cell">
        <p>我爱你</p>
        <p>亲爱的中国</p>
        <div style="width:100px;height:50px;border:1px solid #ccc;display:inline-block">div(inline-block)</div>
    </div>
</body>

</html>

inline-block 1

  • 首先要了解垂直方向的对齐排版需使用 vertical-align,并且只应用于inline level, inline-block level 及 table-cells 元素上;
  • 其次 vertical-align 的对齐就基于每个 line box(行框) 的,简单的说,inline level元素按照 Normal flow 水平排版出一行就会形成一个line box,其高度由内容形成,如果换行,则又是另一个line box,所有一段文本可能会分布在多个line box里,这些不重叠的line box被称作为a vertical stack of line boxes(一个垂直堆叠的线框集合)这些。
  • 换句话说,我们的垂直居中是要在每个line box中进行处理。而上例中我们想让一行文本在名叫demo的高100px的容器里垂直居中,这时有个问题就是demo容器并非该行文本的line box,所以就算定义vertical-laign为middle也无法让该行文本在demo容器中垂直居中。我们知道line box的高度是由内容形成的,这时我们可以额外创建一个与该行文本处于同一line box的元素,同时将新增元素的高度定义为与demo容器相同,此时line box的高度将与demo一致,文本将会在line box内垂直居中,即同样实现了在demo容器中垂直居中。本例我们使用伪对象::after来创建那个新增元素,可以设置新增元素为不可见。
  • 当然,该方案也是有局限性的,因为IE8以下的浏览器不支持伪对象::after

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Demo001_displayTable</title>
    <style>
    #demo {
    height: 100px;
    text-align: center;
    }
    #demo:after {
    display: inline-block;
    width: 0;
    height: 100%;
    vertical-align: middle;
    content: '';
    }
    #demo p {
    display: inline-block;
    vertical-align: middle;
    }
    </style>
    </head>

    <body>
    <div id="demo">
    <p>水平垂直居中的随意内容</p>
    </div>
    </body>

    </html>

inline-block 2

  • 其实如果理解了line box概念,写上述2个例子时,就肯定知道会存在这个杯具。如上,CSS不变,只将文本变长。之前得以实现垂直居中,主要是将文本所在line box撑高了,而如果新增的元素被过长文本挤换行,则它们将不再处于同一line box,那么垂直居中将失效。你可能存疑,不是已将新增元素width设置为0了吗?怎么还能被挤换行。这时你应该知道一个常识,inline level或inline-block level的元素之间的间隙问题,对此问题不做详述。

以下是终极版,包含浏览器兼容,过长问题

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Demo001_displayTable</title>
    <style>
    #demo {
        height: 100px;
        text-align: center;
        font-size: 0;
    }

    #demo:after,
    #demo span {
        display: inline-block;
        *display: inline;
        *zoom: 1;
        width: 0;
        height: 100%;
        vertical-align: middle;
    }

    #demo:after {
        content: '';
    }

    #demo p {
        display: inline-block;
        *display: inline;
        *zoom: 1;
        vertical-align: middle;
        font-size: 16px;
    }
    </style>
</head>

<body>
    <div id="demo">
        <p>这是一个终极实现的水平垂直居中实例</p>
        <!--[if lt IE 8]><span></span><![endif]-->
    </div>
</body>

</html>

参考:http://demo.doyoe.com/css/alignment/

css盒模型

Posted on 2017-07-19

盒模型属性

  • margin: 外边距
  • border: 内边距
  • padding: 边框
  • content: 内容

标准盒模型

盒模型的宽和高:margin+border+padding+width/height

设置的width/height:是指content区的

IE盒模型(怪异模式)

盒模型的宽和高:margin+width/height

widht/height: content+padding+border

box-sizing

box-sizing: content-box|border-box|inherit

当设置为content-box时,采用标准模式解析;

当设置为border-box时,采用怪异模式解析:

则设置的width和height:是指border+padding+content

边界塌陷

当相邻的两个盒模型上下紧邻的时候,会选择margin值较大的作为外边距,即合并两个外边距取大值,左右外边距不合并。

如果两个div,一个设置为display:inline-block,一个不设置,那么就不会塌陷。

display: none, overflow: hidden, visibility: hidden之间的区别

Posted on 2017-07-19

display: none

隐藏元素,不占网页中的任何空间,让这个元素彻底消失(看不见也摸不着)

overflow: hidden

让超出的元素隐藏,就是在设置该属性的时候他会根据你设置的宽高把多余的那部分剪掉

visibility: hidden

他是把那个层隐藏了,也就是你看不到它的内容但是它内容所占据的空间还是存在的。(看不见但摸得到)

{ display: none; /* 不占据空间,无法点击 */ } 

{ visibility: hidden; /* 占据空间,无法点击 */ } 

{ height: 0; overflow: hidden; /* 不占据空间,无法点击 */ } 

{ position: absolute; top: -999em; /* 不占据空间,无法点击 */ } 

{ position: relative; top: -999em; /* 占据空间,无法点击 */ } 

{ position: absolute; visibility: hidden; /* 不占据空间,无法点击 */ } 

{ opacity: 0; filter:Alpha(opacity=0); /* 占据空间,可以点击 */ } 

{ position: absolute; opacity: 0; filter:Alpha(opacity=0); /* 不占据空间,可以点击 */ } 

重绘与回流

修改常规流中元素的display通常会造成文档重排。修改visibility属性只会造成本元素的重绘。

是否可以读到

读屏器不会读取display: none;元素内容;会读取visibility: hidden;元素内容

是否加载

这个之前腾讯的开发组做过测试,不同浏览器下面表现不同,但是基本上都是加载的,不管你是display:none还是visibility:hidden,亦或是opacity:0,都会加载的。

css绝对定位position:absolute

Posted on 2017-07-19

absolute的特点:包裹性和高度欺骗。

包裹性

区别就是:下面的图div增加了absolute

<div style="border:4px solid blue;">
      <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red; position: absolute;">
      <img src="img/25/2.jpg" />
</div>

一旦给元素加上absolute或float就相当于给元素加上了display:inline-block;。什么意思呢?比如内联元素span默认宽度是自适应的,你给其加上width是不起作用的。要想width定宽,你需要将span设成display:block。但如果你给span加上absolute或float,那span的display属性自动就变成block,就可以指定width了。因此如果看到CSS里absolute/float和display:block同时出现,那display:block就是多余的CSS代码。

高度欺骗

上例中给图片外层的div加上absolute,因此高度欺骗未能很好的体现出来,将absolute移到内部图片上,效果就出来了:

<div style="border:4px solid blue;">
      <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;">
     <img style="position: absolute;" src="img/25/2.jpg" />
</div>

如果你看过CSS浮动float详解会发现效果是一样的。但其背后的原理其实是有区别的,并不完全相同。加点文字就看出来了:

<div style="border:4px solid blue;">
      <img src="img/25/1.jpg" />
</div>
<div style="border:4px solid red;">
      <img style="position: absolute;" src="img/25/2.jpg" />
      我是一个绝对定位的absolute元素
</div>

从图中明显看出文字被图片遮盖了,这点和float不同。float是欺骗父元素,让其父元素误以为其高度塌陷了,但float元素本身仍处于文档流中,文字会环绕着float元素,不会被遮蔽。

但absolute其实已经不能算是欺骗父元素了,而是出现了层级关系。如果处于正常的文档流中的父元素算是凡人的话,那absolute已经得道成仙,用现在的话说已经不在一个次元上。从父元素的视点看,设成absolute的图片已经完全消失不见了,因此从最左边开始显示文字。而absolute的层级高,所以图片遮盖了文字。

如何确定定位点

  • Case1: 用户只给元素指定了absolute,未指定left/top/right/bottom。此时absolute元素的左上角定位点位置就是该元素正常文档流里的位置。如上面图例中,图片熊猫是父元素的第一个孩子,因此左上角定位点就是父元素的content的左上角

如果将图片熊猫和下面的文字顺序改一下,让其成为父元素的第二个孩子,一图胜千言:

<div style="border:4px solid red;">
      我是一个绝对定位的absolute元素
      <img style="position: absolute;" src="img/25/2.jpg" />
</div>

结论重复一遍:未指定left/top/right/bottom的absolute元素,其在所处层级中的定位点就是正常文档流中该元素的定位点。

  • Case2: 用户给absolute元素指定了left/right,top/bottom

先简单点,让absolute元素没有position:static以外的父元素。此时absolute所处的层是铺满全屏的,即铺满body。会根据用户指定位置的在body上进行定位。

通过对left/top/right/bottom的组合设置,由于没有position:static以外的父元素,此时absolute元素可以去任意它想去的地方,天空才是它的极限。

与relative相爱相杀

通常我们对relative的认识是:relative主要用于限制absolute

上面已经说了,如果absolute元素没有position:static以外的父元素,那将相对body定位,天空才是它的极限。而一旦父元素被设为relative,那absolute子元素将相对于其父元素定位,就好像一只脚上被绑了绳子的鸟。

比如你要实现下图iOS里APP右上角的红色圈圈:

通常的做法是将APP图片所处的div设成relative,然后红色圈圈设成absolute,再设top/right即可。这样无论用户怎么改变APP图片的位置,红色圈圈永远固定在右上角,例如:

.tipIcon {
      background-color: #f00;
      color: #fff;
      border-radius:50%;
      text-align: center;
      position: absolute;
      width: 20px;
      height: 20px;
      right:-10px;  //负值为自身体积的一半
      top:-10px;
}

<div style="display: inline-block;position:relative;">
      <img src="img/25/2.jpg" />
      <span class="tipIcon">6</span>
</div>

这样做效果是OK的,兼容性也OK。但CSS的世界里要实现一个效果可以有很多种方式,具体选用哪个方案是见仁见智的。我比较看重的标准:一个是简洁,另一个是尽量让每个属性干其本职工作。

用这两个标准看待上述实现方法,应该是有改进的空间的。首先外层div多了relative未能简洁到极致。 其次relative的本职工作是让元素在相对其正常文档流位置进行偏移,但父层div并不需要任何位置偏移,之所以设成relative唯一的目的是限制absolute子元素的定位点。因此在我看来这并没有让relative干其本职工作。好比小姐的本职工作是服务业,顺便陪客户聊聊天,但纯聊天聊完一个钟,恐怕会被投诉。

那怎么改进呢?答案在上面探讨absolute定位点时已经说了:未指定left/top/right/bottom的absolute元素,其在所处层级中的定位点就是正常文档流中该元素的定位点。因此改进如下:

.tipIcon2 {
  background-color: #f00;
  color: #fff;
  border-radius:50%;
  text-align: center;
  position: absolute;
  width: 20px;
  height: 20px;
  margin:-10px 0 0 -10px;   //不需要top和right了,改用margin来进行偏移
}

<div style="display: inline-block;">  //父元素不需要relative了
  <img src="img/25/2.jpg" /><!--
 --><span class="tipIcon2">6</span> 
</div>
//img和soan间的HTML注释的目的是消除换行符,你也可以将span紧跟在img后面写到一行里

更深入一点看,多一个属性意味着多一层维护。如果用父relative + 子absolute来实现定位,万一将来页面布局要调整,父元素的尺寸需要变换呢?

<div style="display: inline-block; position:relative;width: 200px;">
  <img src="img/25/2.jpg" />
  <span class="tipIcon">6</span>
</div>

上面仅仅由于父元素的width做了些改变,导致右上角absolute图标错位了。由于absolute和relative耦合在了一起,父元素有点风吹草动(如尺寸变化,或干脆需要去掉relative),子元素需要重新寻找定位点。苦逼的前端仔拿着微薄的工资在那里加班加点,那是大大地不划算。但如果用上例中absolute自身的定位特性,无论父元素怎么折腾,红色的圈圈都牢牢黏在图片的右上角。

这么说来relative和absolute是否应该彻底断绝关系呢?不是这样的,这段的标题是“和relative相爱相杀”,刚才说的想杀部分,现在说下什么相爱部分。

用absolute常见的一个案例是透明层覆盖元素。要实现对全屏加一层滤镜怎么办?很容易:

.cover {
    position: absolute;
    left: 0;right: 0;top: 0;bottom: 0;
    background-color: #fff;
    opacity: .5;filter: alpha(opacity=50);
}

<div style="display: inline-block;">
  <img src="img/25/2.jpg" /><!--
  --><span class="tipIcon2">6</span>
</div>
现在是全屏滤镜时间
<span class="cover"></span>

CSS里有个细节值得关注:用absolute的left: 0;right: 0;top: 0;bottom: 0;来实现全屏拉伸,对于absolute元素来说,如果同时设置left和right会水平拉伸,同时设置top和bottom会垂直拉伸。那为何不设width/height为100%呢?代码都贴给你了,可以自己试试。算了告诉你答案吧,前面说了,不设top/right/top/bottom的话absolute会从正常文档流应处的位置开始定位,因此做不到全屏。除非你设置width/height为100%后,同时再设left: 0; top: 0;。这样就显得很啰嗦。

那我不想全屏滤镜,只希望给图片部分设置滤镜呢?用js计算图片的大小尺寸和定位点后,设置absolute滤镜的尺寸和定位点?太麻烦了。用relative吧

<span class="cover"></span> //CSS部分不变
<div style="display: inline-block;position: relative;">
    <span class="cover"></span>
    <img src="img/25/2.jpg" />
    <!--

–>6

结论:

1.相对定位时,不必拘泥于relative+absolute,试试就去掉relative,充分利用absolute自身定位的特性,将relative和absolute解耦。耦合度越低维护起来越容易,前端仔腾出时间陪女朋友吃饭才是正道。

2.拉伸平铺时,用relative可以有效限制子absolute元素的拉伸平铺范围(注意是拉伸,不是缩小。要缩小请再加上width/height:100%;)

和z-index的关系

z-index被太多的滥用了。几乎成了个定势思维:只要设了absolute就需要同步设置z-index。其实不是这样的。上面所有例子都没有用到z-index,同样正常分层正常覆盖。

以下情况根本不需要设z-index:

  • 让absolute元素覆盖正常文档流内元素(不用设z-index,自然覆盖)
  • 让后一个absolute元素覆盖前一个absolute元素(不用设z-index,只要在HTML端正确设置元素顺序即可)

那什么时候需要设置z-index呢?当absolute元素覆盖另一个absolute元素,且HTML端不方便调整DOM的先后顺序时,需要设置z-index: 1。非常少见的情况下多个absolute交错覆盖,或者需要显示最高层次的模态对话框时,可以设置z-index > 1。

比较好的是京东,查看首页源码,设置z-index的地方也只设了1,2,3。少数地方设了11,12,13。我更倾向于理解为是一种内部潜规则,表明更高层级的一种需要。

如果你的页面不比京东更复杂,那z-index通常设成1,2,3足够了。

减少重绘和回流的开销

例如将元素隐藏,你或许会用display:none。

(这里插一句题外话,用display:none隐藏容易显示难,如果你用的是JQuery等插件,你或许会疑惑,直接用show/hide API不就行了,难在哪里?其中一个难点就是保存隐藏前元素的display属性值。例如A隐藏前display:block,B隐藏前display:inline,A和B都改成none隐藏后,要显示出来时,你必须事先保存元素的display属性值,否则做不到显示后display仍旧是原先的值。而这些工作JQuery插件都替你做好了,才让你产生了隐藏显示很容易的错觉。)

其实我更推荐的是absolute控制隐藏和显示。方法当然相当简单,如absolute+ top:-9999em,或absolute + visibility:hidden。

优点是absolute由于层级的关系,隐藏和显示只会重绘,但不会回流(其实我对absolute不会导致回流这一观点是持怀疑态度的,说不会回流显得过于武断,应该是absolute的回流开销小于正常DOM流中回流的开销。但我战斗力不够,尚未找到靠谱合理的检测回流的方法)。而用display:none会导致render tree重绘和回流。

另外,考虑到重绘和回流的开销,可以将动画效果放到absolute元素中,避免浏览器将render tree回流。

转载自:

链接:http://www.jianshu.com/p/a3da5e27d22b

來源:简书

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

1…5678
xixijiang

xixijiang

切莫停下前进的脚步

74 posts
1 categories
12 tags
© 2019 xixijiang
Powered by Hexo
Theme - NexT.Muse