原文首发于个人博客,欢迎关注~css
我已经入职字节跳动实习啦~~,有对前端感兴趣的同窗能够随时找我内推哟,邮箱:html
职位描述前端
职位要求:vue
即将面试今日头条的前端实习,这次必定要作好充足准备,特打算花个几天的时间对前端来一个系统性的梳理(前端太庞大,其实也只能包含一小部分哈哈)。虽然检查了不少遍,可能仍有错误,若是发现,请指正,谢谢!git
本文参考了不少资料,特别须要感谢的有:es6
参考:github.com/lukehoban/e…github
Promise 与回调函数同样用来管理 JS 中的异步编程,它的提出解决了层层回调函数嵌套形成的回调地狱。new Promise的时候,会把传递的函数当即执行。Promise函数天生有两个参数,resolve(当异步操做执行成功,执行resolve方法),rejected(当异步操做失败,执行reject方法) 。面试
经过使用 Promise 的 .then()
方法,能够注册回调函数,并在 Promise resolved 以后被调用,then
能够返回一个新的 Promise,Promise 将会 resolve 为 then
注册的函数中的返回值,这样实现了链式的回调函数注册。Promise 有三种可能状态,pending、fulfilled(成功)、rejected(失败)。一个 Promise 一旦 resolve 或者 reject 状态就再也不改变。能够用 .catch()
获取 reject 的 Promise 的缘由,也能够用 .then()
第二个参数获取。另外还有 Promise.all
、Promise.race
等等。ajax
相关代码以下(来源:github.com/Molunerfinn… ):正则表达式
// 实现 Promise.race,resolve 或 reject 第一个便可
Promise.race = function (promises) {
return new Promise((resolve, reject) => {
for (const item of promises) {
Promise.resolve(item).then(res => {
resolve(res)
}, err => {
reject(err)
})
}
})
}
// 实现Promise.all
Promise.all = function (promises) {
const length = promises.length
let count = 0
const result = new Array(length) // 暂存结果
return new Promise((resolve, reject) => {
for (const item in promises) {
Promise.resolve(promises[item]).then(res => {
count++
// Promise.all 输出结果顺序是按传入的promise的顺序来的
result[item] = res
if (count === length) { // 所有完成再 resolve
return resolve(result)
}
}, err => {
reject(err) // 一旦有 reject,就 reject
})
}
})
}
复制代码
相应的,还有 async
、await
。
异步编程四种方法:
function print(a = 'test') {
console.log(a)
}
print() // test
print('Hello') // Hello
复制代码
另外还有:
模板字符串(能够嵌套)
解构赋值(数组、对象)
展开语法 ...
,接收剩余参数、将数组转换为逗号分隔的变量
块级做用域 let
、const
,无变量提高,不容许重复声明
迭代器和 for
... of
生成器
function* d() { // Generator 函数。它不一样于普通函数,是能够暂停执行的,因此函数名以前要加星号,以示区别。
for (let i = 0; i < 3; i++) {
yield i * i
}
}
for (let i of d()) { // 调用 Generator 函数,会返回一个内部指针(即迭代器/遍历器 ),即执行它不会返回结果,返回的是指针对象
console.log(i) // 0, 1, 4
}
console.log(d().next()) // {value: 0, done: false},调用指针对象的 next 方法,会移动内部指针;next 方法的做用是分阶段执行 Generator 函数
复制代码
模块,import
、export
模块加载器
Map + Set + WeakMap(只接受对象键名,且是弱引用) + WeakSet
箭头函数,箭头函数没有 arguments
实参集合,取而代之用 ...
运算符
全部 var
声明都会被提高到做用域的最顶上
同一个变量声明只进行一次
console.log(foo) // undefined,刚刚声明完成可是并未赋值
var foo = 3
console.log(foo) // 3,完成赋值
var foo = 5
console.log(foo) // 5,再次赋值
复制代码
函数声明的优先级优于变量声明,且函数声明会连带定义一块儿被提高
console.log(foo) // 输出 `foo() {}`
function foo() {}
foo = 5
复制代码
注意只有 var
才能提高,不带 var
的全局变量仍是按照顺序声明
console.log(foo) // Uncaught ReferenceError: foo is not defined
foo = 3
foo = 5
复制代码
在 ES5 中,js 只有两种形式的做用域:全局做用域和函数做用域。
先来看看 var
:
(function() {
var a = b = 5;
})();
var c = 55
console.log(window.c) // 55,var 做用域存在于所定义的函数,不然(没有外围函数)就属于 window(浏览器)/global(Node.js)
console.log(b); // 5,b 没有关键字 var,是全局变量
console.log(window.b); // 5,全局变量也属于 window 对象
console.log(a); // undefined,离开了 a 的做用域
复制代码
在 ES6 中,新增长的 let/const
让 块级做用域(block scope) 成为现实,在js中常见到的 if{}
、for{}
、while{}
、try{}
、catch{}
、switch case{}
甚至直接单纯的 {}
这种带花括号的都是块级做用域,var obj = {}
中对象的大括号不是块级做用域。块级做用域中的同一变量不能被重复声明(块级下 let
不能重复定义,严格模式下 function 也不能重复声明)。
this
指向this
的指向和 var
很相似,this
老是指向调用这个函数的对象,根据 this
所在的函数主要分为两种状况:
若是此函数是一个对象 obj
的成员,咱们称之为方法(method),this
指向方法所属对象 obj
。
const video = {
title: 'a',
play() {
console.log(this)
}
}
video.play() // Object {title: "a", play: function play()}
video.stop = function() {
console.log(this)
}
video.stop() // Object {title: "a", play: function play()}
复制代码
若是此函数是一个普通函数,即不是某个对象的一部分,this
指向 window(浏览器)/global(Node.js),若是是严格模式则是 undefined
。
function playVideo() {
console.log(this)
}
playVideo() // Window
复制代码
构造函数同 1 相似,this
指向新建立的对象。
function Video(title) {
this.title = title
console.log(this)
}
const v = new Video('b') // Video {title: "b"}
复制代码
回调函数,this
指向 window(浏览器)/global(Node.js)。
function Video(title) {
this.title = title
console.log(this)
const arr = [1, 2, 3]
arr.forEach(function(ele) {
console.log(this) // 三次打印 Window,要使 `this` 指向新建的 Video,有两种方法:
// 1. forEach 在 callback 参数以后能够添加 `thisArg` 参数
// 2. 使用 ES6 中新增的箭头函数
})
}
const v = new Video('b')
复制代码
箭头函数,this
指向外层函数的 this
,而且不能用 call
进行指定。
const obj = {
a: () => {
console.log(this)
}
}
obj.a() // Window
obj.a.call('123') // Window
复制代码
元素监听函数,指向元素自己。
let button = document.getElementById('button')
button.addEventListener('click', function(e) {
console.log(this) // <button id="button">测试 this</button>
})
复制代码
简单来讲闭包就是在函数里面声明函数并返回,当一个函数可以访问和操做另外一个函数做用域中的变量时,就构成了一个闭包(Closure)。咱们要记住函数在执行时使用的是声明时所处的做用域链,而不是调用时的做用域链。
function addTo(base) {
let sum = base
return function(b) {
sum += b
return sum
}
}
let add = addTo(2)
console.log(add(4)) // 6
console.log(add(5)) // 11
复制代码
同源策略指的是协议、域名、端口相同,一段脚本只能读取来自同源的信息。注意子域名也不一样源。
同源策略限制是有道理的,假设没有同源策略,黑客能够利用 IFrame 把真正的银行登录界面嵌入到他的页面上,当你使用真实用户名、密码登陆时,他的页面就能够经过 JS 读取到 Iframe 中 input 中的内容、你使用的 Cookie 等,可以轻松盗取用户信息。
跨域主要有如下几种方法:
<script>
的 src
属性(相似的还有 href
属性)不受同源策略限制,咱们在 js 中定义回调函数 callback(data)
接收服务器传来的 data
,请求时必须指定回调函数名称,服务器动态生成 js 脚本对本地的 js callback
进行调用并传入服务端查询获得的 data
数据。注意 jsonp 只能解决 GET 请求。document.domain = ...
。脚本能够将 document.domain 的值设置为其当前域或其当前域的父域。注意,company.com 不能设置 document.domain 为 othercompany.com,由于它不是 company.com 的父域。Access-Control-Allow-Origin: *
便可像普通 ajax 同样访问跨域资源。注意如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,称为非简单请求,在正式通讯以前,还须要增长一次预检请求(preflight)。用到的头部有 Access-Control-Request-Method
、Access-Control-Request-Headers
、Access-Control-Allow-Methods
、Access-Control-Allow-Headers
、Access-Control-Allow-Credentials
(发送Cookie和HTTP认证信息)。window.postMessage()
。现代浏览器中多窗口通讯使用 HTML5 规范的 targetWindow.postMessage(data, origin);其中 data 是须要发送的对象,origin 是目标窗口的 origin。window.addEventListener('message', handler, false);handler 的 event.data 是 postMessage 发送来的数据,event.origin 是发送窗口的 origin,event.source 是发送消息的窗口引用。相同点:保存在浏览器,同源。
不一样点
window.sessionStorage
和 window.localStorage
不会自动把数据发给服务器,仅在本地保存;call
vs apply
vs bind
call
和 apply
都是用来改变函数执行的时候的 this
和参数。惟一不一样的是 call
传入逗号(comma)分隔的参数,apply
传入数组(array)做为参数。
bind
返回一个新的函数,传入一个 this
参数和逗号分隔的参数,新返回的函数执行时使用给定的 this
和参数。
若是要本身实现这三个函数的话,核心的思路就是:
Function.prototype.newCall = function (context, ...args){
//...
context.fn = this // 当前调用 newCall 的函数
const
result = context.fn(...args) // 此处调用时改变了this指向,fn的this指向context
// ...
}
复制代码
参考:segmentfault.com/a/119000000…
事件流描述的是从页面中接收事件的顺序,也可理解为事件在页面中传播的顺序。
事件冒泡和事件捕获分别由微软和网景公司提出,在事件捕获的概念下在p元素上发生click事件的顺序应该是document -> html -> body -> div -> p,在事件冒泡的概念下在p元素上发生click事件的顺序应该是p -> div -> body -> html -> document。
addEventListener有三个参数:
element.addEventListener(event, function, useCapture) 复制代码
第三个参数默认值是false,表示在事件冒泡阶段调用事件处理函数;若是参数为true,则表示在事件捕获阶段调用处理函数。点击下面的 s2 按钮查看效果。
See the Pen event capture and bubbling by Li Yiming (@upupming) on CodePen.
注意:对于target节点上(这里的 s2),是先捕获仍是先冒泡则捕获事件和冒泡事件的注册顺序,先注册先执行)。
阻止冒泡:
function stopBubble(e) {
if (e && e.stopPropagation) { // 若是提供了事件对象event 这说明不是IE浏览器
e.stopPropagation()
} else {
window.event.cancelBubble = true //IE方式阻止冒泡
}
复制代码
See the Pen 事件代理 by Li Yiming (@upupming) on CodePen.
IE浏览器对addEventListener兼容性并不算太好,只有IE9以上可使用。
要兼容旧版本的IE浏览器,可使用IE的attachEvent函数
object.attachEvent(event, function) 复制代码
两个参数与addEventListener类似,分别是事件和处理函数,默认是事件冒泡阶段调用处理函数,要注意的是,写事件名时候要加上"on"前缀("onload"、"onclick"等)。
typeof
vs. instanceof
参考:stackoverflow.com/questions/8…
typeof
用来判断简单原始类型(primitive types),instanceof
用来判断复杂原始类型、Object、自定义数据类型。
/** 简单原始类型 */
'example string' instanceof String; // false
typeof 'example string' == 'string'; // true,string 类型用 typeof
'example string' instanceof Object; // false
typeof 'example string' == 'object'; // false
true instanceof Boolean; // false
typeof true == 'boolean'; // true,boolean 类型用 typeof
99.99 instanceof Number; // false
typeof 99.99 == 'number'; // true,number 类型用 typeof
function() {} instanceof Function; // true
typeof function() {} == 'function'; // true,function 类型用 typeof、instanceof 都可
/** 复杂原始类型 */
/regularexpression/ instanceof RegExp; // true,正则表达式用 instanceof
typeof /regularexpression/; // object
[] instanceof Array; // true,array 用 instanceof
typeof []; //object
{} instanceof Object; // true,object 用 instanceof
typeof {}; // object
/** 自定义类型 */
var ClassFirst = function () {};
var ClassSecond = function () {};
var instance = new ClassFirst();
typeof instance; // object
typeof instance == 'ClassFirst'; // false
instance instanceof Object; // true
instance instanceof ClassFirst; // true
instance instanceof ClassSecond; // false
复制代码
除了上面的 instanceof
外还有以下方法:
// Array API
Array.isArray(arr)
// Object类型的toString会返回[object type],其中type是类型
// 可是有的对象的toString方法会被改写
// 因此须要借用一下Object原始的toString
return Object.prototype.toString.call(arr) === '[object Array]'
// 利用自定义对象的 constructor
arr.constructor.name === 'Array'
复制代码
instanceof
循环使用 Object.getPrototypeOf()
便可:
// getPrototypeOf 可同时用于对象和原型,不能直接用于类型(直接返回 Function.prototype)
Object.getPrototypeOf([]) === Array.prototype // true
Object.getPrototypeOf(Array.prototype) === Object.prototype // true
Object.getPrototypeOf(Array) == Function.prototype // true
let newInstanceOf = function (left, right) {
// 检查必须是复杂数据类型
if (typeof left !== 'object' && typeof left !== 'function') {
return false
}
right = right.prototype
do {
left = Object.getPrototypeOf(left)
if (left === right) return true
} while (left !== null)
return false
}
复制代码
也可使用 isPrototypeOf
直接检查对象是否在另外一对象的其原型链上:
Object.prototype.isPrototypeOf([]) // true
Array.prototype.isPrototypeOf([]) // true
复制代码
另外注意 hasOwnProperty
在执行对象查找时,始终不会查找原型。
==
vs ===
==
:容许不一样数据类型之间的比较,若是是不一样类型的数据进行比较,会默认进行数据类型之间的转换,若是是对象数据类型的比较,比较的是空间地址;
a = [1, 2]
b = [1, 2]
// 比较地址空间
a == b // false
_.isEqual(array1, array2) // true,使用 Lodash 库进行比较,或者本身一个一个元素进行比较
false
复制代码
===
:只要数据类型不同,就返回false。
防抖是说连续两次的调用必须间隔指定的时间,节流是说当调用一次以后,必须在指定时间以后的调用才会有效。
具体使用场景:
resize
调整窗口大小,由于一次窗口调整中间会出发出至关多的时间间隔很短的 resize
事件,那么防抖主要是看用户进行调整的总次数,而节流看的是每一次调整时,用户的 resize
的手速有多快。front end
,当你输入前面的 f
或者 front
时就会出现候选结果。可是由于 API 调用消耗很大,因此会使用防抖来较少调用次数,这符合用户停顿时就是想看到搜索结果的现实逻辑。实现以下:
function debounce(func, limit) {
let timer
return function (...args) {
// 前一次还没来得及执行的话,取消掉前一次的
clearTimeout(timer)
timer = setTimeout(() => {
func.apply(this, args)
}, limit)
}
}
function throttle(func, limit) {
let flag = true
return function(...args) {
if (flag) {
func.apply(this, args)
flag = false
// 只有通过指定时间后,才能够执行新的
setTimeout(() => {
flag = true
}, limit)
}
}
}
复制代码
在非IE浏览器(如Firefox)下,当容器的高度为auto,且容器的内容中有浮动(float为left或right)的元素,在这种状况下,容器的高度不能自动伸长以适应内容的高度,使得内容溢出到容器外面而影响(甚至破坏)布局的现象。这个现象叫浮动溢出,为了防止这个现象的出现而进行的CSS处理,就叫CSS清除浮动。
inline-block
,其 margin: 0 auto
居中方式失效overflow:hidden
See the Pen 圣杯布局 by Li Yiming (@upupming) on CodePen.
See the Pen 双飞翼布局 by Li Yiming (@upupming) on CodePen.
ajax的原理:至关于在用户和服务器之间加一个中间层(ajax引擎),使用户操做与服务器响应异步化。
怎么解决呢?经过location.hash
值来解决Ajax过程当中致使的浏览器前进后退按键失效, 解决之前被人常遇到的重复加载的问题。主要比较先后的hash值,看其是否相等,在判断是否触发ajax。
function getData(url) {
var xhr = new XMLHttpRequest(); // 建立一个对象,建立一个异步调用的对象
xhr.open('get', url, true) // 设置一个http请求,设置请求的方式,url以及验证身份
xhr.send() //发送一个http请求
xhr.onreadystatechange = function () { //设置一个http请求状态的函数
if (xhr.readyState == 4 && xhr.status ==200) {
console.log(xhr.responseText) // 获取异步调用返回的数据
}
}
}
复制代码
AJAX状态码:
setTimeout
实现 setInterval
基本思想:
function mySetInterval(handler, timeout, ...arguments) {
const fn = () => { // 关键在于构造 fn 反复调用 handler
handler()
setTimeout(fn, timeout)
}
setTimeout(fn, timeout)
}
mySetInterval(() => {
console.log(`bla bla...`)
}, 1000)
复制代码
另外,还能够实现 clearTimeInterval
(利用全局 obj
存储自增的 id
到 timeId
的映射) 和 arguments
自定义参数。
JavaScript 的并发模型基于“事件循环”。这个模型与像 C 或者 Java 这种其它语言中的模型大相径庭。
一个 JavaScript 运行时包含了一个待处理的消息队列。每个消息都关联着一个用以处理这个消息的函数。
在事件循环期间的某个时刻,运行时从最早进入队列的消息开始处理队列中的消息。为此,这个消息会被移出队列,并做为输入参数调用与之关联的函数。调用一个函数老是会为其创造一个新的栈帧。函数的处理会一直进行到执行栈再次为空为止;而后事件循环将会处理队列中的下一个消息(若是还有的话)。
Event Loop是一个程序结构,用于等待和发送消息和事件。常见形式:
while (queue.waitForMessage()) {
queue.processNextMessage();
}
复制代码
const s = new Date().getSeconds();
setTimeout(function() {
// 输出 "2",表示回调函数并无在 500 毫秒以后当即执行
// 而是等待下面的 while 执行完以后才开始执行
// 在浏览器里,当一个事件发生且有一个事件监听器绑定在该事件上时,消息会被随时添加进队列。
// 500ms事后,WebAPIs把此函数放入任务队列,此时while循环还在栈中,此函数须要等待;
console.log("Ran after " + (new Date().getSeconds() - s) + " seconds");
}, 500);
while(true) {
// while循环执行完毕从栈中弹出,main()弹出,此时栈为空,Event Loop,setTimeout中的回调函数进入栈
if(new Date().getSeconds() - s >= 2) {
console.log("Good, looped for 2 seconds");
break;
}
}
复制代码
class
& interface
在es6中,咱们有一种新的关键字class
来定义一个类;咱们能够继承方法和属性,使用extends
关键字继承;其实本质上,仍是使用原型链的方式继承,只是给了更好理解的语法糖;Typescript在 class
的基础上添加了访问修饰符和接口 interface
。
property:属性,attribute:特性
attribute 是 DOM 元素在文档中做为 HTML 标签拥有的属性;property 是 DOM 元素在 JavaScript 中做为对象拥有的属性。
input.value
、input.id
、input.disabled
、a1.href
等等attributes
属性中,经常使用方法:getAttribute
、setAttribute
、removeAttribute
;value
,class
这样的属性/特性,数据绑定的方向是单向的,attribute->property;id
而言,数据绑定是双向的,attribute<=>property;disabled
而言,property上的disabled设置为false时,会移除attribute上的 disabled
,反之亦然,此时数据绑定能够认为是双向的;置换元素(replaced element)主要是指 img, input, textarea, select, object 等这类默认就有 CSS 格式化外表范围的元素。进而可知,非置换元素(non-replaced element)就是除了 img, input, textarea, select, object 等置换元素之外的元素。
在 CSS 中,可替换元素(replaced element)的展示效果不是由 CSS 来控制的。这些元素是一种外部对象,它们外观的渲染,是独立于 CSS 的。
background-color 规定要使用的背景颜色。
background-position 规定背景图像的位置。
background-size 规定背景图片的尺寸。
background-repeat 规定如何重复背景图像。
background-origin 规定背景图片的定位区域。
background-clip 规定背景的绘制区域。
background-attachment 规定背景图像是否固定或者随着页面的其他部分滚动。
background-image 规定要使用的背景图像。
inherit 规定应该从父元素继承 background 属性的设置。
box-sizing: content-box
(默认)
总宽度 = margin-left + border-left + padding-left + width + padding-right + border-right + margin-right
若是你设置一个元素的宽为 100px,那么这个元素的内容区会有 100px 宽,而且任何边框和内边距的宽度都会被增长到最后绘制出来的元素宽度中。
box-sizing: border-box
总宽度 = margin-left + width + margin-right
你想要设置的边框和内边距的值是包含在width内的。也就是说,若是你将一个元素的width设为100px,那么这100px会包含它的border和padding,内容区的实际宽度是width减去(border + padding)的值。大多数状况下,这使得咱们更容易地设定一个元素的宽高。
在ie8+浏览器中使用哪一个盒模型能够由box-sizing(CSS新增的属性)控制,默认值为content-box,即标准盒模型;若是将box-sizing设为border-box则用的是IE盒模型。若是在ie6,7,8中DOCTYPE缺失会触发IE模式。在当前W3C标准中盒模型是能够经过box-sizing自由的进行切换的。
利用标准盒模型便可:
See the Pen VwwdxXr by Li Yiming (@upupming) on CodePen.
参考:www.w3schools.com/cssref/trys…
static
、relative
、absolute
、fixed
参考:www.cnblogs.com/theWayToAce…
static
(静态定位):默认值。没有定位,元素出如今正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
relative
(相对定位):生成相对定位的元素,经过top,bottom,left,right的设置相对于其正常(原先自己)位置进行定位。可经过z-index进行层次分级。
absolute
(绝对定位):生成绝对定位的元素,相对于 static 定位之外的第一个父元素进行定位。元素的位置经过 "left", "top", "right" 以及 "bottom" 属性进行规定。可经过z-index进行层次分级。
fixed
(固定定位):生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置经过 "left", "top", "right" 以及 "bottom" 属性进行规定。可经过z-index进行层次分级。
定位于父级内部某个位置的元素,最好用 absolute,由于它不受父级元素的padding的属性影响,固然你也能够用relative,不过到时候计算的时候不要忘记padding的值。
inline
vs. inline-block
vs. block
block和inline这两个概念是简略的说法,完整确切的说应该是 block-level elements (块级元素) 和 inline elements (内联元素)。
block元素一般被现实为独立的一块,会单独换一行;inline元素则先后不会产生换行,一系列inline元素都在一行内显示,直到该行排满。
大致来讲HTML元素各有其自身的布局级别(block元素仍是inline元素):
block元素能够包含block元素和inline元素;但inline元素只能包含inline元素。要注意的是这个是个大概的说法,每一个特定的元素能包含的元素也是特定的,因此具体到个别元素上,这条规律是不适用的。好比 P 元素,只能包含inline元素,而不能包含block元素。
细节对比:
display:block
block元素会独占一行,多个block元素会各自新起一行。默认状况下,block元素宽度自动填满其父元素宽度。
block元素能够设置width,height属性,即便设置了宽度,仍然是独占一行。
block元素能够设置margin和padding属性。
display:inline
inline元素不会独占一行,多个相邻的行内元素会排列在同一行里,直到一行排列不下,才会新换一行,其宽度随元素的内容而变化。
inline元素设置width,height属性无效。
inline元素的margin和padding属性,水平方向的padding-left, padding-right, margin-left, margin-right都产生边距效果;
但竖直方向的padding-top, padding-bottom, margin-top, margin-bottom不会产生边距效果。
display:inline-block
简单来讲就是将对象呈现为inline对象,可是对象的内容做为block对象呈现。以后的内联对象会被排列在同一行内。
好比咱们能够给一个link(a元素)inline-block属性值,使其既具备block的宽度高度特性又具备inline的同行特性。
margin: auto
:适用于块级元素
text-align: center
:适用于内联元素
line-height: height
:适用于内联元素
The line-height
CSS property sets the height of a line box. It's commonly used to set the distance between lines of text. On block-level elements, it specifies the minimum height of line boxes within the element. On non-replaced inline elements, it specifies the height that is used to calculate line box height.
line-height
CSS 属性用于设置多行元素的空间量,如多行文本的间距。对于块级元素,它指定元素行盒(line boxes)的最小高度。对于非替代的 inline 元素,它用于计算行盒(line box)的高度。(也就是说内联元素的高度就是在父元素中指定的 line-height
了。)
绝对定位负 margin
:适用于块级元素
父元素:relative;子元素:absolute,margin-top: -(高度的一半); margin-left: -(宽度的一半);
绝对定位 + transform
:适用于块级元素
See the Pen neg-margin by Li Yiming (@upupming) on CodePen.
绝对定位 + margin: auto
:适用于块级元素
See the Pen neg-transform by Li Yiming (@upupming) on CodePen.
另外还有:
使用 flex
弹性盒子布局:块级元素(兼容性很差)
.parent {
width: 600px;
height: 200px;
border: 1px solid red;
display: flex;
align-items: center; /*垂直居中*/
justify-content: center; /*水平居中*/
}
复制代码
padding
child 是 parent 的一半:块级元素
display: table-cell
伪元素
::before
和 ::after
垂直居中:
.parent {
width: 300px;
height: 300px;
border: 1px solid red;
text-align: center;
}
.child {
background: blue;
width: 100px;
height: 40px;
display: inline-block;
vertical-align: middle;
}
.parent::before {
content: '';
height: 100%;
display: inline-block;
vertical-align: middle;
}
复制代码
连接:www.nowcoder.com/questionTer… 来源:牛客网
<article id="electriccars" data-columns="3" data-index-number="12314" data-parent="cars">
...
</article>
复制代码
JS 访问利用 .dataset
:
var article = document.querySelector('#electriccars');
article.dataset.columns // "3"
article.dataset.indexNumber // "12314"
article.dataset.parent // "cars"
复制代码
CSS 访问利用 attr()
:
article::before {
content: attr(data-parent);
}
/* 属性选择器使用 data */
article[data-columns='3'] {
width: 400px;
}
article[data-columns='4'] {
width: 600px;
}
复制代码
beforeCreate
:vue 实例的挂载元素 el
和数据对象 data
都是 undefined
,尚未初始化。【None】created
:vue 实例的数据对象 data
有了,能够访问数据和方法,未挂载到 DOM,el
尚未。【data
】beforeMount
:vue 实例的 el
和 data
都初始化了,可是挂载以前为虚拟的 DOM 结点。【data
& el
】mounted
:vue 实例挂载到真正的 DOM 上,能够经过 DOM 获取 DOM 结点。【data
& el
& DOM】beforeUpdate
:响应式数据更新时调用,发生在虚拟 DOM 打补丁以前,适合在更新以前访问现有的 DOM,好比手动移除已添加的事件监听器。【data
& el
& 旧 DOM】updated
:虚拟DOM从新渲染和打补丁以后调用,组成新的DOM已经更新,避免在这个钩子函数中操做数据,防止死循环。【【data
& el
& 新 DOM】】beforeDestroy
:实例销毁前调用,实例还能够用,this能获取到实例,经常使用于销毁定时器,解绑事件。destroyed
:实例销毁后调用,调用后全部事件监听器会被移除,全部的子实例都会被销毁。