1. 请简单叙述Vue2和Vue3的区别和变化至少说6点?
- 数据绑定的原理发生了变化:vue2中使用了object.definedProperty(),vue3中使用proxy对数据代理。
- 建立数据发生了变化:vue2把数据放在data中,vue3把数据放在setup中。
- 是否支持碎片化:vue2.0只允许有一个根标签,vue3.0支持碎片化,可以拥有对多个根节点。
- composition API:vue2中采用的是选选项式api,vue3采用的是组合式api
- 生命周期的不同:vue3在组合式API中使用生命周期钩子函数的时候,使用的时候需要引入,vue中可以直接使用生命周期钩子函数。
- main.js文件不同:vue2中我们可以使用pototype的形式进行操作,引入的是构造函数,vue3中需要使用结构的形式进行操作,引入的是工厂函数。
2. Vue3中组件通信的方法有些?
- props:父组件以数据绑定的形式声明要传递的数据,子组件通过defineProperty方法创建props对象,就能拿到父组件传递过来的数据。
父组件 <!-- list是我们要传递的数据 --> <child-components :list="list"></child-components>
子组件 <template> <ul> <li v-for="i in props.list" :key="i">{{ i }}</li> </ul> </template> <script setup> import { defineProps } from 'vue' const props = defineProps({ list: { type: Array }, }) </script>
- emit方式:是vue中最常见的组件通信方式,该方式用于子传父;
子组件 const emits = defineEmits(['add']) emits('add', 1)
父组件 <!-- add是子组件要传递的动作,handleAdd是监听到之后执行的事件 --> <child-components @add="handleAdd"></child-components> <script> const list = ref([1,2,3]) const handleAdd = value => { list.value.push(value) } </script>
v-model方式 不能严格的作为数据传递的方式,只是减少了代码量。
<ChildComponent v-model:list="list" /> // 等价于 <ChildComponent :list="pageTitle" @update:list="list = $event" />
//子组件需要emit一个叫update:xxx的事件,再把需要更新的响应式数据传给emit方法的第二个参数即可 const emits = defineEmits(['update:list']) emits('update:list', arr)
- provide/inject就是在父组件中通过provider来提供变量,然后在子组件中通过inject来注入变量,实现祖和后代组件间通信
父组件有一个provide选项提供数据,后代组件有一个inject选项来开始使用这些数据。
provide(第一个参数是要注入的key,它可以是一个字符串或一个symbol;第二个参数是要注入的值(具体要传递给子孙组件的数据)。
import {reactive,provide} from "vue"; let person = reactive({name: '张三',age: 14}); provide('person',person);
inject()函数
定义: 注入一个由祖先(父)组件或整个应用提供的值
实现: 接收父(祖)组件传递过来的值.
nject(第一个参数,第二个参数(可选)):第一个参数是注入的key,来自父(祖)组件,它们两者是需要保持一致的
Vue会遍历父组件链,通过匹配key来确定所提供的值,如果父组件链上多个组件对同一个key提供了之,那么离得更近的将会覆盖链上更远的组件所提供的值
如果没有能通过key匹配到的值,inject()函数将返回undefined,除非提供一个默认值
第二个参数是可选的,即没有匹配到key时,使用默认值,它也可以是一个函数,用来返回某些创建起来比较复杂的值,如果默认值本身就是一个函数,那么必须将false作为第三个参数传入,表明这个函数就是默认值,而不是一个工厂函数。
与注册生命周期钩子的API类似,inject()必须在组件的setup()阶段同步调用
import {inject,toRefs} from "vue"; const person = inject('person'); // 若是使用解构,则会丢失响应式,修改数据时,页面不会更新,具体解决,可以引入toRef或toRefs函数 const {name,website} = toRefs(person); 模板使用 {{person.name}}---{{person.website}}
- vuex/pinia Vuex 和 Pinia 是 Vue 3 中的状态管理工具,使用这两个工具可以轻松实现组件通信。
- eventBus Vue 3 中移除了 eventBus,但可以借助第三方工具来完成。Vue 官方推荐使用 mitt 或 tiny-emitter。
3. 说说对盒子模型的理解?
盒模型都是由四人部分组成的,分别是margin、border、padding和content. 标准盒模型和IE盒模型的区别在于设置width和height时,所对应的范围不同标准盒模型的width和height属性的范围只包含了content, IE盒模型的width和height属性的范围包含了border、padding和content。 可以通过修改元素的box-sizing属性来改变元素的盒模型 box-sizing: content-box 表示标准盒模型 (默认值) box-sizing: border-box 表示E盒模型 (怪异盒模型)
4. Css的选择器有哪些?优先级?哪些可以继承
选择器类型:
- 通配符选择器:*
- 标签选择器 E
- id选择器 #id
- 类选择器 .class
- 伪类选择器
- 后代选择器(#box div),选择id为box元素内部所有的div元素
- 子选择器(.one>one_1),选择父元素为.one的所有.one_1的元素
优先级:
!important>内联 > ID选择器 > 类选择器 > 标签选择器
继承属性:
字体系列属性:font:组合字体、font-family:规定元素的字体系列、font-weight:设置字体的粗细、font-size:设置字体的尺寸、等
文本系列属性:text-indent:文本缩进、text-align:文本水平对刘、line-height:行高、color:文本颜色等。
列表属性:list-style-type:文字前面的小点点样式、list-style-position:小点点位置、list-style:以上的属性可通过这属性集合。
5. 元素水平垂直居中的方法有哪些?如果元素不定宽高呢?
6. 怎么理解回流跟重绘?什么场景下会触发?
回流:布局引擎会根据各种样式计算每个盒子在页面上的大小与位置
重绘:当计算好盒模型的位置、大小及其他属性后,浏览器根据每个盒子特性进行绘制。
重绘的触发条件
color、backgroundColor、size等改变元素外观的属性
重绘的触发条件
重绘一般发生在 UI 界面;是一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重 新绘制,使元素呈现新的外观。
回流的触发条件:
任何页面布局和几何属性的改变都会触发重排。
7. 什么是响应式设计?响应式设计的基本原理是什么?如何做?
响应式网站设计(Responsive Web design)是一种网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的响应和调整。
实现方式
响应式设计的基本原理是通过媒体查询检测不同的设备屏幕尺寸做处理,为了处理移动端,页面头部必须有meta声明viewport。
实现响应式布局的方式有如下:
媒体查询
百分比
vw/vh
rem
- 媒体查询
CSS3中的增加了更多的媒体查询,就像if条件表达式一样,我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表,通过媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片。
- 百分比
通过百分比单位 " % " 来实现响应式的效果。
- rem
移动端多会采用rem进行页面的布置。
响应式设计实现通常会从以下几方面思考:
- 小结
弹性盒子(包括图片、表格、视频)和媒体查询等技术
使用百分比布局创建流式布局的弹性UI,同时使用媒体查询限制元素的尺寸和内容变更范围
使用相对单位使得内容自适应调节
选择断点,针对不同断点实现不同布局和内容展示。
- 总结
优点:
面对不同分辨率设备灵活性强
能够快捷解决多设备显示适应问题
缺点:
仅适用布局、信息、框架并不复杂的部门类型网站
兼容各种设备工作量大,效率低下
代码累赘,会出现隐藏无用的元素,加载时间加长
其实这是一种折中性质的设计解决方案,多方面因素影响而达不到最佳效果
一定程度上改变了网站原有的布局结构,会出现用户混淆的情况
8. 如果要做优化,CSS提高性能的方法有哪些?
实现方式
实现方式有很多种,主要有如下:
内联首屏关键CSS(通过内联css关键代码能够使浏览器在下载完html后就能立刻渲染)
异步加载CSS(在CSS文件请求、下载、解析完成之前,CSS会阻塞渲染,浏览器将不会渲染任何已处理的内容,前面加载内联代码后,后面的外部引用css则没必要阻塞浏览器渲染。这时候就可以采取异步加载的方案:比如:使用javascript将link标签插到head标签最后)
资源压缩(利用webpack、gulp/grunt、rollup等模块化工具,将css代码进行压缩,使文件变小,大大降低了浏览器的加载时间)
合理使用选择器(我们在编写选择器的时候,可以遵循以下规则:
不要嵌套使用过多复杂选择器,最好不要三层以上,使用id选择器就没必要再进行嵌套;通配符和属性选择器效率最低,避免使用)
减少使用昂贵的属性(在页面发生重绘的时候,昂贵属性如box-shadow/border-radius/filter/透明度/:nth-child等,会降低浏览器的渲染性能)
不要使用@import(css样式文件有两种引入方式,一种是link元素,另一种是@import,
@import会影响浏览器的并行下载,使得页面在加载时增加额外的延迟,增添了额外的往返耗时
而且多个@import可能会导致下载顺序紊乱)
9. 对前端工程师这个职位是怎么样理解的?它的前景会怎么样
10. 说说JavaScript中的数据类型?存储上的差别?
在JavaScript中,我们可以分成两种类型:
基本类型
基本类型主要为以下6种: Number String Boolean Undefined null symbol
复杂类型
复杂类型统称为Object,我们这里主要讲述下面三种:
Object Array Function
两种类型的区别是:存储位置不同
存储区别
基本数据类型和引用数据类型存储在内存中的位置不同:
基本数据类型存储在栈中 引用类型的对象存储于堆中
当我们把变量赋值给一个变量时,解析器首先要确认的就是这个值是基本类型值还是引用类型值
11. 请简单叙述js数据类型判断的方法有哪些?
typeof ,instanceof,Object.prototype.toString.call()
- typeof它返回值是一个字符串,该字符串说明运算数的类型.
- instanceof 是用来 判断数据是否是某个对象的实例,返回一个布尔值。
缺点:对于基本类型的数据,instanceof是不能直接判断它的类型的,因为实例是一个对象或函数创建的,是引用类型,所以需要通过基本类型对应的
包装对象 来判断。所以对于 null 和 undefined 这两个家伙就检测不了. - Array.isArray() 方法:js中的isArray()是Array类型的一个静态方法,使用它可以判断一个值是否为数组。返回一个布尔值。
12. 说说你对闭包的理解?闭包使用场景?
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包.闭包让你可以在一个内层函数中访问到其外层函数的作用域.
使用场景
任何闭包的使用场景都离不开这两点:
创建私有变量 延长变量的生命周期
注意事项
如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响
13. bind、call、apply 区别?如何实现一个bind?
call,apply, bind方法都可以改变函数的this指向
call方法apply调用后函数会立即执行,bind万法不会立即执行函数call方法和bind方法后面跟的是参数列表,apply的参数据是一个数组。
14. Javascript本地存储的方式有哪些?区别及应用场景?
javaScript本地缓存的方法:
cookie
sessionStorage
localStorage
indexedDB
区别:
关于cookie、sessionStorage、localStorage三者的区别主要如下:
存储大小:cookie数据大小不能超过4k,sessionStorage和localStorage虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大
有效时间:localStorage存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; sessionStorage数据在当前浏览器窗口关闭后自动删除;cookie设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
数据与服务器之间的交互方式,cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端; sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
应用场景:
标记用户与跟踪用户行为的情况,推荐使用cookie
适合长期保存在本地的数据(令牌),推荐使用localStorage
敏感账号一次性登录,推荐使用sessionStorage
存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况,推荐使用indexedDB
15. 请叙述Vue2和Vue3数据响应式原理的不同?
vue2响应式:
vue2.0的双向数据绑定是通过数据劫持,结合发布订阅的方式来实现的,也就是说数据和视图同步,数据发生变化,视图也会发生变化,视图变化,数据也会随之发生改变。vue2的双向数据绑定核心是object.definedproperty()方法。给vue中的数据绑定get和set方法,当获取数据的时候,调用get()方法,当修改数据的时候调用set()方法。通过watcher监听器去更新视图,完成数据的双向绑定。
Vue3中的响应式原理:
通过Proxy(代理): 拦截对象中任意属性的变化,包括:属性值的读写,属性的增加,属性的删除等。
对比:
在Vue中,Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。
16. 请叙述Vue2和Vue3的diff算法的区别?
17. 请简单叙述你对作用域链得理解?
- 概念:
作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合
换句话说,作用域决定了代码区块中变量和其他资源的可见性。
- 作用域分类:
全局作用域(全局作用域下声明的变量可以在程序的任意位置访问) 函数作用域(如果一个变量是在函数内部声明的它就在一个函数作用域下面。这些变量只能 在函数内部访问,不能在函数以外去访问) 块级作用域(ES6引入了let和const关键字,和var关键字不同,在大括号中使用let和const声明的 变量存在于块级作用域中。在大括号之外不能访问这些变量)
18. Vue3中的生命周期函数的变化以及含义?
19. Vue3中自定义指令生命周期的变化及含义
自定义指令的生命周期
自定义指令有五个生命周期(也叫钩子函数),分别是bind,inserted,update,componentUpdated,unbind
**bind:**只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个绑定时执行一次的初始化动作。
**inserted:**被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于document中)。
update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。
componentUpdated:被绑定元素所在模板完成一次更新周期时调用。
unbind:只调用一次,指令与元素解绑时调用。