作者主页:仙女不下凡
学习建议:以下 内容不建议死记硬背,而且内容太多也记不住,建议了解链接里面的详情解释之后在理解我总结的面试回答,相信看到这篇文章的小伙伴相当一部分是没有工作经验的初学者,所以我会简单提到这些知识点什么时候使用,因为个人开发经验不算丰富总结内容常有不全,欢迎指正修改!
欢迎点赞 收藏⭐ 留言 如有不足与错误敬请指正!
✨ 重点理解: 盒模型分为标准盒模型与IE
盒模型,元素在网页实际占位为content + padding + border + margin
,标准盒子模型与低版本IE盒子模型区别就是取宽高的时不同,标准盒模型宽高指content
的宽高;低版本IE盒子模型宽高指content + padding + border
。
问题拓展: CSS 如何设置这两种模型? 标准盒模型(默认)box-sizing : content-box;
IE
盒模型box-sizing : border-box
。
问题拓展: CSS水平居中+垂直居中+水平/垂直居中的方法总结
✨ 重点理解: 增加了❶新语义元素(新标签和新属性,如
) ❷加强本地存储(增加了sessionStorage
与localStorage
等) ❸表单新增功能(from
) ❹css3
等。
详情文章: h5新特性有哪些
✨ 重点理解: H5
能够本地存储数据,在之前都是使用cookies
使用的。H5
提供了下面两种本地存储方案: localStorage
( 用于持久化的本地存储,数据永远不会过期,关闭浏览器也不会丢失)与sessionStorage
(同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage
不是一种持久化的本地存储,仅仅是会话级别的存储)。
✨ 重点理解: 我们记住几个吧,如XMLHttpRequest
对象:H5
标准新增了更多的属性和方法和事件;多媒体Media API
等等,很多很多。
✨ 重点理解: 应用程序缓存是H5
的重要特性之一,提供了离线使用的功能,提高网站性能,让应用程序可以获取本地的网站内容,例如HTML、CSS、
图片以及JavaScript
。
✨ 重点理解: px
是绝对长度,而em rem vh vw
都是相对长度,rem em
区别:rem
只能在html
标签里面设置rem
的依赖的值到底是多少,而em
是可以在自己元素以及父级元素设置em
依赖的值到底是多少。vh
和vw
:就是根据窗口的宽高,分成100等份,100vh
就表示满高,50vh
就表示一半高。
width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。当然,初始化样式会对SEO有一定的影响,但鱼和熊掌不可兼得,但力求影响最小的情况下初始化。
1.父级div定义height
原理:父级div手动定义height,就解决了父级div无法自动获取到高度的问题
优点:简单,代码少,容易掌握
缺点:只适合高度固定的布局,要给出精确的高度,如果高度和父级div不一样时,会产生问题。
建议:不推荐使用,只建议高度固定的布局时使用
2.最后一个浮动元素后加空 div 标签 并添加样式 clear:both。(理论上能清除任何标签,增加无意义的标签)
3.包含浮动元素的父标签添加样式 overflow 为 hidden 或 auto。
4.父级 div 定义 zoom(空标签元素清除浮动而不得不增加无意义代码的弊端,使用zoom:1用于兼容IE)
5.用after伪元素清除浮动(用于非IE浏览器)
该布局模型的目的是提供一种更加高效的方式来对容器中的条目进行布局、对齐和分配空间。在传统的布局方式中,block 布局是把块在垂直方向从上到下依次排列的;而 inline 布局则是在水平方向来排列。弹性盒布局并没有这样内在的方向限制,可以由开发人员自由操作。
试用场景:弹性布局适合于移动前端开发,在Android和ios上也完美支持。
✨ 总结理解: 先设置主轴(横向或纵向),再设置排列方式。
前言: 学习JavaScript
之前我建议要把他的技术发展的时间线做一个大概的了解。下图是我在之前文章的总结截图,我们知道ES5
是05年版本
的统称,ES6
是15年版本
所有版本的统称,下面的面试题我尽量按照ES5
与ES6
两版不同对比总结。
✨前端学习笔记-javascript,完整版
✨ 在ES5
版本中有6种数据类型▶️基本数据类型Undefined、Null、Boolean、Number、String
,▶️复杂数据类型Object
。
详解文章:js的基本数据类型有哪些?
✨ ES6
之后引入两种新数据类型Symbol
与bigInt
。
详情文章:
详情文章:js中数组操作方法整理
✨ 重点看遍历数组的方式与数组去重的方法。
✨ 重点理解: 操作对象的方法很多,建议记住几个常用的方法即可。其中apply、call、bind
是改变this
指向的方法,此处也是一个面试常见题目。
✨ 重点理解: ⑴ 改变this
指向apply、call、bind
三种方法的区别?⑵ this
指向window
有哪些?⑶ 哪些实际应用:其实在实际开发中并不算是常用与常用的数据操作方法使用频率相差很多,但是比如在某个方法中想调用其他方法或者数据会使用。
详情文章:this、apply、call、bind
✨ 重点理解: typeof()、instanceof()
这两个方法常用,instanceof()
是ES6
方法,在实际项目中很少直接使用,那什么时候用呢?一般都是不确定后台返回什么数据类型时打印一下到底返回了什么,比如console.log(typeof(xxx))
。
✨ 总结理解: 调用new
构造函数例var obj = new Base();
这样代码的结果是什么?new
操作符具体干了什么呢?其实很简单就干了三件事情。❶ var obj = {};
创建一个新对象 ❷obj.__proto__ = Base.prototype;
❸Base.call(obj);
新对象的_proto_
属性指向构造函数的原型对象,同时返回新对象obj
,所以构造函数中不用return
值。
详情文章:js中的new关键字都干了些什么?
✨ 总结理解: 在4.new操作符
中相信有人对于function Base(){放了一堆方法}; obj.__proto__ = Base.prototype;
不理解,其实这部分也是JavaScript
中的原型链知识点、非常重要,一句话总结 prototype是函数才有 的属性实际使用时有一些组件或整个项目常用的方法会放在里面;而 __proto__是每个对象都有的属性 (但是万物皆对象,所以__proto__
谁都有)。
详情文章:__proto__与prototype
✨ 重点理解:
详情链接:
5.浏览器如何渲染页面的?
6.http请求
✨ 重点理解: 这个问题很简单for…in
和for…of
都是循环数据使用,不同的是for…in
循环的是键名,for...of
循环的是键值。
const arr = ['a', 'b', 'c']
for (let i in arr) {
console.log(i)
}; /执行结果为0 1 2/
for (let i of arr) {
console.log(i)
}; /执行结果为a b c/
但是for...in
有一种特殊情况
const arr = ['a', 'b', name:'qiqingfu']
for (let i in arr) {
console.log(i)
}; /执行结果为a b name/
✨ 重点理解: ES6
引入了两个新的数据结构:▶️Set
与▶️Map
。
➡️Set
数据容器是一个能够存储无重复值的有序列表。
let set = new Set([1,2,3,3,3,3]);
console.log(set.size); /执行结果为3, 因为重复的值去除了, 所以set数组中只有3个变量长度为3/
➡️Map
数据结构类似于对象,也是键值对的集合。“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说Object
结构提供了“字符串—值”的对应,Map
结构提供了“值—值”的对应,是一种更完善的Hash
结构实现。如果需要“键值对”的数据结构,Map
比Object
更合适。Map
的键是跟内存地址绑定的,只要内存地址不一样,就可视为两个键。这样解决了同名属性碰撞(clash)的问题,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。
详情链接: 深入理解ES6–7.Set和Map
详情链接: JavaScript中Map的用途是什么?
✨ 重点理解: 这个概念我其实在实际项目中基本没有用到过,不过也是面试的知识点。
详情链接:前端必知必会ES5、ES6的7种继承
✨ 重点理解:
详情链接:
✨ 重点理解:
详情链接:
✨ 重点理解: 我在刚刚接触这个方法的时候一直有个疑问,为什么要用这个方法,这不是更加不方便了么,后来慢慢理解了,这个方法可以限制加入的数据是否可以遍历、是否可以删除等。
详情链接:深入浅出Object.defineProperty()
✨ 重点理解: Proxy
对象是ES6
引入的新知识点,建议结合Object.defineproperty()
与vue
框架的双向数据绑定一起理解。
详情链接:详解es6中Proxy代理对象的作用
详情链接:面试官: 实现双向绑定Proxy比defineproperty优劣如何?
✨ 重点理解: 关于防抖节流的应用,其实在实际应用中发生滚动事件、input
事件、页面resize
事件等较常遇到,➡️防抖含义是对于短时间内连续触发的事件,让某个时间期限内,事件处理函数只执行一次;➡️节流含义是对于短时间内连续触发的事件,让某个时间期限内,事件处理函数每定期执行一次;
➡️防抖和节流的区别: 防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行。
详情链接:浅谈 JS 防抖和节流
☃️☃️☃️ 前言: 既然我们是前端开发那就势必要与后端配合,来请求后台的服务器的数据,这时候就是网络http
出场的时间了,个人建议在看该面试题之前建议先将http
基础复习一遍,方便了解下面的面试题以及总结的答案。前端工程师必须要知道的HTTP部分。
✨ 重点理解: 我们在前言复习时了解到,http
请求方式不止GET
与POST
,还有PUT
等其他请求方式,但是不作为重点了解。
✨ 面试时回答3点我认为足够了!!!
❶GET
比POST
不安全,因为GET
提交的数据放在URL
中,POST
则不是(POST
也不安全,因为HTTP
是明文传输抓包就能获取数据内容,要想安全还得加密)。
❷GET
回退浏览器无害,POST
需要再次提交请求(GET
有缓存中拿结果,POST
没缓存)。
❸GET
和POST
还有一个重大区别,简单的说:GET
产生一个TCP
数据包,POST
产生两个TCP
数据包。换句话说:对于GET
方式的请求,浏览器会把http header
和data
一并发送出去,服务器响应200(返回数据),而对于POST
,浏览器先发送header
,服务器响应100 continue
,浏览器再发送data
,服务器响应200 ok
(返回数据)。也就是网络请求的两次握手,我记得在哪见过解释。
详情链接:你敢在post和get上刁难我,就别怪我装逼了
✨ 重点理解: 又上一个面试题我们知道,在实际开发中前端展示的数据大都是通过http
网络请求后后台服务器返回的数据,所以这就引出了Cookies、Session、SessionStore、LocalStore
这几个浏览器的缓存机制,来保存必要的数据,这样就大大的减少了请求次数!
详情链接:Cookie、session和localStorage、以及sessionStorage之间的区别
https 的握手过程
✨ 重点理解:
详情链接:
2.ajax中get和post请求的区别
3.如何解析json数据:JSON.parse()
4.Promise异步函数
再看这些面试题之前,希望了解一些基本概念,什么是Vue实例,什么是Vue组件,什么是$el,路由,基本的javascript语法等。如果时间充足建议花两个星期的时候研读下面的笔记已经对应的视频,很多问题就可以迎刃而解了。
前端学习笔记____Vue2+Vue3全家桶
浅谈Vue构造、Vue实例、Vue组件的区别
使用 v-cloak 解决,它是是一个特殊属性,Vue 实例创建完毕并接管容器后,会散删掉v-cloak属性;使用 css 配合 v-cloak 可以解决网速慢时页面展示出 {{xxx}} 的问题。
<h2 v-cloak>{{name}}h2>
/如果不加v-cloak页面会显示{{name}},5秒之后插值表达式才会解析/
el 的两种写法
<head>
<script text="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">容器div>
body>
<script type="text/javascript">
const vm = new Vue({
el: '#root', /第一种写法,直接与容器关联/
data: {},
})
script>
<head>
<script text="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">容器div>
<script type="text/javascript">
const vm = new Vue({
data: {},
});
vm.$mount('#root'); /mount挂载,写法灵活,比如可以加定时器控制执行时间/
script>
body>
data 的两种写法
<head>
<script text="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">容器div>
body>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: {}, /第一种写法,对象式/
})
script>
<head>
<script text="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">容器div>
body>
<script type="text/javascript">
const vm = new Vue({
el: '#root',
data: function(){ /第二种 函数式,function可以省略,组件必须使用函数式/
return: 'xxx',
},
})
script>
思考:为什么组件中 data 必须使用函数式写法?这个也是一个面试题。
key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速。
虚拟DOM中key的作用:key是虚拟DOM对象的标示,当数据发生变化时,Vue会3据新数据生成新的虚拟DOM,随后Vue进行新虚拟DOM与旧虚拟DOM的差异比较。比较规则如下:
对比规则:❶旧虚拟DOM中找到了与新虚拟DOM相同的key;若虚拟DOM中内容没变,直接使用之前的真实DOM;若虚拟DOM中内容变了,则生成新的真实DOM,随后替换掉页面中之前的真实DOM。❷旧虚拟DOM中未找到与新虚拟DOM相同的key创建新的真实DOM,随后渲染到页面。
用index作为key可能会引发的问题:❶若对数据进行:逆序添加、逆序删除破坏操作( 会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低 )。⑵如果结构中还包含输入类的DOM( 会产生错误DOM更新 ==> 界面有问题 )。
开发中如何选择key?
❶最好使用每条数据的唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。❷如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
示例代码如下
/需求1: 定义一个v-big指令,与v-text类似但是会把绑定的数值放大10倍/
/需求2: 定义一个v-fbind指令,与v-bind类似但可以让其所绑定的input元素默认获取焦点/
<body>
<div id="root">
<h2>当前的n值是:<span v-text="n">span> h2>
<h2>放大10倍后的n值是:<span v-big="n">span> h2>
<button @click="n++">点我n+1button> <hr/>
<input type="text" v-fbind:value="n">
div>
body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: '#root'
data: { n:1 },
/局部自定义指令/
directives: {
/两种方式,第一写成对象big:{}(完整),第二种写成函数big(){}/
big(element,binding){ /element是真实DOM元素,binding是一个对象存各种信息/
element.innerText = binding.value * 10;
},
fbind:{ /包含3个钩子函数/
console.log(this); /注意此处的this指向window/
bind(element,value){ element.value = binding.value }, /指令与元素成功绑定时调用/
inserted(element,value){ element.focus() }, /指令所在元素被插入页面时调用/
upddate(element,value){ element.value = binding.value } /指令所在的模板被重新解析时调用/
}
},
})
script>
局部指令 new Vue({ directives:{指令名:配置对象} })
或 new Vue({ directivea(){} })
全局指令Vue.directive(指令名, 配置对象)
或 Vue.directive(指令名, 回调函数)
。
配置对象中常用的3个钩子函数:
❶ bind 指令与元素成功绑定时调用
❷ inserted 指令所在元素被插入页面时调用
❸ update 指令所在模板结构被重新解析时调用。
⚠️指令定义时不加 v-,但使用时要加 v- ;指令名如果是多个单词,要使用 kebab-case 命名方式,不要用 camelCase 命名。
✨总结理解: 先了解什么是 SAP 单页面应用,用一句话总结就是整个应用只有一个完整页面,点击页面中的导航只做局部刷新,如下图。
详解文章:
✨总结理解: Vue 参考了该 MVVM 模型,在 Vue 之前就有 MVVM 的模型理念。一句话就是:数据改变视图,视图影响数据。
M模型(Model): 对应data中的数据;V视图(View): 模板;VM视图模型(ViewModel): Vue实例对象。❶data(即M模型)中所有的属性,最后都出现在了vm身上;❷另外vm身上所有的属性及Vue原型上所有属性,在Vue模板中都可以直接使用。
✨总结理解: 其实双向数据绑定分为两种:Vue2.x底层语法是 Object.defineProperty(),Vue3.1是Proxy,这个也衍生出他们两个的区别或者说,3.X版本有什么优点,可以自行思考一下。通过这个话题其实可以衍生出 Proxy 与 Object.defineProperty 优劣对比(ES6)语法?与 JavaScript 部分呼应。
详解文章:Vue 是如何实现数据双向绑定的?
✨总结理解: 一句话概括就是,绑定数据并且监听数据改变。v-model 是:value="msg" @input="msg=$event.target.value"
的语法糖,其中:value="msg"
是绑定了数据,value 就是 input 输入框里的值;@input="msg=$event.target.value"
就是监听 input 输入框里值的变化,然后改变值。
详解文章: 你知道v-model的原理吗?说说看
✨总结理解:
详解文章:
✨总结理解: v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件。v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 “display” 属性进行切换。所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。
详解文章:
✨总结理解: Vue 实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载 Dom->渲染、更新->渲染、卸载等一系列过程,即 Vue 的生命周期。我们要知道 Vue 实例生命周期有8个,但是 keep-alive 有两个专属的生命周期,详解如下图。
生命周期 | 详解 |
---|---|
beforeCreate | 组件实例被创建之初,组件的属性生效之前 |
created | 组件实例已经完全创建,属性也绑定,但真实 dom 还没有生成,$el 还不可用 |
beforeMount | 在挂载开始之前被调用:相关的 render 函数首次被调用 |
mounted | el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子 |
beforeUpdate | 组件或实例数据更新之前调用,发生在虚拟 DOM 打补丁之前 |
update | 组件或实例数据更新之后 |
activited | keep-alive 专属,组件被激活时调用 |
deactivated | keep-alive 专属,组件被销毁时调用 |
beforeDestory | 组件或实例销毁前调用 |
destoryed | 组件或实例销毁后调用 |
详解文章: |
/绑定class样式--字符串写法,适用于:样式的类名不确定,需要动态指定/
<div class="basic" :class="mood" @click="changeMood">{{name}}div><dr/>
/绑定class样式--数组写法,适用于:要绑定的样式个数和名字不确定/
<div class="basic" :class="classArr">{{name}}div><dr/>
/绑定class样式--对象写法,适用于:要绑定的样式个数和名字确定,但是要动态决定用不用/
<div class="basic" :class="classObj">{{name}}div><dr/>
<div class="basic" :style="{fontSize: fsize+'px'}">{{name}}div>
/绑定style样式--数组写法/
<div class="basic" :style="styleObj">{{name}}div>
/绑定style样式--对象写法/
<div class="basic" :style="styleArr">{{name}}div>
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
props: ['initialCounter'],
props: ['size'],
✨总结理解: 关于 this 指向:①组件配置中data函数、methods中的函数、computed中的函数它们的this指向均是【VueComponent实例对象】②new Vue()配置中data函数、methods中的函数、computed中的函数它们的this指向均是【Vue实例对象】。
✨总结理解: router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等
详解文章: vue2.0中的$router 和 $route的区别
✨总结理解: vue-router 有 3 种路由模式:hash、history、abstract
详解文章:vue-router路由模式有几种?
✨总结理解: 先理解hash 与 history 是什么?他们其实是路由的两种工作模式。vue默认为 hash 模式,转变为 history 模式方式如下图。▶️1. hash模式:❶地址中永远带着#号,不美观;❷若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合适;❸兼容性好。▶️2. history模式:❶地址干净,美观;❷兼容性和hash模式相比略差;❸应用部署上线时需要后端人员支持,解决刷新页面服务端404问题。
详解文章: 能说下 vue-router 中常用的 hash 和 history 路由模式实现原理吗?
✨总结理解: keep-alive 其实就是缓存路由组件,可以不使用,使用之后的优点是:让不展示的路由组件保持挂载,不被销毁,使用方法如下
<--⚠️如不写include属性,代表所有的router-view中所有层级都缓存不销毁 -->
<router-view>router-view>
keep-alive>
详解文章: 谈谈你对 keep-alive 的了解?
✨总结理解: 加载渲染过程:父beforeCreate => 父created => 父beforeMount => 子beforeCreate => created => 子beforeMount => 子mounted => 父mounted
;子组件更新过程:父beforeUpdate => 子beforeUpdate => 子updated => 父updated
;父组件更新过程:父beforeUpdate => 父updated
;销毁过程:父beforeDestroy => 子beforeDestroy => 子destroyed => 父destroyed
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。vue 具体的生命周期示意图可以参见如下,理解了整个生命周期各个阶段的操作,关于生命周期相关的面试题就难不倒你了。
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
✨总结理解:
详解文章:
内置关系VueComponent.prototype.proto === Vue.prototype
✨总结理解: 可以。有两种方法:1.在父组件中定义一个事件,在子组件中用$emit
去触发。2.父组件引用子组件时,给父组件添加@hook
来监听。其它的生命周期事件,例如:created,updated 等都可以监听。
详解文章:父组件可以监听到子组件的生命周期吗?