CSS 相关
圣杯和双飞翼
都是用float实现布局的,都是两边宽度固定,中间自适应的三栏布局,中间栏始终放在最前面优先渲染。
-
圣杯:左中右三个盒子在同一个盒子中,中间盒子设置左右padding值留给左右两个盒子,左右两个盒子通过position:relative设置left和right属性,以便不遮挡中间的盒子。
- 优点:少一层dom;
- 缺点:当页面拉伸或者中间的盒子宽度小于左边盒子宽度时,会布局混乱。
-
双飞翼:左中右三个盒子也在同一个盒子中,但中间盒子需要再加一个子盒子,设置子盒子的左右margin值给左右两边的盒子留出位置。
- 优点:不会因为拉伸等情况造成布局问题;
- 缺点:多一层dom.
元素的居中方式 (问了)
/* margin 居中对齐 */
margin:0 auto;
/* flex 水平垂直居中 */
display:flex;
justify-content:center;
align-item:center;
/* position 水平垂直居中 */
Position:absolute;
left:50%;
top:50%;
transform:translate(-50%,-50%);
JS 相关
数据类型 (问了)
-
基本数据类型:string,boolean,number,null,undefined,symbol
-
引用数据类型:object,function等
-
symbol 表示独一无二的值,最大的用法就是定义对象的唯一属性名。
es6的5种去重方式 (问了)
- 利用set和array.from()去重
let arr = [1,1,2,3,4,2,3,5,undefined];
let newArr = Array.from(new Set(arr));
console.log(newArr);
- 利用Set和扩展运算符去重
let arr = [1,1,2,3,4,2,3,5,undefined];
let newArr = [...new Set(arr)];
console.log(newArr);
- 利用单层循环和indexOf去重
let arr = [1,1,2,3,4,2,3,5,undefined];
let newArr = [];
for(let i=0;i<arr.length;i++){
if(newArr.indexOf(arr[i])===-1){
newArr.push(arr[i])
}
}
console.log(newArr);
- 利用单层循环和includes去重
let arr = [1,1,2,3,4,2,3,5,undefined];
let newArr = [];
for(let i=0;i<arr.length;i++){
if(!newArr.includes(arr[i])){
newArr.push(arr[i])
}
}
console.log(newArr);
- 利用数组的filter去重
let arr = [1,1,2,3,4,2,3,5,undefined];
let newArr = arr.filter(item,index=>{
return arr.indexOf(item,0) === index;
})
console.log(newArr)
闭包
一个函数的返回值是一个函数,如果这个返回的函数调用了父函数内部的变量,并且被外部调用了,就形成了闭包。
一般应用在返回值,函数赋值,自执行函数等。
promise,promise.all,promise.race (问了)
promise 是es6的特性,通常是异步的一种解决方案。
promise 有三种状态:
-
pending:初始化状态
-
fulfilled:已完成状态
-
rejected:已拒绝状态
promise 有两个过程:
-
pending => resolved (已完成)
-
pending => rejected (已拒绝)
只要promise一旦开始,无论怎么样,状态都无法被改变。
优点:
-
promise 将异步操作已同步的方式展示出来,避免的层层嵌套,更清晰,代码更优雅;
-
promise 对象提供统一的接口,使控制异步操作更容易。
缺点:
-
无法取消promise,一旦开始立即执行,中途无法取消;
-
如果不设置回调函数,结果无法被抛出;
-
当处于pending阶段时,无法知道目前正处于哪一个阶段,直到结束。
promise.all 将多个promise实例组合成一个新的实例,成功的时候返回一个成功的数组,失败的时候返回最先被返回的rejected的值。
promise.race 有点赛跑的意思,也就是哪一个最先完成就返回哪一个,不管是成功,还是失败。
Vue 相关
为什么data是一个函数
组件中的data写成一个函数,以返回值的形式定义,这样每复用一次组件,就行形成一个新的data,而写成一个对象的话,那就共用同一个data,就会造成一个变了所有的都会变的结果。
vue 生命周期 (问了)
-
create阶段:beforeCreate:vue实例创建之前,create:vue实例创建完成,data中有值,未挂载,可以将数据请求放在这个阶段;
-
mount阶段:beforeMount:dom 挂载之前,mounted:dom 挂载完成,可以操作dom;
-
update阶段:当data数据变化时,会出发beforeUpdate和updated;
-
destroy阶段:当vue实例被销毁的时候发生,beforeDestroy,销毁之前,可以清除定时器或者一些需要手动销毁的方法,destroyed:vue实例已经被销毁了。
组件之间的传值 (问了)
-
父传子:父组件给子组件传的值,子组件通过props接收;
-
子传父:子组件用emit给父组件传值,父组件用@方法名来接收;
-
亲兄弟传值:通过公共的父组件,用父子,子父的方式进行传值;
-
非亲兄弟:创建一个中间组件,用on,进行传值和接受;
-
祖孙传值:provide/inject
v-if 和 v-show (问了)
v-if 通过控制dom实现显示和隐藏,所以会不停的销毁和创建,v-show 通过控制css中的display完成显示和隐藏的效果,只编译一次。通常日常判断显示和隐藏用v-show,一般带权限的判断用v-if多一些。
v-if 和 v-for 为什么不建议一起用 (问了)
v-for 的优先级高于v-if,如果一起用的话,每一次遍历都会执行一次v-if,比较消耗性能,可以在v-for的外层加一层template,在template上使用v-if,也可以在computed中完成v-if的判断,将其替换掉。
v-for中key的作用 (问了)
key的作用是在diff算法执行时能够更快的找到对应的节点,提高diff的效率,更高效的更新虚拟dom。
key 应该是唯一的,如果不设置key,则值就是undefined,或者key设置成相同的,vue会认为两个节点是同一个,会频繁的更新元素,影响性能。
通常情况下,用唯一的id设置key,不建议使用index下标,如果使用index,当删除或者新增了元素,那所有的key值都会发生变化。
怎样理解Vue的数据单向流
在Vue中,数据总是从父组件传到子组件的,子组件没有权利修改父组件传过来的值,只能通过调用父组件的方法来修改原始数据,这样可以防止因为子组件误操作改变父组件的状态,从而使数据流向难以理解,如果一定要修改父组件传过来的props的值,可以在data中重新定义一个变量,将props的值作为初始值,再用$emit通知父组件对原数据进行修改。
watch和computed的区别
-
watch:属性监听,第一个参数是最新的值,第二个参数是改变之前的值,watch不支持缓存,当监听的属性值发生改变时,它就会触发相应的操作,watch支持异步操作。
-
computed:计算属性,支持缓存,当依赖发生改变的时候,才会重新计算,仅支持同步操作。当返回值是函数的时候,默认进行的是get方法,还有一个set,当数据变化的时候,调用set方法。
-
当一个属性受多个属性影响时,一般写在computed中,比如购物车结算,当一个数据影响多个数据的时候,一般用watch,比如搜索
Vue 的双向绑定原理 (问了)
整体思路:数据劫持+观察者模式
使用 Object.defineProperty() 的方法对已存在的属性劫持。当页面使用对应的属性时,每个属性都会有属于自己的dep属性,存放在它所依赖的watcher中,当属性变化时就会通知对应的watcher去更新。
Vuex (问了)
Vuex 是专为vue设计的状态管理模式+库,每一个vuex的核心就是store(仓库);
Vuex 是响应式的,当组件从store中读取状态的时候,如果状态更新了,那相应的组件也会得到更新;
Vuex 的几大状态:
-
state:定义应用中的状态数据;
-
getter:store 中的 getter,相当于store中的计算属性,getter的返回值会根据它的依赖被储存起来,只有当发生改变的时候才会更新;
-
mutation:是store中唯一可以更改状态的属性,mutation中的操作必须是同步的。
-
action:相当于mutation,但只能用来提交mutation,不能直接更改的状态,可以进行所有的异步操作。
-
module:可以将一个store分割成多个store,每个store都可以有自己的一套state、getter、mutation、action。
虚拟DOM
在浏览器中频繁的操作dom,会造成一定的性能问题,这也是虚拟dom出现的原因,虚拟dom的本质就是用原生js对象去描述真实dom节点,是对真实domd的抽象。
优点:保证了性能下限,不用手动操作dom,更方便跨平台操作。
缺点:无法进行极致优化。
v-model 的原理
v-model只是一个语法糖而已,它的本质就是为不同的输入元素用不同的property并抛出不同的事件。
-
text和textarea 使用 value property 和 input 事件;
-
checkbox和radio 使用 checked property 和 change 事件;
-
select 使用value作为prop ,change 作为事件;
Vue 事件绑定原理
原生事件绑定通过addeventlistenter绑定给真实元素的,组件是通过自定义$on实现的。
说出至少vue 3个常用事件修饰符
-
:stop 阻止点击事件冒泡
-
:prevent 阻止默认事件
-
:once 只执行一次
-
:self 只在元素本身触发
父子组件生命周期顺序
父beforeCreate => 父created => 父beforeMount => 子beforeCreate => 子created => 子beforeMount => 子mounted => 父mounted
更新:父beforeUpdate => 子beforeUpdate => 子updated => 父updated
路由的两种模式 (问了)
- hash模式
- history模式
vue项目性能优化 (问了)
- 编码阶段
- 尽量减少data中的数据,data中的数据都会增加getter和setter,会收集对应的watcher
- v-if和v-for不能连用
- 如果需要使用v-for给每项元素绑定事件时使用事件代理
- SPA 页面采用keep-alive缓存组件
- 在更多的情况下,使用v-if替代v-show
- key保证唯一
- 使用路由懒加载、异步组件
- 防抖、节流
- 第三方模块按需导入
- 长列表滚动到可视区域动态加载
- 图片懒加载
- SEO优化
- 预渲染
- 服务端渲染SSR
- 打包优化
- 压缩代码
- Tree Shaking/Scope Hoisting
- 使用cdn加载第三方模块
- 多线程打包happypack
- splitChunks抽离公共文件
- sourceMap优化
- 用户体验
- 骨架屏
- PWA
- 还可以使用缓存(客户端缓存、服务端缓存)优化、服务端开启gzip压缩等。