谈谈对VUE的理解
vue是一个数据双向绑定的渐进式框架,有很多自己的插件,同样也是一个声明式的UI框架,借助了MVVM的思想,是单页面形式的,可以把一个页面分割为多个组件,从而提高复用性。
什么是MVVM?
首先MVVM是一种设计思想,每个字母代表的是:Modle(数据和业务逻辑层)、View(视图层)、ViewModle(数据渲染视图),View和Modle之间并没有联系,通过ViewModel进行关联,Model和ViewModel之间有着双向数据绑定的联系,用户因为交互在View中改变了数据也会在Modle中直接同步,相反因为数据发生了改变也会在View层直接更新,这种模式实现了Modle和View的数据自动更新,因此开发者只需要关心业务逻辑和数据就可以了,不用自己操作DOM。
什么是MVC?
MVC也是一种设计思想,当数据发生改变的时候会通知视图层去更新,视图层因为用户交互发生数据改变会有Controllor调用Modle层从而改变数据,然后Modle层再通知视图层去更新。
什么是MVP?
MVP和MVC一样的思想,区别就是Controllor和Presenter,MVC是Controllor只控制Modle,没有控制View,MVP是presenter可以控制Modle和View,从而实现View和Modle的同步更新。
Vue的双向绑定是什么原理?以及Vue3的
vue2:
Vue2是使用数据劫持结合发布-订阅模式的方式实现的,当一个vue实例被创建时,vue会遍历data中的属性,并使用Object.difineProperty()方法转换为getter和setter,从而实现数据劫持。当数据发生变化的时候,setter会通知依赖该数据的所有组件进行更新。
vue3:
Vue3中也是使用数据劫持和发布-订阅模式实现的,不同的是Vue3中使用的Proxy对象替代了Object.defineProperty()方法,proxy对象可以拦截并重载对象上的各种操作,包括属性访问、属性赋值、函数调用等。
Proxy和Object.defineProperty()的区别?及优劣
- Proxy可以拦截对象的所有操作。包括属性访问、属性赋值、函数访问,而Object.defineProperty()只能拦截属性的访问和删除。
- Proxy可以监听整个对象而不需要监听对象的每个属性,更加高效,而Object.defineProperty()需要给对象的每个属性分开设置getter和setter,增加了代码的复杂度和运行时的开销。
- Proxy可以动态增加或者删除属性,而Object.defineProperty()不能。
- proxy可以监听数组的变化,而Object.defineProperty()不能。
- Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改。
Vue的生命周期有哪些?及Vue3的
vue2
- beforeCreate(创建前):此时vue的实例还没有被创建,此时data的响应式追踪、event/watcher都还没有被设置,也就是说不能访问data、methods上的方法和数据。适合在该阶段做一些初始化的操作,比如:配置项的处理,全局时间的绑定。
- created(创建后):此时vue实例已经创建完成,data、methods等都已配置完成,但是渲染节点还没有挂载到DOM上,无法访问
$el属性。适合进行数据初始化和异步请求。 - beforeMount(挂载前):在挂载开始之前被调用,此时已经生成了HTML,但还没挂载到页面上去。适合设置数据或者执行某些操作。
- mounted(挂载后):在挂载之后被调用,此时实例已经挂载到页面当中,DOM节点已经可见,可以进行DOM操作。适合调用第三方库或者进行DOM操作。
- beforeUpdate(更新前):数据更新前被调用,发生在重新渲染虚拟DOM和打补丁之前,但是对应的真实DOM还没有被修改。适合在更新之前访问已有DOM,比如手动移除已添加的事件监听器
- updated(更新后):数据更改导致虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新到页面当中,在这个阶段要避免修改数据,以免导致更新无限循环。
- beforeDestory(销毁前):此时vue实例还没有被销毁,this也可以正常使用,常用于清除定时器、解绑事件等。
- destoryed(销毁后):实例被销毁后调用,所有绑定的数据和事件监听都被解绑,所有子实例也都被销毁。
vue3
- Option Api:中就是把beforeDestory、destoryed改为了beforeUnmount、unmounted。
- Composition Api :中把beforeCreate、created改为setup函数,beforeDestory、destoryed改为OnBeforeUnmount、OnUnmounted,其余的加On。
Vue组件通信的方式有哪些?
- 父传子:父组件给子组件身上绑定属性,子组件通过prop来接收。
- 子传父:父组件通过给子组件监听事件,子组件通过
$emit来触发事件,进而传递参数。 - 依赖注入:父组件使用provide提供数据,子组件通过inject获取数据。
- eventBus:兄弟组件之间传递参数,
$emit传递参数,$on接收。 - ref/refs:通过ref给组件标记一个唯一的引用,通过
$refs来访问组件的实例。 - parent/children:层级不深的组件,子组件通过
$parent可以获取父组件的数据,父组件可以通过$childern来获取子组件身上的数据。 - attrs/listeners:
$attrs可以让父组件向子组件传递所有的属性,$listeners可以让子组件向父组件传递所有的事件。 - 状态管理:vuex或者pinia。
讲一下Vuex和Pinia
这个两个都是官方推出的状态管理库,允许跨组件或页面共享状态,在使用上区别不大。
vuex中有state、Getter、Mutation、Action、Modle,pinia中把Mutation和Action合并成Action。
- state:存放数据的状态
- Getter:相当于计算属性一样
- Mutation:同步函数,更改数据状态的地方
- Action:异步操作,请求数据,不能直接修改数据状态
- Modle:切割模块
Vuex的使用流程:页面通过dispath来触发action中的方法,action通过commit来提交到mutation中,mutation会修改state中的值,页面重新渲染。
Vue的指令有哪些?
- v-if:根据表达式来判断是否渲染,结果为true时渲染,false时不渲染。
- v-show:根据表达式来判断是否显示隐藏,与v-if的区别在于v-if是是否渲染,v-show是控制dispaly的bolck和none。
- v-for:遍历数组或对象,循环渲染。
- v-bind:动态绑定组件的属性
- v-on:绑定事件监听器
- v-model:双向数据绑定
- v-text:更新元素的文本内容
- v-html:更新元素的html内容
- v-once:只渲染一次
Vue怎么自定义指令?
- 全局:Vue.directive("focus"{})
- 局部:directive()
- 钩子函数:
Vue.directive('directiveName', {
// 指令的生命周期钩子
bind(el, binding, vnode) {
// 指令绑定时调用
},
inserted(el, binding, vnode) {
// 被绑定元素插入父节点时调用
},
update(el, binding, vnode, oldVnode) {
// 组件更新时调用,可能发生在子组件的更新之前
},
componentUpdated(el, binding, vnode, oldVnode) {
// 组件更新后调用
},
unbind(el, binding, vnode) {
// 指令解绑时调用
},
});
- 钩子函数参数:
el:指令所绑定的元素,可以用来直接操作DOM。binding:一个对象,包含指令的信息,如value、name等。vnode:Vue编译生成的虚拟节点。oldVnode:上一个虚拟节点,仅在update和componentUpdated钩子中可用。
Vue的事件修饰符有哪些?
.once:只触发一次.self:只触发自己.stop:阻止事件冒泡.prevent:阻止事件默认行为.captrue:使事件捕获,从外到内
computed和watch的区别?
- 语义上:computed是计算属性,watch是侦听器。
- 功能上:computed有缓存,只有依赖的数据发生变化时才会重新计算,watch没有缓存,可以监听到每个数据发生变化,并在数据变化时执行回调。computed用于处理对数据的计算或逻辑处理,返回一个新的响应式数据,watch用于观察数据的变化,并执行对应的操作,不会返回新数据。computed是声明式写法,watch是命令式写法,需要手动指出需要监听的数据和执行的回调函数。
data为什么是一个函数不是一个对象?
防止数据污染,对象是引用型数据,当多个实例指向同一个对象的时候,只要一个实例对这个对象进行操作,也会改变其他实例的对象。通过data定义为函数时,数据是以函数返回值的形式定义的,都会调用函数返回一个新的数据对象,修改组件自身的data不会影响到其他组件。
Vue模版编译的原理是什么?
- 解析阶段(parse):使用大量的正则表达式对 tempalte 字符串进行解析,将标签、指令、属性等转化为抽象语法树(AST)
- 优化阶段(optimize):遍历抽象语法树(AST),找出其中的静态节点并标记,方便diff比较的时候跳过这些节点,提高性能。
- 生成阶段(generate):将最终的 AST 转化为 render 函数字符串。
v-model有什么修饰符?
.nomber:输入的内容自动转化为数字。.trim:去除首位空格.lazy:change事件的时候再调用
Vue路由的方式有哪些?有什么区别?
- hash:hash模式不会包含在http请求当中,并且hash不会重新加载页面,在url中对有一个#号。原理是onhashchange()事件。
- history:使用history不会有#号,初次访问或者刷行都会向服务器发送请求,需要后端配合。原理是H5新增的两个方法:pushState和replaceState来完成的。
$route和$router的区别?
- $route:指的是路由信息对象,包括path、params、name、query等。
- $router:指的是路由实例,包含了路由的跳转方法和钩子函数。
路由的跳转方法有哪些?
push、go、router-link标签的to方法、replace
路由的钩子函数有哪些?
beforeEach:在路由切换之前调用,可以用于进行全局的权限验证或拦截导航。beforeResolve:在路由解析之前调用,可以用于确保异步组件加载完成。afterEach:在路由切换成功后调用,可以用于进行页面埋点等收尾工作。beforeRouteEnter:在路由进入组件之前调用,允许访问组件实例,但无法访问组件的this。beforeRouteUpdate:在路由更新但是仍然复用组件时调用,允许访问组件实例。beforeRouteLeave:在路由离开组件之前调用,允许访问组件实例,可以用于弹出确认对话框等操作。
虚拟DOM是什么?
虚拟Dom是一种前端优化性能的一项技术。通过以javascript对象的形式表示真实Dom树,减少对真实Dom的操作,从而提高页面渲染效率。
虚拟Dom的工作原理是什么?
- 初始化阶段:当页面加载或组件初始化时,会通过解析模版或渲染函数来创建一个虚拟Dom树。
- 数据变化:当数据发生变化时,触发视图更新。
- 更新阶段:在更新阶段,新的数据会与之前的虚拟Dom树进行比较,从而找到需要更新的部分。
- 应用差异:将比较得到的数据,只更新差异的数据到真实的Dom中。
- 渲染阶段:将真实的Dom更新到页面当中。
虚拟Dom 的优势在于什么?
- 减少Dom操作:通过比较新旧虚拟Dom树,只更新变化的部分,避免重复的Dom操作,提高页面渲染的性能。
- 跨平台:虚拟Dom是javascript对象,不依赖浏览器。
- 简化开发:开发者无需操作Dom,只需要操作数据,框架会自动处理Dom更新。
diff算法是什么?
diff算法是一种用于比较两树结构的算法。它通过比较新旧虚拟Dom树,找出差异,然后只需要更新差异部分到真实Dom中,从而提高页面渲染性能。
vue项目中的性能优化
1.不要在模板里面写过多表达式
2.循环调用子组件时添加key
3.频繁切换的使用v-show,不频繁切换的使用v-if
4.尽量少用float,可以用flex
5.按需加载,可以用require或者import()按需加载需要的组件
6.路由懒加载