链接
如何实现浏览器内多个标签页之间的通信? (阿里)
WebSocket、SharedWorker;
也可以调用localstorge、cookies等本地存储方式;
localstorge另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,
我们通过监听事件,控制它的值来进行页面信息通信;
注意quirks:Safari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常
js如何判断数组是Array类型
在说明如何判断一个对象为数组类型前,我们先巩固下js的数据类型,
js一共有六大数据类型:number、string、object、Boolean、null、undefined。
var str="string";
console.log(typeof str); //string
var num=1;
console.log(typeof num); //number
var bn=false;
console.log(typeof bn); //boolean
var a;
console.log(typeof a); //undfined
var obj = null;
console.log(typeof obj); //object
var doc = document;
console.log(typeof doc);//object
var arr = [];
console.log(arr); //object
var fn = function(){};
console.log(typeof fn); //function
除了前四个类型外,null、对象、数组返回的都是object类型;
对于函数类型返回的则是function,再比如typeof(Date),typeof(eval)等。接下来进入正题,
js判断数组类型的方法。
-
方法一: 使用instanceof方法
instanceof 用于判断一个变量是否某个对象的实例,左边操作数是一个对象,右边操作数是一个函数对象或者函数构造器。
原理是通过判断左操作数的对象的原型链上是否具有右操作数的构造函数的prototype属性。
a instanceof b?alert("true"):alert("false")
//注意b值是你想要判断的那种数据类型,不是一个字符串,比如Array。
举一个例子:
var arr=[];
console.log(arr instanceof Array) //返回true
-
方法二: 使用constructor方法
在W3C定义中的定义:constructor
属性返回对创建此对象的数组函数的引用,就是返回对象相对应的构造函数。
从定义上来说跟instanceof不太一致,但效果都是一样的。
那么判断各种类型的方法:
console.log([].constructor == Array); //true
console.log({}.constructor == Object); //true
console.log("string".constructor == String); //true
console.log((123).constructor == Number); //true
console.log(true.constructor == Boolean); //true
注意:
使用instaceof和construcor,被判断的array必须是在当前页面声明的!
比如,一个页面(父页面)有一个框架,框架中引用了一个页面(子页面),
在子页面中声明了一个array,并将其赋值给父页面的一个变量,
这时判断该变量,Array ==object.constructor;会返回false;
原因:
1、array属于引用型数据,在传递过程中,仅仅是引用地址的传递。
2、每个页面的Array原生对象所引用的地址是不一样的,在子页面声明的array,所对应的构造函数,
是子页面的Array对象;父页面来进行判断,使用的Array并不等于子页面的Array。
- 方法三: 使用Object.prototype.toString.call(arr) === '[object Array]'方法
function isArray(o) {
return Object.prototype.toString.call(o);
}
var arr=[2,5,6,8];
var obj={name:'zhangsan',age:25};
var fn = function () {}
console.log(isArray(arr)); //[object Array]
console.log(isArray(obj)); //[object Object]
console.log(isArray(fn)); //[object function]
-
方法四:ES5定义了Array.isArray:
Array.isArray([]) //true
js扩展运算符(spread)是三个点(…)
// ES6 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
合并两个数组并去重(ES5和ES6两种方式实现)
https://blog.youkuaiyun.com/qingmengwuhen1/article/details/79876813
- ES6实现方式
let arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4]
let arr2 = [1, 2, 5, 4, 9, 7, 7, 8, 8]
function uniqueArr(arr1,arr2) {
//合并两个数组
arr1.push(...arr2)
//或者arr1 = [...arr1,...arr2]
//去重
let arr3 = Array.from(new Set(arr1))
//let arr3 = [...new Set(arr1)]
console.log(arr3)
}
uniqueArr(arr1,arr2)
注:new Set()接收一个数组,并且数组中的元素是唯一的。Array.from()能把伪数组转化为真正的数组。
- ES5实现方式1
var arr1 = [1, 1, 2, 3, 6, 9, 5, 5, 4]
var arr2 = [1, 2, 5, 4, 9, 7, 7, 8, 8]
function uniqueArr(arr1, arr2){
var arr3 = arr1.concat(arr2)
var arr4 = []
for(var i=0,len=arr3.length; i<len; i++) {
if(arr4.indexOf(arr3[i]) === -1) {
arr4.push(arr3[i])
}
}
console.log(arr4)
}
uniqueArr(arr1, arr2)
合并多个对象并且去重的2种写法(es6)
let objOne = {a:1};
let objTwo = {b:2};
let objThree = {b:4,c:5};
let obj = Object.assign(objOne,objTwo,objThree);
console.log(obj) // {a:1,b:4,c:5}
let obj1={...objOne,...objTwo,...objThree};
console.log(obj1) // {a:1,b:4,c:5}
什么是事件循环(Event Loop)
执行栈与事件队列
堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。
js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码…,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)”的原因
this指向
-
① this指向的,永远只可能是对象!
-
② this指向谁,永远不取决于this写在哪!而是取决于函数在哪调用。
-
③ this指向的对象,我们称之为函数的上下文context,也叫函数的调用者。
-
通过函数名()直接调用:this指向window
function func(){
console.log(this);
}
//① 通过函数名()直接调用:this指向window
func(); // this--->window
- ② 通过对象.函数名()调用的:this指向这个对象
function func(){
console.log(this);
}
//② 通过对象.函数名()调用的:this指向这个对象
// 狭义对象
var obj = {
name:"obj",
func1 :func
};
obj.func1(); // this--->obj
// 广义对象
document.getElementById("div").onclick = function(){
this.style.backgroundColor = "red";
}; // this--->div
- ③ 函数作为数组的一个元素,通过数组下标调用的:this指向这个数组
function func(){
console.log(this);
}
//③ 函数作为数组的一个元素,
通过数组下标调用的:
this指向这个数组
var arr = [func,1,2,3];
arr[0](); // this--->arr
- ④ 函数作为window内置函数的回调函数调用:this指向window( setInterval setTimeout 等)
function func(){
console.log(this);
}
//④ 函数作为window内置函数的回调函数调用:
this指向window
setTimeout(func,1000);// this--->window
//setInterval(func,1000);
- ⑤ 函数作为构造函数,用new关键字调用时:this指向新new出的对象
function func(){
console.log(this);
}
//⑤ 函数作为构造函数,
用new关键字调用时:
this指向新new出的对象
var obj = new func(); //this--->new出的新obj
几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构?
基本数据类型:Undefined、Null、Boolean、Number、String
值类型:数值、布尔值、null、undefined。
引用类型:对象、数组、函数。
堆栈数据结构:是一种支持后进先出(LIFO)的集合,即后被插入的数据,先被取出!
js数组中提供了以下几个方法可以让我们很方便实现堆栈:
shift:从数组中把第一个元素删除,并返回这个元素的值。
unshift: 在数组的开头添加一个或更多元素,并返回新的长度
push:在数组的中末尾添加元素,并返回新的长度
pop:从数组中把最后一个元素删除,并返回这个元素的值。
const let var
与之相比var let const三种,前者因为var的变量会提升到window,但是let个const不会,let ,const会生成块作用域,同一作用域下let和const不能声明同名变量,而var可以
GET和POST的区别,何时使用POST?
- GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符
- POST:一般用于修改服务器上的资源,对所发送的信息没有限制。
GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值,
也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。
然而,在以下情况中,请使用 POST 请求:
- 无法使用缓存文件(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 没有数据量限制)
- 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
异步加载和延迟加载
- 1.异步加载的方案: 动态插入script标签
- 2.通过ajax去获取js代码,然后通过eval执行
- 3.script标签上添加defer或者async属性
- 4.创建并插入iframe,让它异步执行js
- 5.延迟加载:有些 js代码并不是页面初始化的时候就立刻需要的,而稍后的某些情况才需要的。
17.事件委托?有什么好处?
- (1)利用冒泡的原理,把事件加到父级上,触发执行效果
- (2)好处:新添加的元素还会有之前的事件;提高性能。
防止冒泡和捕获
http://caibaojian.com/javascript-stoppropagation-preventdefault.html
防止冒泡和捕获
w3c的方法是e.stopPropagation(),IE则是使用e.cancelBubble = true
当需要停止冒泡行为时,可以使用
function stopBubble(e) {
//如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
当需要阻止默认行为时,可以使用
//阻止浏览器的默认行为
function stopDefault( e ) {
//阻止默认浏览器动作(W3C)
if ( e && e.preventDefault )
e.preventDefault();
//IE中阻止函数器默认动作的方式
else
window.event.returnValue = false;
return false;
}
取消默认事件
w3c的方法是e.preventDefault(),IE则是使用e.returnValue = false;
//假定有链接<a href="http://caibaojian.com/" id="testA" >caibaojian.com</a>
var a = document.getElementById("testA");
a.onclick =function(e){
if(e.preventDefault){
e.preventDefault();
}else{
window.event.returnValue == false;
}
}
js的对象深拷贝
深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用,
浅复制:只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”。
var json1 = {"a":"李鹏","arr1":[1,2,3]}
function copy(obj1) {
var obj2 = {};
for (var i in obj1) {
obj2[i] = obj1[i];
}
return obj2;
}
var json2 = copy(json1);
json1.arr1.push(4);
alert(json1.arr1); //1234
alert(json2.arr1) //1234
深复制的话,我们要求复制一个复杂的对象,那么我们就可以利用递归的思想来做,及省性能,又不会发生引用。
var json1={"name":"鹏哥","age":18,"arr1":[1,2,3,4,5],"string":'afasfsafa',"arr2":[1,2,3,4,5],"arr3":[{"name1":"李鹏"},{"job":"前端开发"}]};
var json2={};
function copy(obj1,obj2){
var obj2=obj2||{}; //最初的时候给它一个初始值=它自己或者是一个json
for(var name in obj1){
if(typeof obj1[name] === "object"){ //先判断一下obj[name]是不是一个对象
obj2[name]= (obj1[name].constructor===Array)?[]:{}; //我们让要复制的对象的name项=数组或者是json
copy(obj1[name],obj2[name]); //然后来无限调用函数自己 递归思想
}else{
obj2[name]=obj1[name]; //如果不是对象,直接等于即可,不会发生引用。
}
}
return obj2; //然后在把复制好的对象给return出去
}
json2=copy(json1,json2)
json1.arr1.push(6);
alert(json1.arr1); //123456
alert(json2.arr1); //12345
JavaScript原型,原型链 ? 有什么特点?
所有对象都有__proto__属性,prototype属性只有函数对象才有。
每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
于是就这样一直找下去,也就是我们平时所说的原型链的概念。
关系:instance.constructor.prototype = instance.proto
特点:
JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,
就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。 function Func(){}
Func.prototype.name = "Sean";
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();//现在可以参考
var person = Object.create(oldObject);
console.log(person.getInfo());
//它拥有了Func的属性和方法
//"Sean"
console.log(Func.prototype);
// Func { name="Sean", getInfo=function()}
js的面向对象
- 一切事物皆对象
- 对象具有封装和继承特性
- 对象与对象之间使用消息通信,各自存在信息隐藏
面向对象仅仅是一个概念或者编程思想而已,
面向对象的语言最基本的标志就是类的概念。什么是类?类是包含多个属性和方法的集合,类的实例即对象。
js的call,apply,bind的使用与区别
https://www.cnblogs.com/evaling/p/7396253.html
作用:动态改变某个类的某个方法的运行环境。
1)call,apply都是执行某一函数,发现this有变得时候才使用的(进行时)
两者区别仅在于接收参数方式不同,
apply()第一个参数是调用apply的函数运行的作用域,的第二个参数可以是Array的实例(数组),也可以是arguments对象,
call()第一个参数是this的值没有变化,而其余参数都直接传递给函数(也就是逐个列举出来)。
Function.prototype.apply和Function.prototype.call 的作用是一样的,区别在于传入参数的不同;
第一个参数都是,指定函数体内this的指向;
第二个参数开始不同,apply是传入带下标的集合,数组或者类数组,apply把它传给函数作为参数,call从第二个开始传入的参数是不固定的,都会传给函数作为参数。
call比apply的性能要好
如果要传入的是数组或arguments对象,apply会更方便。
2)bind是在函数进行调用之前,就强行给变了this的指向(进行前),它的效果是返回一个函数(只是给变了this指向)
- 一个问题:怎么把call换成apply???
只需要这样: Foo.call(this,name);要被改变成—>Foo.apply(this,[name])…多说一句,applay与call的却别就是applay的参数是一个数组,
flex布局核心:
flex核心主要在轴和容器上做文章
https://segmentfault.com/a/1190000011033230
-
主轴方向:
1.justify-content: -
交叉轴方向:
2.align-items:
js闭包
闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。
闭包是指可以访问另一个函数作用域变量的函数
-
闭包的特性:
- 1.函数内再嵌套函数
- 2.内部函数可以引用外层的参数和变量
- 3.参数和变量不会被垃圾回收机制回收
-
为什么需要闭包?
局部变量无法共享和长久的保存,而全局变量可能造成变量污染,所以我们希望有一种机制既可以长久的保存变量又不会造成全局污染。
-
何时使用?
变量既想反复使用,又想避免全局污染
实例
function getName () {
var name = 'Schopenhauer';
returun function (){
return name
}
}
var b = getName()
console.log( b() ) // Schopenhauer
WEB应用从服务器主动推送Data到客户端有那些方式?
- html5 websoket
- WebSocket通过Flash
- XHR长时间连接
- XHR Multipart Streaming
- 不可见的Iframe
null 与 undefined 的异同点是什么呢?
共同点:都是原始类型,保存在栈中变量本地。
不同点:
(1)undefined——表示变量声明过但并未赋过值。
(2)null——表示一个变量将来可能指向一个对象。
请描述一下 cookies,sessionStorage 和 localStorage 的区别?
cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(通常经过加密)。
cookie数据始终在同源的http请求中携带(即使不需要),记会在浏览器和服务器间来回传递。
sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
存储大小:
cookie数据大小不能超过4k。
sessionStorage和localStorage
比cookie大多,可以达到5M或更大。
有期时间:
localStorage
存储持久数据,浏览器关闭后数据不丢失除非主动删除数据;
sessionStorage
数据在当前浏览器窗口关闭后自动删除。
cookie
设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
什么是Async/Await? es7
http://caibaojian.com/asyncawait.html
- async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
- async/await是基于Promise实现的,它不能用于普通的回调函数。
- async/await与Promise一样,是非阻塞的。
- async/await使得异步代码看起来像同步代码,这正是它的魔力所在。
promise 判断多个请求是否都结束
var p1 = new Promise(function (resolve, reject) {
setTimeout(resolve, 500, 'P1');
});
var p2 = new Promise(function (resolve, reject) {
setTimeout(resolve, 600, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then(function (results) {
console.log(results); // 获得一个Array: ['P1', 'P2']
});
input相关
input 数字类型(number)限制长度
<input type="number" oninput="if(value.length>5)value=value.slice(0,5)">
解决 html5 input type=‘number’ 类型可以输入e
<input type='number' onkeypress='return( /[\d]/.test(String.fromCharCode(event.keyCode) ) )' />
函数节流与函数防抖
函数防抖
debounce-所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行时间。
function debounce(fn) {
var timer
var _self = fn
return function() {
clearTimeout(timer)
var args = arguments // fn所需要的参数
var _me = this // 当前的this
timer = setTimeout(function() {
_self.call(_me, args)
}, 200)
}
}
function resizeDiv() {
var div = document.getElementById('mydiv')
div.style.height = div.offsetWidth + 'px'
console.log('resize')
}
window.onresize = debounce(resizeDiv)
函数节流
throttle-所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
function throttle(fn, interval) {
var _self = fn // 保存需要被延迟执行的函数引用
var firstTime = true // 是否初次调用
var timer // 定时器
return function() {
var args = arguments
var _me = this
if (firstTime) { // 如果是第一次调用不需要延迟执行
_self.call(_me, args)
} if (timer) { // 如果定时器还在,说明前一次延迟执行还没有完成
return false
}
timer = setTimeout(function() { // 延迟一段时间执行
clearTimeout(timer) // 清除定时器 避免下一次return false
timer = null
_self.call(_me, args)
}, interval || 500)
}
}
function resizeDiv() {
var div = document.getElementById('mydiv')
div.style.height = div.offsetWidth + 'px'
console.log('resize')
}
window.onresize = throttle(resizeDiv)
Vue.js面试题整理
一、什么是MVVM?
MVVM是Model-View-ViewModel的缩写。MVVM是一种设计思想。Model 层代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑;View 代表UI 组件,它负责将数据模型转化成UI 展现出来,ViewModel 是一个同步View 和 Model的对象。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
二、mvvm和mvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?
mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
- 区别:vue数据驱动,通过数据来显示视图层而不是节点操作。
- 场景:数据操作比较多的场景,更加便捷
三、vue的优点是什么?
- 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
- 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
- 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
- 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。
四、 组件之间的传值?
-
首选使用Vuex
-
使用事件总线:eventBus,允许组件自由交流
-
父组件与子组件传值
父组件通过标签上面定义传值
这里在父组件使用v-on来监听子组件上的自定义事件($emit的变化),
子组件通过props方法接受数据
- 子组件向父组件传递数据
子组件通过$emit方法传递参数
父组件 .sync 子组件修改父组件的参数,不用调用函数
.sync 修饰符所提供的功能。当一个子组件改变了一个 prop 的值时
,这个变化也会同步到父组件中所绑定
五、路由之间跳转
声明式(标签跳转) 编程式( js跳转)
六、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?
- 第一步:在components目录新建你的组件文件(indexPage.vue),script一定要export default {}
- 第二步:在需要用的页面(组件)中导入:import indexPage from ‘@/components/indexPage.vue’
- 第三步:注入到vue的子组件的components属性上面,components:{indexPage}
- 第四步:在template视图view中使用,
例如有indexPage命名,使用的时候则index-page
七、vue如何实现按需加载配合webpack设置
webpack中提供了require.ensure()来实现按需加载。以前引入路由是通过import 这样的方式引入,改为const定义的方式进行引入。
不进行页面按需加载引入方式:import home from ‘…/…/common/home.vue’
进行页面按需加载的引入方式:const home = r => require.ensure( [], () => r (require(’…/…/common/home.vue’)))
八、vuex面试相关
(1)vuex是什么?怎么使用?哪种功能场景使用它?
vue框架中状态管理。在main.js引入store,注入。新建一个目录store,…… export 。场景有:单页应用中,组件之间的状态。音乐播放、登录状态、加入购物车
(2)vuex有哪几种属性?
有五种,分别是 State、 Getter、Mutation 、Action、 Module
-
vuex的State特性
A、Vuex就是一个仓库,仓库里面放了很多对象。其中state就是数据源存放地,对应于一般Vue对象里面的data
B、state里面存放的数据是响应式的,Vue组件从store中读取数据,若是store中的数据发生改变,依赖这个数据的组件也会发生更新
C、它通过mapState把全局的 state 和 getters 映射到当前组件的 computed 计算属性中
-
vuex的Getter特性
A、getters 可以对State进行计算操作,它就是Store的计算属性
B、 虽然在组件内也可以做计算属性,但是getters 可以在多组件之间复用
C、 如果一个状态只在一个组件内使用,是可以不用getters
-
vuex的Mutation特性
Action 类似于 mutation,不同在于:Action 提交的是
mutation,而不是直接变更状态;Action 可以包含任意异步操作。
(3)不用Vuex会带来什么问题?
可维护性会下降,想修改数据要维护三个地方;
可读性会下降,因为一个组件里的数据,根本就看不出来是从哪来的;
增加耦合,大量的上传派发,会让耦合性大大增加,本来Vue用Component就是为了减少耦合,现在这么用,和组件化的初衷相背。
九、 v-show和v-if指令的共同点和不同点
v-show指令是通过修改元素的display的CSS属性让其显示或者隐藏
v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果
十、 如何让CSS只在当前组件中起作用
将当前组件的
十一、的作用是什么?
包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
十二、Vue中引入组件的步骤?
1)采用ES6的import … from …语法或CommonJS的require()方法引入组件
2)对组件进行注册,代码如下
// 注册
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
3)使用组件
十三、指令v-el的作用是什么?
提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标.可以是 CSS 选择器,也可以是一个 HTMLElement 实例
十四、在Vue中使用插件的步骤
采用ES6的import … from …语法或CommonJS的require()方法引入插件
使用全局方法Vue.use( plugin )使用插件,可以传入一个选项对象Vue.use(MyPlugin, { someOption: true })
十五、请列举出3个Vue中常用的生命周期钩子函数
created: 实例已经创建完成之后调用,在这一步,实例已经完成数据观测, 属性和方法的运算, watch/event事件回调. 然而, 挂载阶段还没有开始, $el属性目前还不可见
mounted: el被新创建的 vm.el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.el 也在文档内。
activated: keep-alive组件激活时调用
十六、active-class是哪个组件的属性?
vue-router模块的router-link组件。
十七、怎么定义vue-router的动态路由以及如何获取传过来的动态参数?
在router目录下的index.js文件中,对path属性加上/:id。使用router对象的params.id。
十八、vue-router有哪几种导航钩子?
第一种:是全局导航钩子:主要有两种钩子:前置守卫、后置钩子,
-
全局前置守卫:router.beforeEach(to,from,next),作用:跳转前进行判断拦截。
-
后置钩子:router.afterEach((to, from) => {});
第二种:组建内的导航钩子
组件内的导航钩子主要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。他们是直接在路由组件内部直接进行定义的
const File = {
template: `<div>This is file</div>`,
beforeRouteEnter(to, from, next) {
// do someting
// 在渲染该组件的对应路由被 confirm 前调用
},
beforeRouteUpdate(to, from, next) {
// do someting
// 在当前路由改变,但是依然渲染该组件是调用
},
beforeRouteLeave(to, from ,next) {
// do someting
// 导航离开该组件的对应路由时被调用
}
}
第三种:路由独享的钩子
顾名思义,即单个路由独享的导航钩子,它是在路由配置上直接进行定义的:
cont router = new VueRouter({
routes: [
{
path: '/file',
component: File,
beforeEnter: (to, from ,next) => {
// do someting
}
}
]
});
十九、VUE生命周期相关面试题
答 : 创建前/后,DOM渲染前/后,更新前/后,销毁前/后;
创建前/后:
beforeCreated:此时的vue实例还没有挂载元素$el,数据对象data也是undefiend;
created:vue实例的数据对象data有了,但是$el还没有
载入前/后:
beforeMount:vue的实例的$el和data都初始化了,但还是挂载在之前虚拟的DOM节点上面,data.message还未
替换
mounted :vue实例挂载完成,data.message成功渲染。
更新前/后
在data发生变化的时候,会触发beforeUpdate和updated方法。
销毁前/后:
在destiory之后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
(1)、什么是vue生命周期
答: Vue 实例从创建到销毁的过程,就是生命周期。
也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,
我们称这是 Vue 的生命周期。
(2)、vue生命周期的作用是什么
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
(3)、vue生命周期总共有几个阶段
答:可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后
(4)、第一次页面加载会触发哪几个钩子
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
(5)、DOM 渲染在 哪个周期中就已经完成
答:DOM 渲染在 mounted 中就已经完成了。
(6)、简单描述每个周期具体适合哪些场景
答:生命周期钩子的一些使用方法:
beforecreate : 可以在这加个loading事件,在加载实例时触发
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
mounted : 挂载元素,获取到DOM节点
updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框
nextTick : 更新数据后立即操作dom
二十、说出至少4种vue当中的指令和它的用法?
v-if:判断是否隐藏;
v-for:数据循环;
v-bind:class:绑定一个属性;
v-model:实现双向绑定
二十一、vue-loader是什么?使用它的用途有哪些?
解析.vue文件的一个加载器。
用途:js可以写es6、style样式可以scss或less、template可以加jade等
二十二、scss是什么?在vue.cli中的安装使用步骤是?有哪几大特性?
答:css的预编译。
使用步骤:
第一步:先装css-loader、node-loader、sass-loader等加载器模块
第二步:在build目录找到webpack.base.config.js,在那个extends属性中加一个拓展.scss
第三步:在同一个文件,配置一个module属性
第四步:然后在组件的style标签加上lang属性 ,例如:lang=”scss”
特性:
可以用变量,例如($变量名称=值);
可以用混合器,例如()
可以嵌套
二十三、为什么使用key?
当有相同标签名的元素切换时,需要通过 key 特性设置唯一的值来标记以让 Vue 区分它们,否则 Vue 为了效率只会替换相同标签内部的内容。
二十四、为什么避免 v-if 和 v-for 用在一起
当 Vue 处理指令时,v-for 比 v-if 具有更高的优先级,通过v-if
移动到容器元素,不会再重复遍历列表中的每个值。取而代之的是,我们只检查它一次,且不会在 v-if 为否的时候运算 v-for。
二十五、VNode是什么?虚拟 DOM是什么?
Vue在 页面上渲染的节点,及其子节点称为“虚拟节点 (Virtual Node)”,简写为“VNode”。“虚拟 DOM”是由 Vue 组件树建立起来的整个 VNode 树的称呼。
二十六、vue-router 实现原理,路由的底层原理?
通过改变浏览器地址URL,在不重新请求页面的情况下,更新页面视图
1.一种是# hash , 在地址中加入#以欺骗浏览器,地址的改变是由于正在进行页内导航
2.一种是h5的history , 使用URL的Hash来模拟一个完整的URL
二十七、聊聊你对Vue.js的template编译的理解?
简而言之,就是先转化成AST树(语法树),再得到的render函数返回VNode(Vue的虚拟DOM节点)
二十八、Vue的双向数据绑定原理是什么?
vue是采用数据劫持,并且使用发布-订阅者的开发模式。原理是观察者observer通过Object.defineProperty()来劫持到各个属性的getter setter,在数据变动的时候,会被observer观察到,会通过Dep通知数据的订阅者watcher,之后进行相应的视图上面的变化
- VUE实现双向数据绑定的原理就是利用了Object.defineProperty()这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的。
- vue数据双向绑定是通过数据劫持Object.defineProperty( )结合发布者-订阅者模式的方式来实现的
二十九、自定义指令,指令函数可接受所有合法的 JavaScript 表达式,以下实例传入了 JavaScript 对象:
<div id="app">
<div v-runoob="{ color: 'green', text: '菜鸟教程!' }"></div>
</div>
<script>
Vue.directive('runoob', function (el, binding) {
// 简写方式设置文本及背景颜色
el.innerHTML = binding.value.text
el.style.backgroundColor = binding.value.color
})
new Vue({
el: '#app'
})
</script>
vue中解决跨域问题(https://www.cnblogs.com/ldlx-mars/p/7816316.html)
-
- 方法1.后台更改header
header('Access-Control-Allow-Origin:*');//允许所有来源访问
header('Access-Control-Allow-Method:POST,GET');//允许访问的方式
-
- 方法2.使用JQuery提供的jsonp ,
jsonp的原理是动态插入script标签
- 方法2.使用JQuery提供的jsonp ,
methods: {
getData () {
var self = this
$.ajax({
url: 'http://f.apiplus.cn/bj11x5.json',
type: 'GET',
dataType: 'JSONP',
success: function (res) {
self.data = res.data.slice(0, 3)
self.opencode = res.data[0].opencode.split(',')
}
})
}
}
-
- 方法3. 代理解决
proxyTable: {
'/api': { //使用"/api"来代替"http://f.apiplus.c"
target: 'http://f.apiplus.cn', //源地址
changeOrigin: true, //改变源
pathRewrite: {
'^/api': 'http://f.apiplus.cn' //路径重写
}
}
}
CSS
CSS选择符有哪些?哪些属性可以继承?
-
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a:hover, li:nth-child)
-
可继承的样式: font-size font-family color, UL LI DL DD DT;
-
不可继承的样式:border padding margin width height ;
请解释一下CSS3的Flexbox(弹性盒布局模型),以及适用场景?
一个用于页面布局的全新CSS3功能,Flexbox可以把列表放在同一个方向(从上到下排列,从左到右),并让列表能延伸到占用可用的空间。
较为复杂的布局还可以通过嵌套一个伸缩容器(flex container)来实现。
采用Flex布局的元素,称为Flex容器(flex container),简称"容器"。
它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称"项目"。
常规布局是基于块和内联流方向,而Flex布局是基于flex-flow流可以很方便的用来做局中,能对不同屏幕大小自适应。
在布局上有了比以前更加灵活的空间。
为什么要初始化CSS样式
-
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
-
当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。
CSS中 link 和@import 的区别是?
- (1) link属于HTML标签,而@import是CSS提供的;
- (2) 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
- (3) import只在IE5以上才能识别,而link是HTML标签,无兼容问题;
- (4) link方式的样式的权重 高于@import的权重.
介绍一下CSS的盒子模型?
-
1)有两种, IE 盒子模型、标准 W3C 盒子模型;IE的content部分包含了 border 和 pading;
-
2)盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border).
CSS 选择符有哪些?哪些属性可以继承?优先级算法如何计算? CSS3新增伪类有那些?
-
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a: hover, li:nth-child) -
可继承的样式: font-size font-family color, text-indent;
-
不可继承的样式:border padding margin width height ;
-
优先级就近原则,同权重情况下样式定义最近者为准;
-
载入样式以最后载入的定位为准;
优先级为:
- !important > id > class > tag
- important 比 内联优先级高,但内联比 id 要高
CSS3新增伪类举例:
- p:first-of-type
选择属于其父元素的首个’p>'元素的每个 ‘p>’ 元素。 - p:last-of-type 选择属于其父元素的最后’ p> ‘元素的每个’ p> '元素。
- p:only-of-type 选择属于其父元素唯一的’ p> '元素的每个 ‘p>’ 元素。
- p:only-child 选择属于其父元素的唯一子元素的每个 ‘p>’ 元素。
- p:nth-child(2) 选择属于其父元素的第二个子元素的每个 ‘p>’ 元素。
- :enabled :disabled 控制表单控件的禁用状态。
- :checked 单选框或复选框被选中。
列出display的值,说明他们的作用。position的值, relative和absolute分别是相对于谁进行定位的?
-
block 象块类型元素一样显示。 inline 行内元素类型一样显示。 inline-block 象行内元素一样显示,但其内容象块类型元素一样显示。 list-item 象块类型元素一样显示,并添加样式列表标记。
-
absolute
生成绝对定位的元素,相对于 static 定位以外的第一个祖先元素进行定位。 -
fixed (老IE不支持)
生成绝对定位的元素,相对于浏览器窗口进行定位。 -
relative
生成相对定位的元素,相对于其在普通流中的位置进行定位。 -
static 默认值。没有定位,元素出现在正常的流中
*(忽略 top, bottom, left, right z-index 声明)。 -
inherit 规定从父元素继承 position 属性的值。
CSS3有哪些新特性?
CSS3实现圆角(border-radius),阴影(box-shadow),
对文字加特效(text-shadow、),
线性渐变(gradient),
旋转(transform)
transform:rotate(9deg)
scale(0.85,0.90)
translate(0px,-30px)
skew(-9deg,0deg);//旋转,缩放,定位,倾斜
增加了更多的CSS选择器 多背景 rgba
在CSS3中唯一引入的伪元素是::selection.
媒体查询,多栏布局
border-image
说说你对语义化的理解?
- 1,去掉或者丢失样式的时候能够让页面呈现出清晰的结构
- 2,有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
- 3,方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
常见兼容性问题?
-
png24位的图片在iE6浏览器上出现背景,解决方案是做成PNG8.也可以引用一段脚本处理.
-
浏览器默认的margin和padding不同。解决方案是加一个全局的*{margin:0;padding:0;}来统一。
-
IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
-
浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。)
#box{ float:left; width:10px; margin:0 0 0 100px;}
这种情况之下IE会产生20px的距离,解决方案是在float的标签样式控制中加入 ——_display:inline;将其转化为行内属性。(_这个符号只有ie6会识别)
- 渐进识别的方式,从总体中逐渐排除局部。
首先,巧妙的使用“\9”这一标记,将IE游览器从所有情况中分离出来。
接着,再次使用“+”将IE8和IE7、IE6分离开来,这样IE8已经独立识别。
css
.bb{
background-color:#f1ee18;/所有识别/
.background-color:#00deff\9; /IE6、7、8识别/
+background-color:#a200ff;/IE6、7识别/
_background-color:#1e0bd1;/IE6识别/
}
-
IE下,可以使用获取常规属性的方法来获取自定义属性,
也可以使用getAttribute()获取自定义属性;
Firefox下,只能使用getAttribute()获取自定义属性.
解决方法:统一通过getAttribute()获取自定义属性. -
IE下,event对象有x,y属性,但是没有pageX,pageY属性;
Firefox下,event对象有pageX,pageY属性,但是没有x,y属性. -
解决方法:(条件注释)缺点是在IE浏览器下可能会增加额外的HTTP请求数。
-
Chrome 中文界面下默认会将小于 12px 的文本强制按照 12px 显示,
可通过加入 CSS 属性 -webkit-text-size-adjust: none; 解决. -
超链接访问过后hover样式就不出现了 被点击访问过的超链接样式不在具有hover和active了解决方法是改变CSS属性的排列顺序:
L-V-H-A : a:link {} a:visited {} a:hover {} a:active {} -
怪异模式问题:漏写DTD声明,Firefox仍然会按照标准模式来解析网页,但在IE中会触发怪异模式。为避免怪异模式给我们带来不必要的麻烦,最好养成书写DTD声明的好习惯。现在可以使用html5推荐的写法:
<doctype html>
-
上下margin重合问题
ie和ff都存在,相邻的两个div的margin-left和margin-right不会重合,但是margin-top和margin-bottom却会发生重合。
解决方法,养成良好的代码编写习惯,同时采用margin-top或者同时采用margin-bottom。 -
ie6对png图片格式支持不好(引用一段脚本处理)
css三角形
div {
width: 0;
height: 0;
border-width: 0 40px 40px;
border-style: solid;
border-color: transparent transparent red;
}
解释下浮动和它的工作原理?清除浮动的技巧
浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。
- 1.使用空标签清除浮动。
这种方法是在所有浮动标签后面添加一个空标签 定义css clear:both. 弊端就是增加了无意义标签。 - 2.使用overflow。
给包含浮动元素的父标签添加css属性 overflow:auto; zoom:1; zoom:1用于兼容IE6。 - 3.使用after伪对象清除浮动。
该方法只适用于非IE浏览器。具体写法可参照以下示例。使用中需注意以下几点。一、该方法中必须为需要清除浮动元素的伪对象中设置 height:0,否则该元素会比实际高出若干像素;
浮动元素引起的问题和解决办法?
浮动元素引起的问题:
- (1)父元素的高度无法被撑开,影响与父元素同级的元素
- (2)与浮动元素同级的非浮动元素会跟随其后
- (3)若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构
解决方法:
使用clear:both;属性来清除元素的浮动可解决2、3问题,
对于问题1,添加如下样式,给父元素添加
.clearfix:after{
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
.clearfix{
display: inline-block;
} /* for IE/Mac */
清除浮动的几种方法:
-
1,额外标签法,
(缺点:不过这个办法会增加额外的标签使HTML结构看起来不够简洁。) -
2,使用after伪类
#parent:after{
content:".";
height:0;
visibility:hidden;
display:block;
clear:both;
}
- 3,浮动外部元素
- 4,设置
overflow
为hidden
或者auto
html5有哪些新特性、移除了那些元素?如何处理HTML5新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
-
HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
-
拖拽释放(Drag and drop) API
语义化更好的内容标签(header,nav,footer,aside,article,section)
音频、视频API(audio,video)
画布(Canvas) API
地理(Geolocation) API
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
sessionStorage 的数据在浏览器关闭后自动删除表单控件,calendar、date、time、email、url、search
新的技术webworker, websocket, Geolocation -
移除的元素
纯表现的元素:basefont,big,center,font, s,strike,tt,u;
对可用性产生负面影响的元素:frame,frameset,noframes;
支持HTML5新标签:
-
IE8/IE7/IE6支持通过document.createElement方法产生的标签,
可以利用这一特性让这些浏览器支持HTML5新标签,浏览器支持新标签后,还需要添加标签默认的样式:
-
当然最好的方式是直接使用成熟的框架、使用最多的是html5shim框架
如何区分: DOCTYPE声明\新增的结构元素\功能元素
如何实现浏览器内多个标签页之间的通信?
调用localstorge、cookies等本地存储方式
你如何对网站的文件和资源进行优化?
期待的解决方案包括:
文件合并
文件最小化/文件压缩
使用 CDN 托管
缓存的使用(多个域名来提供缓存)
其他
请说出三种减少页面加载时间的方法。
- 1.优化图片
- 2.图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)
- 3.优化CSS(压缩合并css,如margin-top,margin-left…)
- 4.网址后加斜杠(如www.campr.com/目录,会判断这个“目录是什么文件类型,或者是目录。)
- 5.标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。
当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了。) - 6.减少http请求(合并文件,合并图片)。
你都使用哪些工具来测试代码的性能?
Profiler, JSPerf(http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout), Dromaeo
面试题 链接
https://blog.youkuaiyun.com/keyandi/article/details/89227175