img标签的title和alt属性有什么区别
- alt:图片加载失败时,显示在网页上的替代文字
- title:鼠标(手机端该属性无意义)放在图片上时显示的文字
- alt是必需属性(但属性值可为空),title非必需
图片懒加载的原理
图像是img标记,浏览器根据图像的src属性请求图像,因此惰性加载的关键是当图像不在可视区域时,不给`imgs‘赋值。
懒加载的思路及实现代码详见js实现图片懒加载原理
H5新增了哪些标签?
常见的有:article、aside、audio、video、footer、header、nav、section
H5和H4有什么不同?
H5新特性有: 用于媒体回放的video和audio元素 对本地离线存储的更好的支持 新的特殊内容元素,如article、footer、header、nav、section
简单地说,它更标准,提供更多的多功能支持。更标准、更可读性、更好的性能和更方便的执行。
块级元素、行内元素分别有哪些?
块级元素:div , p , form, ul, li , ol, dl, form, address, fieldset, hr, menu, table 行内元素:span, strong, em, br, img , input, label, select, textarea, cite
SVG和CANVAS的区别?
SVG
表示以XML格式定义图像的可伸缩矢量图形。
CANVAS
通过 JavaScript 来绘制 2D 图形。
二者比较
svg如何调整颜色
标签fill属性设置即可
关于CSS
css3新的特性?
RGBA和透明度
是RGB颜色模型的一个扩展。本质上,在设置元素中添加了一个alpha通道,即一个表示除红色、绿色和蓝色三种颜色之外的透明度的通道。
background属性
- background-image:设置元素的背景图像。
- background-origin:规定背景图片的定位区域。
- background-size :规定背景图片的尺寸。
- background-repeat:设置是否及如何重复背景图像。
word-wrap属性
word-wrap 属性允许长单词或 URL 地址换行到下一行。
注:所有主流浏览器都支持 word-wrap 属性。
基础语法:
word-wrap: normal|break-word;
text-shadow属性
text-shadow 属性:向文本设置阴影。
text-shadow基础语法:
text-shadow: 5px 5px 5px #FF0000;
参数分别表示:水平阴影,垂直阴影,模糊距离,阴影颜色;
font-face属性
font-face属性:定义自己的字体
在新的 @font-face 规则中,您必须首先定义字体的名称(比如 myFirstFont),然后指向该字体文件。
border-radius属性
border-radius 属性:是一个简写属性,用于设置四个 border-*-radius 属性。
基础语法:
border-radius: 1-4 length|% / 1-4 length|%;
注:该属性允许您为元素添加圆角边框!
border-image属性
border-image:将图片规定为包围 div 元素的边框
border-image基础语法:
border-image: url(border.png) 30 30 round
box-shadow属性
box-shadow属性:向框添加一个或多个阴影。(盒阴影)
box-shadow基础语法:
box-shadow: 10px 10px 5px #888888
媒体查询
媒体查询定义两套css,当浏览器的尺寸变化时会采用不同的属性。
元素居中的方式有哪些?
水平居中
1.行内元素水平居中 利用 text-align: center 可以实现在块级元素内部的行内元素水平居中。此方法对inline、inline-block、inline-table和inline-flex元素水平居中都有效。 此外,如果块级元素内部包着也是一个块级元素,我们可以先将其由块级元素改变为行内块元素,再通过设置行内块元素居中以达到水平居中。
2.块级元素的水平居中 ①将该块级元素左右外边距margin-left和margin-right设置为auto。 ②使用table+margin 先将子元素设置为块级表格来显示(类似),再将其设置水平居中。 display:table在表现上类似block元素,但是宽度为内容宽。 ③使用absolute+transform 先将父元素设置为相对定位,再将子元素设置为绝对定位,向右移动子元素,移动距离为父容器的一半,最后通过向左移动子元素的一半宽度以达到水平居中。 不过transform属于css3内容,兼容性存在一定问题,高版本浏览器需要添加一些前缀。 ④使用flex+justify-content 通过CSS3中的布局利器flex中的justify-content属性来达到水平居中。 ⑤使用flex+margin 通过flex将父容器设置为为Flex布局,再设置子元素居中。
3.多块级元素水平居中 ①利用flex布局 利用弹性布局(flex),实现水平居中,其中justify-content 用于设置弹性盒子元素在主轴(默认横轴)方向上的对齐方式,本例中设置子元素水平居中显示。 ②利用inline-block 将要水平排列的块状元素设为display:inline-block,然后在父级元素上设置text-align:center,达到与上面的行内元素的水平居中一样的效果。
4.浮动元素水平居中 对于定宽的浮动元素,通过子元素设置relative + 负margin 对于不定宽的浮动元素,父子容器都用相对定位 通用方法(不管是定宽还是不定宽):flex布局
垂直居中
1.多行内联元素垂直居中 ①利用flex布局(flex) 利用flex布局实现垂直居中,其中flex-direction: column定义主轴方向为纵向。这种方式在较老的浏览器存在兼容性问题。 ②利用表布局(table) 利用表布局的vertical-align: middle可以实现子元素的垂直居中。
2.块级元素垂直居中 ①使用absolute+负margin(已知高度宽度) 通过绝对定位元素距离顶部50%,并设置margin-top向上偏移元素高度的一半,就可以实现了。 ②使用absolute+transform 当垂直居中的元素的高度和宽度未知时,可以借助CSS3中的transform属性向Y轴反向偏移50%的方法实现垂直居中。但是部分浏览器存在兼容性的问题。 ③使用flex+align-items 通过设置flex布局中的属性align-items,使子元素垂直居中。 ④使用table-cell+vertical-align 通过将父元素转化为一个表格单元格显示(类似 和 ),再通过设置 vertical-align属性,使表格单元格内容垂直居中。
水平垂直居中
1、绝对定位+CSS3(未知元素的高宽) 利用Css3的transform,可以轻松的在未知元素的高宽的情况下实现元素的垂直居中。 CSS3的transform固然好用,但在项目的实际运用中必须考虑兼容问题,大量的hack代码可能会导致得不偿失。 2、flex布局 利用flex布局,其中justify-content 用于设置或检索弹性盒子元素在主轴(横轴)方向上的对齐方式;而align-items属性定义flex子项在flex容器的当前行的侧轴(纵轴)方向上的对齐方式。不能兼容低版本的IE浏览器。 3、flex/grid与margin:auto(最简单写法) 容器元素设为 flex 布局或是grid布局,子元素只要写 margin: auto 即可,不能兼容低版本的IE浏览器。
自适应的方案?
viewport方案
配置默认根字号、默认字号、默认设计稿宽度,然后使用postcss插件将代码中的px自动转换成rem,这种方法可以完成使用1080p设计稿再不同手机下的适应方案,所有元素大小均按照1080p下的大小来定义px。配置上述插件后,px单位在编译后会默认转为rem单位,如果不需要被转换,可以将小写的px改成大写的PX或Px。取消使用viewport.js文件,如果遇到不能适配的公共组件,则拷贝一个新的版本,适配新的方案,逐步淘汰老版本。
// 引用该mixin,其中包含了默认的变量等
$default-font-size: 100; // 默认根字号大小,用于换算vw单位
$baseFontSize: 100px; // 默认字号大小,用于计算rem值
$pageWidth: 1080; // 默认的设计稿宽度
@import '@oppobrowser/lib-browser-scss/src/mixins.scss';
//项目的vue.config.js中增加如下postcss配置
// 在css配置项中增加postcss配置,用于px转rem单位,后续合到master后就统一配置了
css: {
loaderOptions: {
sass: {
data: '@import "@/common/scss/variables.scss";',
},
postcss: {
plugins: [
require('postcss-pxtorem')({
// 把px单位换算成rem单位
rootValue: 100, // 换算的基数(设计图1080的根字体为100)
selectorBlackList: [], // 忽略转换正则匹配项
propList: ['*'],
}),
],
}
}
rem方案
针对Android4.4以下版本,全部使用rem单位兼容方案,并在head标签内添加脚本重写html根字号的大小,1080p下为100px。并且针对受影响的公共组件写出兼容性代码。
<script type="text/javascript">
(function(doc, win) {
var basicWidth = 1080;
var minWidth = 360;
var htmlElement = doc.documentElement;
var dpr = parseInt(window.devicePixelRatio || 1, 10);
var recalc = function() {
var clientWidth = htmlElement.clientWidth || (basicWidth / 2);
window.rootFontSize = 100 * (clientWidth / basicWidth);
clientWidth = clientWidth < minWidth? minWidth : clientWidth;
htmlElement.style.fontSize = 100 * (clientWidth / basicWidth) + 'px';
htmlElement.setAttribute("data-dpi", dpr);
};
recalc();
if (!win.addEventListener) return;
win.addEventListener('resize', recalc, false);
})(document, window);
</script>
父容器高度塌陷的解决方案?
overflow:hidden
利用伪元素
div::after {
display: block;
content: "";
clear: both;
}
添加一个div
<style>
.cf {
clear: both;
}
</style>
<div>
.......
.......
<div class="cf"></div>
</div>
清除浮动的方法有哪些?
额外标签法:
给谁清除浮动,就在其后额外添加一个空白标签 。 优点:通俗易懂,书写方便。(不推荐使用) 缺点:添加许多无意义的标签,结构化比较差。
给元素small清除浮动(在small后添加一个空白标签clear(类名可以随意),设置clear:both;即可)
父级添加overflow方法:
可以通过触发BFC的方式,实现清楚浮动效果。 优点:代码简洁(慎重使用,若该父盒子里还有position定位会引起麻烦) 缺点:内容增多时候容易造成不会自动换行导致内容被隐藏掉,无法显示需要溢出的元素。
注意:别加错位置,是给父亲加(并不是所有的浮动都需要清除,谁影响布局,才清除谁。)
使用after伪元素清除浮动:
after方式为空元素的升级版,好处是不用单独加标签了。 优点:符合闭合浮动思想,结构语义化正确 缺点:由于IE6-7不支持:after,使用zoom:1,触发hasLayout。
注意:这个也是给父亲添加 clearfix
使用before和after双伪元素清除浮动:
注意:是给父亲添加clearfix
less和sass的区别?
不管是Sass,还是Less,都可以视为一种基于CSS之上的高级语言,其目的是使得CSS开发更灵活和更强大,Sass的功能比Less强大,基本可以说是一种真正的编程语言了,Less则相对清晰明了,易于上手,对编译环境要求比较宽松。考虑到编译Sass要安装Ruby,而Ruby官网在国内访问不了,个人在实际开发中更倾向于选择Less。
关于JS、ES6
es6兼容的浏览器版本
支持ie 11+
var,let,const的比较?
- var声明变量存在变量提升,let和const不存在变量提升
- let、const都是块级局部变量
- 同一作用域下let和const不能声明同名变量,而var可以
继承的方式有那几种?
原型链继承
父类的实例作为子类的原型
借用构造函数继承(伪造对象、经典继承)
复制父类的实例属性给子类
实例继承(原型式继承)
组合式继承
调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用
寄生组合继承
通过寄生的方式来修复组合式继承的不足,完美的实现继承
es6 extends继承
代码量少,易懂
ES5继承和ES6继承的区别
es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中
Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this)
es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this
说说对原型链的理解
原型链,简单理解就是原型组成的链,对象的proto它的是原型,而原型也是一个对象,也有proto属性,原型的proto又是原型的原型,就这样可以一直通过proto想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。
有哪些数据类型
值类型(基本类型):
字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。
引用数据类型:
对象(Object)、数组(Array)、函数(Function)。
判断数据类型的方式有哪些
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
数组去重的方式
1、使用set
2、使用 filter()
3、使用 reduce()
const array = [' ', 1, 2, ' ',' ', 3];
// 1: "Set"
[...new Set(array)];
// 2: "Filter"
array.filter((item, index) => array.indexOf(item) === index);
// 3: "Reduce"
array.reduce((unique, item) =>
unique.includes(item) ? unique : [...unique, item], []);
// RESULT:
// [' ', 1, 2, 3];
深拷贝和浅拷贝的方式
深拷贝
1、最简单的方法就是JSON.parse(JSON.stringify())
function deepCopy(o) {
return JSON.parse(JSON.stringify(o))
}
var c = {
age: 1,
name: undefined,
sex: null,
tel: /^1[34578]\d{9}$/,
say: () => {
console.log('hahha')
}
}
// { age: 1, sex: null, tel: {} }
需要注意的是:这种拷贝方法不可以拷贝一些特殊的属性(例如正则表达式,undefine,function)
2、用递归去复制所有层级属性
function deepCopyTwo(obj) {
let objClone = Array.isArray(obj) ? [] : {};
if (obj && typeof obj == 'object') {
for (const key in obj) {
//判断obj子元素是否为对象,如果是,递归复制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deepCopyTwo(obj[key]);
} else {
//如果不是,简单复制
objClone[key] = obj[key];
}
}
}
return objClone;
}
浅拷贝
object.assign(target,source)
防抖和节流的区别
debounce和throttling 各有特点,在不同 的场景要根据需求合理的选择策略。如果事件触发是高频但是有停顿时,可以选择debounce; 在事件连续不断高频触发时,只能选择throttling,因为debounce可能会导致动作只被执行一次,界面出现跳跃。
二叉树的遍历有几种方法?
- 先序
- 中序
- 后序
- 层序遍历
具体实现方法详见:二叉树遍历的几种常见方法
数组扁平化有几种方法?
二维数组时,可以简单使用flat()方法
let arr = [[1,2],[3,4],[5,6]];
let arr = [[1,2],[3,4],[5,6]].flat();
console.log(arr); // [1,2,3,4,5,6]
如果是多维数组,则flat()将达不到效果,
需要给flat()传一个参数,var newArray = arr.flat([depth]),
参数:depth ,可选,指定要提取嵌套数组的结构深度,默认值为 1。
let arr = [[1,2],[3,4],[5,6]].flat(Infinity);
console.log(arr); // [1,2,3,4,5,6]
迭代实现 (ES6扩展运算符…)
const arr = [1,2,[3,4,5,[6,7],8],9,10,[11,[12,13]]];
const flatten = (arr) => {
while(arr.some(item=>Array.isArray(item))){
arr=[].concat(…arr);
}
return arr;
}
console.log(flatten(arr)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
普通递归实现
const arr = [1,2,[3,4,5,[6,7],8],9,10,[11,[12,13]]];
const flatten = (arr) => {
let result = [];
arr.forEach((item, i, arr) => {
if (Array.isArray(item)) {
result = result.concat(flatten(item));
} else {
result.push(arr[i])
}
})
return result;
};
console.log(flatten(arr));