一. html与css
1.em 和 rem 的区别是什么
em单位,是使用em单位的元素的字体大小,父元素会影响到其大小(因为继承的原因)
rem单位,是相对于根元素的字体大小,也就是一个html的字体大小
2.rem 适配的原理
利用媒体查询@media,根据屏幕大小不同时分别设置一个html的font-size大小,页面中的px单位转化为rem单位,当一个根元素的字体发生变化时,其他尺寸也会跟着变化,从而达到适配的效果
移动端适配:
1. 结合flexible.js,内部原理是将屏幕划分为10份,只需要手动设置html的font-size大小(750px设计稿/10 ) VSCode中插件 cssrem px 转换rem
2.vh与vw
100vw相当于100%的视口宽度 100vh相当于100%的视口高度
如果此时375px的设计稿(屏幕宽度),100px的div,100px的字体大小,(375px=100vw;1px=100vw/375)
3. vue中移动端适配:插件①amfe-flexible(屏幕分为10份,原理同上), ②安装postcss-pxtorem@5.0.0 将px转rem 注意版本问题
配置字体大小,创建postcss.config.js 代码如下
module.exports = {
plugins: {
rootValue: 37.5, // 基准值(设计稿/份数10),
// propList:哪些css需要转化
propList: ['*']
}
}
//设计稿为1080 723px用rem表示 723/108rem
如果有两套标准,ui设计有一套方案大小等,还有一套是vant组件库的样式大小,只需要把配置更改一下,如下: 加入判断条件
//file.dirname:得到文件路径
//如果是组件库的css解析,它的文件都来自于node_modules/vant
const path = require('path')
module.exports = ({ file }) => {
//判断当前文件路径是否包含vant,如果包含就是解析的vant的css
//(假设vant的尺寸是375,设计稿是750)
const base = file.dirname.includes(path.join('node_modules', 'vant'))
? 37.5 // vant尺寸px/10
: 75 // 设计稿大小px/10
return {
plugins: {
rootValue: base, // 基准值(设计稿/份数10),
// propList:哪些css需要转化
propList: ['*']
}
}
}
3.HTML 的语义化你是怎么理解的
让内容可以更具有语义,有利于SEO,也更有助于理解
4.margin-top 的百分比相对谁,例如 margin-top: 50% 是什么意思
是相对于父盒子宽度的百分比,子盒子上边距的距离是父盒子宽度的50%,(注意上边距塌陷问题,父盒子加边框...)
5.说一下 Less 你用过哪些特性(除了变量、嵌套、计算)
可以定义方法,如下:
定义:
.border(@w,@color){
.border:@w solid @color
}
使用:
.app{
.border(1px,red)
}
6.BFC 块格式上下文
是一块独立的渲染区域,决定子元素的定位以及和其他元素的关系(触发了BFC,那这一块区域就是独立的渲染区域)
比如:根元素,浮动元素,绝对定位元素,行内块元素,表格单元格,overflow(除visible外),都会触发BFC
特性:
1.同一个BFC上下外边距会合并
2.清除浮动
3.BFC区域不会与float元素重叠
7.meta标签的作用
1.有利于SEO
2.设置网页视口大小,缩放,比例
3.设置http响应头,字符集
8.img中srcset
让图片实现响应式 适配屏幕大小,在不同尺寸下设置不同的img图片显示(js也可以实现)
可以搭配picture标签包裹img使用
9.script标签 async与defer
导入文件时,可能会导致堵塞后面的结构的加载和解析
用async或者defer 异步加载文件后,就不会堵塞页面的加载,与页面加载同时进行
区别:
async 脚本加载完,立刻执行,适合不依赖于其他js文件的脚本加载
defer 脚本加载完,会等待一定时间,等dom加载完毕且等上面的其他defer脚本执行完毕后才执行(保证顺序) 类似onload事件
10.z-index 坑
如果父元素有定位,且配置了z-index,优先按照父辈元素的定位的z-index进行比较层级
11.flex-弹性盒子布局
响应式的布局方式,某种程度上可以替代浮动或定位的布局,代码更简洁
flex-direction调整主轴方向,默认x轴(row),y轴(column)
justify-conent 设置主轴方向的盒子对齐的方式,常用:center(弹性盒子中间位置对齐),space-around(环绕,均匀分布),spance-between(左右贴,中间盒子均分位置)
align-items 设置侧轴的对齐方式(单行),center(居中)...
align-content (多行)
12.grid网格布局
将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局
使用网格布局后,项目的float
、display: inline-block
、display: table-cell
、vertical-align
和column-*
等设置都将失效。
划分列 grid-template-columns/划分行 grid-template-rows:
- px
- %
- 比例值 fr(可与auto关键字一起使用)
- minmax()函数值 :函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
- repeat()函数值:
repeat()
接受两个参数,第一个参数是重复的次数,第二个参数是要重复的值。 - fit-content()函数:让尺寸适应于内容,但不超过设定的尺寸,常用于希望grid子项的宽度随着内容变化,但是又不希望宽度太大的场景。(函数只支持数值和百分比值,fr值是不合法的)
-
min-content
-
max-content
-
auto
自动填充 auto-fill
设置行/列的间距(row-gap/column-gap/gap(合并写法)
)
指定区域 grid-template-areas
改变网格布局的布局顺序 grid-auto-flow
设置单元格内的对齐方式(justify-items/align-items/place-items(合并写法)
) 单个项目(justify-self/align-self/place-self
)
设置容器内的对齐方式(justify-content/align-content/
)
13.css可以继承的属性
子节点默认使用父节点的样式属性:有颜色,文字,字体间距行高对齐方式,和列表的样式等可以继承
所有元素可继承:visibility和cursor
块级的可继承:line-height、color、font,transform
终端块状元素可继承:text-indent和text-align
列表元素可继承::list-style、list-style-type
二.js
1. 数据类型有哪几种
简单数据类型:Null,Undefined,Boolean,String,Number,Symbol,BigInt
复杂数据类型:Object(Function,Array,Object...)
2.判断数据类型
typeOf 简单数据类型(null不可以准确判断(返回object)以及复杂数据类型)
intanceOf 复杂数据类型 (返回布尔值)
最准确的方法:
Object.prototype.toString.call() 方法
内部原理:改变原型上toString中的this指向 可以准确判断数据类型
3.伪数组转真数组
es6:Array.from()
Array.protoptye.slice.call() / [].slice.call()
4.数组去重的方法
- const one=Array.from(new Set(arr)) set数据结构
- let newArr=arr.filter(item=>{return arr.indexOf(item)===index})(indexof只会查找第一个)
- 用for嵌套for,用数组的第i项和第i+1项比较,一样就splice(j,1)删除后者,且j--
- 用includes,定义一个空数组,for循环原数组,如果空数组中是否包含includes(arr[i])就用push添加到新数组
5.前端存储方式
localStore:5M,永久存储,除非手动删除
sessionStore:5M,页面关闭时被自动清理
Cookie:4K 设置过期时间后清理,插件js-cookie
IndexedDB:大于等于250MB 甚至没有上限
6.js垃圾回收
js中内存的分配和回收都是自动完成的,内存不使用的时候会被垃圾回收器回收,但是过度依赖会出现问题,比如内存的泄漏(闭包)
回收算法:引用计数,标记计数
引用计数:如果没有任何变量指向引用,说明该对象不在再需要(致命弱点:循环引用:两个对象互相引用,会导致内存泄露)
标记计数:(js的全局对象,)凡是能从根部到达的对象(变量,函数等),都是不会被释放的
7.作用域链
函数内访问变量时,优先使用自己内部声明的变量,如果没有就会尝试访问外层函数作用域的变量,直到找到全局,如果全局都没有就报错,这样一层一层向外查找的关系就是作用域链
(js全局有全局可执行上下文,每个函数调用时,有着函数的可执行上下文,每个可执行上下文都有着对于外部上下文的引用,外部上下文也有着对于其自己外部的上下文词法作用域的引用) 就形成了作用域链
8.闭包
内层函数引用外层函数中的变量,使用变量的地方称为发生了闭包现象,定义变量所在的函数称为闭包函数
常见应用(作用):实现数据的私有化
(全局变量是容易随意被改变的,会影响到函数中访问全局变量的值,希望有些数据是私有化的,不让外部使用的,就会用到闭包,用变量包裹)
注意点:外部函数中,一般需要return 引用,才不会被垃圾回收,内存不会释放(容易导致内存泄露,手动释放,将引用置null)
9.原型链
构造函数通过new 创建实例对象,实例对象通过隐式原型(__proto__),可以访问构造函数的原型对象,构造函数通过显式原型(prototype)指向自己的原型对象,构造函数的原型对象通过constructor指向构造函数,在实例访问属性和方法时,优先查找自己的,如果无则通过__proto__往原型对象上找,如果没有就会继续找Object的原型对象,还是没有会找到Object原型对象上的__proto__(null),最后报错,这就是原型链
10.继承
让多个构造函数之间建立联系,便于管理和复用,继承一些属性和方法
原型继承:通过改造原型链实现继承,利用原型链的特征实现继承
寄生组合继承:通过Object.create(参数对象),创建一个新对象,并且这个对象的__proto__指向传入的参数对象
组合式继承:通过原型链和借用构造函数call技术组合到一起实现继承的方式
es6-class继承:extends(constructor中利用super实现借调父构造函数)
11.this的理解
1.函数的调用 fn() 指向window
2.方法的调用 obj.fn() 指向调用者
3.上下文调用模式 想指向谁就指向谁 call,apply,bind 第一个参数就是this的指向
4.构造函数模式 指向创建的实例对象
5.箭头函数 与外层函数this指向一致
12.promise 的理解
一般作为构造函数使用,有3种状态,pending(处理中),fulfilled(成功),rejected(失败)
拿到一个 Promise 实例后,具有 then 和 catch 方法,一般 then 里面拿到成功的结果,catch 拿到失败的结果
它主要解决了回调地狱的问题,但是 Promise 并不能简化代码,工作的时候都会配合 async/await 来使用,这样既解决了回调地狱又简化了代码
同时发送并发请求利用Promise.all() 方法
最优选择,谁执行快(读取缓存,本地/服务器读取) 利用Promise.race() 方法
13.宏任务 微任务
事件循环:js主线程执行同步任务,异步任务委托给到宿主环境执行,将异步任务的回调函数依次放在等待队列等待,当同步任务执行完毕之后,就会执行等待队列中任务,不断循环的过程就是EventLoop
主线程的同步任务属于宏任务, setTimeout 等也属于宏任务(是异步任务中的宏任务),可以理解为主线程的代码为宏任务1,当宏任务1执行完毕之后,才会执行异步任务中的宏任务2
promise中的.then或.catch等是微任务,会在当前宏任务执行完毕之后,在下一个宏任务执行之前执行(执行下一个宏任务前优先执行执行满足条件的等待的微任务)
async用于修饰一个函数,表示此函数是异步的,但是只有在遇到await才是异步的开始(如果没有await,async不生效).await赋值等内容可以理解为是.then中的内容(函数的调用表示的还是宏任务)
14.async/await
async函数 是Generator 函数的语法糖,async会自动将常规函数转换成Promise,返回值也是一个Promise对象,await后的代码赋值操作是异步的操作
相较于Promise,其优势在于代码简单,结合try/catch可以更简洁的捕获错误且不会影响后续代码的执行
15.深拷贝/浅拷贝
浅拷贝只拷贝一层,复杂数据类型在赋值时,是赋值的引用地址,方法有es6的展开运算符
深拷贝 利用JSON.parse(JSON.stringfy(obj)) 解决大部分问题
16.http协议相关等
- 发送请求方式: 常用GET,DELET,POST,PUT(整体修改),PATCH(局部修改更新)
- get/post区别:①get是地址栏传参,post是请求体传参;②get请求参数长度限制,post无;③get后退刷新浏览器操作无影响,post可能会引起重复提交表单;④get请求的参数数据类型ASCII字符,而POST没有限制;⑤get请求暴露在地址栏中安全性相对较低
- HTTP 请求报⽂的组成:请求⾏、请求头、(空⾏)、请求体
- HTTP 响应报⽂的组成: 响应⾏、响应头、(空⾏)、响应体
-
HTTP状态码:
2xx: 200/201 表示成功
3xx:301永久重定向,302临时重定向 304协商缓存(未修改,返回此响应时不会有内容)
4xx:表示失败(400传参格式问题,401权限问题(token) ,404表示没有找到请求的资源)
5xx:表示服务器错误(也有可能是浏览器请求中存在错误,服务端无法识别,501服务器无法识别的请求方式)
- HTTP的Keep-Live(在请求头中加入)
使客户端到服务器端的连接持续有效,当出现对服务器的后续请求时,该功能避免了重新建立连接
优:减少CPU和内存占用,减少后续请求的延迟
缺:处理的暂停期间也仍然被占用
解决:timeout,设置过期时间;max设置最大请求次数(为0后,断掉连接)
- HTTPS
17.同源策略以及如何解决跨域
同源:协议,域名,端口号一致
同源策略:一种保护机制,(协议/域名/端口号某一个不一样),它用于限制从⼀个源加载的⽂档或脚本与来⾃另⼀个源的资源进⾏交互
三个标签除外,不受同源策略的影响 :<img> / <link> / <script>
实现跨域:
-
JSONP :利用script标签的src属性,请求数据的同时,返回一个回调函数,只支持GET请求,安全性较低
-
CORS :主流,后端设置响应头,开发中或上线遇到跨域,不考虑兼容问题,优先后端配置CORS
-
服务器代理(webpack代理[开发时,devserver的proxy配置项], Nginx反向代理[上线时])
18.call apply bind的使用
都可以改变this指向,区别是call可以传递多个参数,apply是传递数组,bind不能直接调用,是返回一个新函数,共有一个函数体
19.数组常用api
push,splice,indexof,join,map,reduce,filter,forEach,every,find,findIndex (改变原数组的方法:pop,reverse,push,sort,splice...)
pop删除最后一个,shift删除第一个
unshift前面添加一个或数组元素,push后面添加
20.字符串常用api
- 长度:
length()
或.length()
,获取字符串的长度,即字符数。 - 拼接:
+
运算符、concat()
或join()
函数,将两个或多个字符串连接成一个新的字符串。 - 访问字符:通过索引访问单个字符,如
charAt(index)
或[index]
。 - 截取子串:
substring(startIndex, endIndex)
,从指定位置开始到结束位置(不包括该位置)取出子串。 - 替换:
replace(oldChar, newChar)
或replaceAll(pattern, replacement)
,替换字符串中的特定字符或模式。 - 查找:
indexOf(searchValue)
或contains(substring)
,搜索某个子串的位置或检查是否包含。 - 分割:
split(separator)
,按给定分隔符将字符串拆分为数组。 - 格式化字符串:
format()
函数(Java)、f-string
(Python),用于插入变量值到预定义的模板中
21.Object的常用api
Object.keys/Object.entries/Object.value/Object.assign
对象.hasOwnProperty
22.eventloop事件循环
同步任务交给js执行栈执行,异步任务交给宿主环境执行将回调函数依次添加到等待队列中等待执行,当js执行栈的任务执行完毕后,去等待队列中依次读取和执行异步任务,重复执行读取和操作的过程叫事件循环
23.描述输入url地址到网页展示的过程
在DNS将url解析成ip之前,先从浏览器的缓存里面读取,如果没有就从系统缓存的host文件里面读取,如果都没有就解析,解析完成后,经过三次握手和四次挥手之后,浏览器将css和html转换为标记再转化为节点,生成对应的dom树和cssom树,最后生成渲染树开始渲染页面
24.hash路由和history路由的原理与区别
hash值变化浏览器不会重新发起请求,但是会触发window.hashChange事件,hashChange事件中获取当前的hash值,并根据hash值来修改页面内容
history模式基于window.history对象的方法 history.pushState,replaceState,以及popState事件监听状态变更,更改浏览器中的url
history路由
优点:
用户体验好,可以保留浏览器的前进后退功能。
可以清晰地看到网站的结构,对搜索引擎优化(SEO)更加友好。
不需要依赖于特定的服务器配置。
缺点:
存在兼容性问题,在浏览器不支持 history.pushState API时不能使用。
需要服务器端配置来支持单页面应用(SPA)的路由。
hash路由
优点:
兼容性好,支持旧浏览器,即使它们不支持 history.pushState API。
不需要服务器端任何配置更改即可使用。
缺点:
不能保留浏览器的前进后退功能,因为它是在hash值变化时进行页面的重新加载。
URL中会带有#,对于用户来说看起来不那么优雅。
对于搜索引擎优化(SEO)不是很友好,因为它会看作是不同页面的不同部分。
实际开发中如何选择路由模式
取决于你的应用需求和目标用户群体。如果你的应用需要良好的用户体验和SEO优化,推荐使用history路由。如果你的应用需要兼容老旧浏览器或者是一个简单的单页面应用,可以选择hash路由。
注:这两种模式都用于单页面应用程序(SPA)中,客户端浏览器根据不同的URL渲染不同的视图页面,更新视图但不重新请求页面,是前端路由原理的核心。
三. git相关
1.git工作流
master:主分支
develop:主开发分⽀。基于该分支上创建新分支,开发自己的模块
release:测试分支,⼀般测试阶段发现的 bug 在这个分⽀进⾏修复
hotfix:热补丁分支。用于修改在线上版本中发现的严重紧急 bug
大部分情况:
在develop上 创建不同分支写不同功能代码,功能写完毕,合并到develop分支, 最后合并release分支上进行该功能的测试,修复bug,最后所有模块bug修复完成后 ,合并到master分支以及develop分支上,将master代码用于真实上线环境,如果上线代码遇到错误,开一个hotfix分支,调试紧急bug
Git的rebase和merge 区别:
merge合并会保留记录,方便复盘,以及回退版本,但是当发现某个功能提交修改比较频繁时,可以尝试使用rebase,会合并之前的 commit
历史
Git的reset回退和revert撤销:
所有版本号:git log --pretty=oneline
回退到某个版本(直接跳回该版本):git reset --hard 版本号(黄色标识)
撤销某个版本内容的内容修改:git revert-n 版本号 (需要再次git add. 与git commit -m '修改')
如果git reset后,版本回退了,无法直接push到远程仓库(因为仓库中的版本更新),此时需要git push -f 覆盖推送即可(将远程仓库的版本也进行了回退)
四.webpack相关
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
是一个打包的工具,在webpack里面一切文件都是模块,通过loader转换文件,通过plugin注入钩子,最后输出多个模块组合的文件
loader:webpack原生只能解析.js文件,比如css文件都要通过loader加载器,用来预处理更多类型的文件(css-loder/style-loder)
plugin:插件 可以扩展webpack的功能,借助第三方插件实现(html-webpack-plugin)
五.Vue相关
1. MVVM
一种总结的设计模式,Model,View,ViewModel实现的是不仅数据可以影响视图,视图还可以影响数据
2. Vue的生命周期
4个阶段(初始化,挂载,更新,卸载),10个常见钩子函数
beforeCreate:创建初期
created:实例创建完毕,data与method已绑定,但真实DOM还未生成(场景:请求,注册全局的组件等)
beforeMount:虚拟DOM挂载成真实的DOM之前
mounted:真实的DOM挂载完毕(可获取到DOM元素)
beforeUpdate:数据修改后,更新之前,发生在虚拟DOM打补丁之前
updated:数据修改之后,视图更新之后
activited:在组件被激活时调用(使用了 <keep-alive>
的情况下)
deactivited:在组件被停用时调用(使用了 <keep-alive>
的情况下)
beforeDestory:在组件销毁之前调用(释放监听,组件类)
destoryed:在组件销毁后调用(手动销毁定时器,等)
3.Vue中的传值
父传子,子传父,非父子,Vuex
- props和$emit 父子之间
父组件:子组件的标签上通过 :自定义属性名='父数据' ,传递到子
子组件:通过props接收数据(可以定义类型和默认值)
父组件: 子组件标签上 @自定义事件名='父事件名(形参)' 传递子
子组件:通过$emit('自定义事件名',实参) 触发父方法
- eventBus事件总线 非父子
在Vue的原型上挂载实例对象 Vue.prototype.$eventBus=new Vue()
通过this.$eventBus.$on('事件名',function(){}) 监听bus事件
通过this.$eventBus.$emit('事件名',实参...) 触发bus事件
- $refs.$parent.$children 父子之间
通过在子组件标签绑定ref属性值 $refs获取子组件的实例
父组件中 $children返回的是一个组件的数组集合,可以通过下标得到子组件实例
而在子组件中$parent 指向的是父组件(包裹子标签的组件/或者父组件)
-
provide inject 成对出现 祖先向子孙
每一个子孙组件都可以通过inject 获取到祖先组件中通过provide传递的数据
//与data同级,且格式一致
provide () {
return {
value: this.value // 共享给子孙组件的数据
}
},
export default {
//其中的名,不可以与其他数据名 雷同
inject: ['value'],
//与props不冲突
props: {
...
}
}
-
$attrs $listeners
祖先组件中,父组件标签,还是属性绑定和自定义事件绑定
$attrs 接受非props属性的数据,$listeners接受祖先的所有方法 绑定在孙组件的标签上
孙组件中:就可以通过props 和$emit 来接受数据和触发方法
<SonSon v-bind="$attrs" v-on="$listeners"></SonSon>
-
Vuex 全局状态管理
state:存放数据
mutations:存放数据的方法
actions:存放异步操作(或同步操作),actions不能直接修改state中的数据,需要通过mutations修改
getters:存放基于state计算的值
modules:模块化
分模块后,其muations, actions, getters,注册到全局的,一般需要开启命名空间
4. computed和watch 区别
computed: 计算属性,用于值的计算,必须有返回一个值,具有缓存性,getter函数计算的值是缓存的,只有当依赖项改变,下一次的访问时,才会重新调用getter函数重新计算;不支持异步,当computed内有异步操作时是无法监听数据变化的;多个依赖,只返回一个值
watch: 观察,当数据变化时的监听并执行其回调,不一定要返回某个值;支持异步操作;监听一个,可以操作多个数据
5. Vue双向数据绑定原理
Vue2中 利用的是Object.defineProperty 劫持数据对象的访问器(getter和setter) 获取对象的属性值和属性 修改的值
- 兼容性好
Vue3中 通过Proxy代理对象,劫持整个对象,对象任意属性的变化都会劫持到
-
可以直接监听整个对象,⽽⾮是对象的某个属性
-
可以直接监听数组的变化
6. Vue响应式系统
- MVVM模式 数据驱动视图,视图还可以改变数据
- Vue2中 通过Object.definePorperty完成对数据的劫持,通过观察者模式,完成对于节点的数据更新
- 观察者模式 一个数据或对象被修改时,会通知所有依赖它的对象,让订阅者Watcher进行更新操作
7. Vue中key的作用
给虚拟DOm添加标识,便于在更新时,结合diff算法,按照 key 对比新旧DOM,找到不同处进行更新视图,优化渲染性能
8. 路由传参
基础传参:
传:this.$router.push(路径/参数名?参数1=值1&参数2=值2..)
this.$router.push({
path:'/path地址',
query:{
参数名:值,
参数2:值2
}
接:this.$route.query.参数名
动态路由传参:
路由配置:
{
path:'路径/:参数名?', // ?代表参数值可传可不传,不写?一定要传
component...
}
传:this.$router.push('路径/参数值')
收:this.$route.params.参数名
name传参:
路由配置:
{
path:'/',
name:'home',
....
}
传1: 刷新不受影响,参数在路径中显示,长度受限制
this.$router.push({name:'home',query:{参数名:参数值}})
收1:this.$route.query.参数名
传2:刷新后传参就没了,数据长度与数据类型不受限制 配合localStorage使用
this.$router.push({name:'home',params:{参数名:参数值}})
收2:this.$route.params.参数名
9.v-mode和.sync的对比
都可以实现传值,区别是在vue2中v-model只能用一次,.sync可以用多次,vue3是直接合并了,用v-model也可以实现多次绑定;v-model是通过vlaue和@input传递属性和方法,子组件通过props接收和$emit('input',参数)来触发父修改数据;.sync是通过自定义的属性名,以及@update:属性名传递修改数据的方法,子组件通过props接收和$emit('update:属性',传参)修改父数据
10.vue2中v-model是一个语法糖,那具体是怎么实现的?
子组件标签利用:value绑定父组件的属性,@input绑定事件
子组件通过props接收value,$emit('input',实参)触发父方法修改值
11.v-if和v-show的区别
v-if 是将dom进行销毁和重构,v-show是将dom添加display:none进行隐藏和显示,两者v-if更消耗性能
12.自定义指令周期
bind类似beforeMount (可能数据少会拿到dom)
inserted类似mounted 获取dom
undate:更新中, 不保证更新完
componentUpdated :类似updated
unbind:解除绑定beforeDestory
13.vue2中vue.use是怎么用的
Vue.use()用来安装插件,参数为一个对象或者函数,如果是一个对象里面必须提供install方法,如果是函数,会被作为install方法,该方法调用时,会将Vue作为参数传入,该方法需要在调用 `new Vue()` 之前被调用
14.vue2中$nextTick
`Vue` 在更新 `DOM` 时是异步执行的。当数据发生变化,`Vue`将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一进行更新
`$nextTick()` 会返回一个 `Promise` 对象,可以是用`async/await`完成相同作用的事情
15.vue2和vue3的区别
- Vue3出来几年了,写代码方式变了,性能提升 vue3是按需导入的 所以打包的时候webpack才能进行tree shacking,把没用的代码忽略,就更简化 vue3
- 为什么v2的option没v3的composition好? 因为v2的选项api代码结构比较分散,大型项目的开发数据较多,同一业务的状态和逻辑太分散了要来回跳
- 解决vue2无法响应式新添加属性或通过下标修改数组无法实现响应式的问题:因为Vue2是通过object.defindpropoty来实现对象中已存在的数据监听,可以通过$set(需要添加的对象,添加的属性名,添加的属性值)解决,Vue3是通过proxy响应式原理代理监听的是整个对象
vue2 $set(原对象,更改的属性,更改的值)就可以实现响应式
Vue项目后续
Vue项目的SEO优化
Vue单页面应用,对SEO不友好,解决如下:
1.SSR服务器渲染 服务端html页面节点, 已经解析创建完了, 浏览器直接拿到的是解析完成的页面结构,服务器需要支持nodejs环境,
2.静态化 Nuxt.js 进行 generate 静态化打包,动态路由会有所忽略
3.预渲染 prerender-spa-plugin (插件) 少量页面的SEO处理
4.用Phantomjs 针对爬虫 做处理
Vue项目首屏加载慢
原因:一次性加载了过多资源,过大的资源
1.配置异步路由,路由懒加载
2.图片压缩 使用webp格式的图片提升首屏加载速度
3.CDN资源
4.开启GZIP压缩
Vue的编译原理/过程
vue的编译主要是3个阶段,第一个是parse(解析) 主要是将template模板进行解析,生成ast(抽象语法树),第二个阶段是optimize(优化),主要是对ast进行优化,标注静态节点,第三个阶段是generate(生成),根据ast生成render函数