vue知识点,面试常考点
双向绑定(vue2和vue3)
vue2:使用Object.defineProperty对象以及属性的劫持+发布订阅模式,只要数据发生变化直接通知变化并驱动试图更新。
语法:
Object.defineProperty(obj,"name",{get:()=>,set:()=>{}}) 参数:参数一obj:劫持对象;参数二“name”:劫持对象属性;参数三:给属性添加set,get方法。
存在的问题:关于对象:Vue无法检测Property的添加或移除。关于数组不能利用索引直接设置一个数组项,也不能修改数组的长度。
vue3:vue3.0的响应式采用了ES6中的Proxy方法。Proxy对象用于定于基本操作的自定义行为(如属性查找,复制,枚举,函数调用等)。
语法:
let p=new Proxy(obj,{get:(target,prop,p)=>{},set:(target,prop,p)=>{}}) 参数:参数一target:劫持对象;参数二prop:劫持对象属性;参数三value:新的属性值,p:本身。
指令
1.v-model:双向绑定
- bind:绑定响应式数据
- 触发oninput事件并传递数据
<input v-model="sth" />等同于<input :value="sth" @input="sth=$event.target.value" />
2.v-for:循环
3.v-if和v-show区别
- v-if直接从dom树上添加或删除节点,更耗性能。
- v-show是设置节点的display为none,不会从dom里删掉。
4.v-once:让界面不要跟着数据变化,只渲染一次。
5.v-on:绑定事件,可多个事件。
<div class="app">
<button v-on={mouseenter:onenter,mouseleave:leave}">
click me
</button>
</div>
6.v-bind:动态的绑定一个或多个attribute,或一个组件prop到表达式。
7.v-text:更新元素的textContent。
8.v-html:更新元素的innerHTML 。
9.v-cloak:这个指令保持在元素上直到关联实例结束编译。
10.v-slot:提供具名插槽或需要接受prop的插槽。
使用的场景:
v-show:前台数据的展示
v-if:管理系统权限列表的展示
vue中的key的作用
1.高效的更新虚拟DOM.
2.默认使用就地复用策略,列表数据更新的时候,它会根据可以值去判断某个值是否修改,如果修改,则重新渲染这一项,否则重用之前的元素。
总结:不适用key时,当更新列表时,所有的数据都需要重新渲染一遍;使用key时,会在适当的时候插入新元素来完成更新。
计算属性computed和侦听属性watch区别
- computed支持缓存(建立了一个data变量里一个新属性),只有依赖数据发生改变时,才会重新进行计算;不支持缓存,数据便,直接会进行相应的操作。
- computed不支持异步;watch支持异步。
- computed(能在data里面添加属性)用来监控自己定义的变量,该变量不在data里面声明,直接在computed里面定义,然后就可以在页面上进行双向数据绑定展示出结果或者用作其他处理;computed比较合适对多个变量或者对象进行处理一个结果只,也就是数多个变量的某一个值发生了变化则我们监控的这个值也会发生变化。
- watch主要用于监控vue实例的变化,他监控的变量必须在data里面声明才可以,可监控一个变量或者一个对象。
- computed中get、set(监听属性,发生改变)
get:读值
set:设值,当computed监测的值变化时,set才会被调用
6.watch一般用于监控路由、input输入框的值特殊处理,他比较适合的场景是一个数据影响多个数据。无法监听数组的变化,解决方案:this.$set
keepAlive
项目主流程缓存优化,主流程页面(组件)切换时保持之前的加载状态,避免反复渲染,影响页面心梗,同时很大程度上减少接口请求,减少服务器压力。
使用了keepAlive内置组建后组件会增加哪两个生命周期函数
activated && deactivated:
activated:当组件为活跃状态的时候触发(活跃状态:进入页面的时候)
deactivated:缓存状态的时候触发
vue.$nextTick()
定义:在下次DOM更新循环结束后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
简单理解:当数据更新了,在dom中渲染后,自动执行该函数。
注意
vue生命周期的created()钩子函数进行的DOM操作一定要放在vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM其实并未进行任何渲染。
vue 路由跳转
- router-link :to=" "
- router.push
- 传参
1. 不带参数
<router-link :to="{name:'home'}">
<router-link :to="{path:'/home'}"> //name,path都行, 建议用name
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
2.带参数
<router-link :to="{name:'home', params: {id:1}}">
// params传参数 (类似post)
// 路由配置 path: "/home/:id" 或者 path: "/home:id"
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
<router-link :to="{name:'home', query: {id:1}}">
// query传参数 (类似get,url后面会显示参数)
// 路由可不配置
// html 取参 $route.query.id
// script 取参 this.$route.query.id
1. 不带参数
this.$router.push('/home')
this.$router.push({name:'home'})
this.$router.push({path:'/home'})
2. query传参
this.$router.push({name:'home',query: {id:'1'}})
this.$router.push({path:'/home',query: {id:'1'}})
// html 取参 $route.query.id
// script 取参 this.$route.query.id
3. params传参
this.$router.push({name:'home',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/home/:id" 或者 path: "/home:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
4. query和params区别
a.使用params传参只能用name来引入路由,即push里面只能是name:’xxxx’,不能是path:’/xxx’,因为params只能用name来引入路由,如果这里写成了path,接收参数页面会是undefined!!!。
b.使用query传参使用path来引入路由。
c.params是路由的一部分,必须要在路由后面添加参数名。query是拼接在url后面的参数,没有也没关系。
二者还有点区别,直白的来说query相当于get请求,页面跳转的时候,可以在地址栏看到请求参数,而params相当于post请求,参数不会再地址栏中显示。
$ router和$route
$ router:是路由操作对象,只写对象
$ route:是路由信息对象,只写对象
//操作 路由跳转
this.$router.push({
name:'hello',
params:{
name:'word',
age:'11'
}
})
//读取 路由参数接收
this.name = this.$route.params.name;
this.age = this.$route.params.age;
vue中set和this.$set
Vue.set(data,key,value),data可以是Array or Object.
在Vue中直接操作数组的下标,会改变数组,但是不会更新页面真实DOM,
原因是受 ES5 的限制,Vue.js 不能检测到对象属性的添加或删除。因为 Vue.js 在初始化实例时将属性转为 getter/setter,所以属性必须在 data 对象上才能让 Vue.js 转换它,才能让它是响应的.
区别: Vue.set 可以设置实例创建之后添加的新的属性,(在data里未声明的属性),而。this.$set只能设置实例创建后存在的属性
生命周期(每一个vue实例从创建到销毁的过程。经历了从开始创建,初始化教程,编译模板,挂载dom,渲染->更新->渲染,卸载等一系列过程。)
beforeCreate:创建前。执行完后,会开始进行数据初始化,在这个过程中,会定义data数据,方法以及事件,并完成数据劫持observe以及给组件实例
配置watcher观察者实例。
created:创建后。执行created时,已经可以拿到data下的数据和methods下的方法了,可以开始调用方法请求数据。created到beforeMount之间,
最主要的是将模板或者el转换为render函数。
beforeMount:挂载前。开始渲染render函数,首先会产生一个虚拟dom(用于后续数据变化时,新老虚拟dom对比计算),进行保存,然后再开始将render
渲染成真实的dom。将渲染出来的dom替换原来的vm.
e
l
,
然
后
再
将
替
换
的
el,然后再将替换的
el,然后再将替换的el append到我们的页面内。
mounted:挂载后。操作dom,dom已经渲染完成。
beforeUpdate:更新前。状态数据发生变化时,会触发beforeUpdate.beforeUpdate调用之后,会重新生成一个新的虚拟dom(VNode),之后新的VNode会和
旧的VNode去做一个diff计算.算出最小的更新范围,从而更新render函数中的最新数据,再将更新后的render函数渲染成真实的dom。也就完成了
我们的数据更新。
updated:更新后.可以操作dom,拿到最新并更新的dom。
beforeDestroy:销毁前。
destoryed:销毁后。
注:mounted和updated的执行,并不会等待所有子组件都被挂载完后在执行,所以你如果希望所有试图都更新完毕之后在做什么,最好在mounted或updated
加$nextTick()。
简述每个周期具体适合哪些场景
- beforecreate : 可以在这加个loading事件,在加载实例时触发
- created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜 在这里调用
- mounted : 挂载元素,获取到DOM节点
- updated : 如果对数据统一处理,在这里写上相应函数
- beforeDestroy : 可以做一个确认停止事件的确认框
- nextTick : 更新数据后立即操作dom
在哪个生命周期内调用异步请求
可以在钩⼦函数 created、beforeMount、mounted 中进⾏调⽤,因为在这三个 钩⼦函数中,data 已经创建,可以将服务端端返回的数据进⾏赋值。但是本⼈ 推荐在 created 钩⼦函数中调⽤异步请求,因为在 created 钩⼦函数中调⽤异步 请求有以下优点: 能更快获取到服务端数据,减少⻚⾯ loading 时间; ssr 不⽀持 beforeMount 、mounted 钩⼦函数,所以放在 created 中有助 于⼀致性
vue的单向数据流
数据从父级组件传递给子组件,只能单向绑定,子组件不能直接修改从父级传递过来的数据数据只能从一个方向来修改状态,如果父组件给N个子组件进行了数据传递。那么某一个子组件中修改了这个数据,那么就会导致其他组件的数据也会发生改变。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。因此数据只能从一个方向来修改状态
虚拟dom(Virtual DOM)[渲染速度提高,并降低了内存消耗,最终的目标是将虚拟节点渲染到视图上]
模板转换成视图的过程
1.vue.js通过编译template模板转换成渲染函数(render),执行渲染函数就可以得到一个虚拟节点树。
2.在对Model进行操作的时候,会触发对应Dep中Watcher对象。Watcher对象会调用对应的updata来修改试图。这个过程主要是将新旧虚拟节点进行
差异对比,然后根据对比差异结果进行DOM操作来更新视图。
简单来点说,在vue的底层实现上,vue将模板编译成虚拟DOM渲染函数。结合vue自带的响应系统,在状态改变时,vue能够智能的计算出重新渲染组件
的最小代价并应到DOM操作上。
注释:
VNode虚拟节点:它可以代表一个真实的dom节点,通过createElement方法能将VNode渲染成dom节点。简单地说,VNode可以理解为节
点描述对象,它描述了应该怎样去创建真实的DOM节点。
数组更新检测
变更方法
- push( )
- pop( )
- shift( )
- unshift( )
- splice( )
- sort( )
- reverse( )