Vue
1.数据双向绑定原理
通过数据劫持结合发布-订阅模式,通过Object.defineProperty()为各个属性定义get、set方法,在数据发生改变时给订阅者发布消息,触发响应的事件回调。
2.Vue生命周期
从创建、初始化数据、编译模板、挂载DOM、渲染-更新-渲染、卸载等一系列过程,称为Vue实例的生命周期。
Vue2.0
beforeCreate创建前、created创建完成、beforeMount挂载前、mounted挂载完成、beforeUpdate更新前、updated更新后、beforeDestroy销毁前、destroyed销毁后
其他:activated:在keep-alive组件激活时调用 deactivated:在keep-alive组件停用时调用
Vue3.0
onBeforeMount、onMounted、onBeforeUpdate、onUpdated、onBeforeUnmount、onUnmounted
3.组件之间如何传值
(1) Vue父子组件之间传值
子组件通过props来接受数据和通过$emit来触发父组件的自定义事件;
(2) 兄弟组件之间的传值
建一个公共组件bus.js。传递方通过事件触发bus.$emit.接收方通过在mounted(){}生命周期里触发 bus.$on
(3) 可以通过VUEX来跨组件传参
(4) 父孙传值
$attrs(向下) $listeners(向上)
(5) 祖先和子孙传值
provide、inject
(6) 获取父组件实例
this.$parent
4. Vuex
原理:Vuex是专门为vue.js应用程序设计的状态管理工具。
构成:
- state : vuex的基本数据,用来存储变量,存放的数据是响应式的。
- mutations : 提交更改数据,同步更新状态。
- actions : 提交mutations,可异步操作
- getters:是store的计算属性
- modules:模块,每个模块里面有四个属性。
5. 如何解决VUEX页面刷新数据丢失问题?
原因:因为vuex里的数据是保存在运行内存中的,当页面刷新时,页面会重新加载vue实例,vuex里面的数据就会被清空。
解决方法:将vuex中的数据直接保存到浏览器缓存中。
另一种方法:使用插件vuex-persistedstate。
可以将Vuex store的状态持久化存储到浏览器的localStorage或sessionStorage中,是的用户下次打开页面时能够继续使用之前的应用状态。
6. computed和watch的区别?
computed值有缓存,触发条件是依赖值发生改变;watch无缓存支持异步、监听数据变化。
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值; watch: 更多的是观察的作用,支持异步,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;
computed应用场景:需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算; watch应用场景:需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
7.vue中数据变了但是视图不更新怎么解决?
解决方法:数组长度变化可以用splice来修改,需要监听某个属性的变化用 $set。
8.vue中data为什么是函数而不是对象?
在vue中组件是可以被复用的,而当data是一个函数的时候,每一个实例的data都是独立的,不会相互影响了。
9.vue中父子组件传值,父组件异步请求,子组件不能实时更新怎么解决?(vue中数据不能实时更新怎么解决?)
原因:因为生命周期只会执行一次,数据是要等到异步请求以后才能拿到,那么子组件的mounted钩子执行的时候,还没有拿到父组件传递过来的数据,但是又必须要打印出来结果,那这样的话,就只能去打印props中的默认值空字符串了,使用打印的结果是一个空字符串。
解决方法:
-
使用v-if控制组件渲染的时机
初始还没拿到后端接口的异步数据的时候,不让组件渲染,等拿到的时候再去渲染组件。使用v-if=“变量”去控制,初始让这个变量为false,这样的话,子组件就不会去渲染,等拿到数据的时候,再让这个变量变成true。
-
使用watch监听数据的变化
-
使用vuex
10.vue路由跳转方式
- router-link 标签跳转
- this.$router.push()
- this.$router.replace()
- this.$router.go(n) (0:当前页,-1上一页,+1下一页,n代表整数)
11.vue中 $nextTick 作用于原理?
异步渲染、获取DOM、Promise等。
Vue 在更新 DOM 时是异步执行的,在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。所以修改完数据,立即在方法中获取DOM,获取的仍然是未修改的DOM。
$nextTick的作用是:该方法中的代码会在当前渲染完成后执行,就解决了异步渲染获取不到更新后DOM的问题了。
$的原理:nextTick 的原理: $nextTick本质是返回一个Promise 。
应用场景:
在created()里面想要获取操作Dom,把操作DOM的方法放在nextTick时,当data中的数据修改后,可以实时的渲染页面
-
12. vue中for循环为什么加key?
为了性能优化优化diff算法, 因为vue是虚拟DOM,更新DOM时用diff算法对节点进行一一比对,比如有很多li元素,要在某个位置插入一个li元素,但没有给li上加key,那么在进行运算的时候,就会将所有li元素重新渲染一遍,但是如果有key,那么它就会按照key一一比对li元素,只需要创建新的li元素,插入即可,不需要对其他元素进行修改和重新渲染。 key也不能是li元素的index,因为假设我们给数组前插入一个新元素,它的下标是0,那么和原来的第一个元素重复了,整个数组的key都发生了改变,这样就跟没有key的情况一样了。
13.vue2和vue3的区别?
(1) 双向数据绑定原理不同
-
vue2的双向数据绑定是利用Object.defineProperty()对数据进行劫持,结合发布订阅模式的方式来实现的。
-
vue3中使用Proxy API对数据代理。
(2) API类型不同
- vue2使用选项类型的api。
- vue3就需要使用一个新的setup()方法。
(3) 生命周期不同
(4) 父子传参不同
(5) 指令与插槽不同
(4) 是否支持碎片
- vue2不支持碎片
- vue3支持碎片,可以拥有多个根节点
14.vue路由中的history和hash的区别
- 地址栏带不带“#”号
hash:http://localhost:8080/#/
history:http://localhost:8080/
-
都是利用浏览器的两种特性实现前端路由
history是利用浏览历史记录栈的API实现 hash是监听location对象hash值变化事件来实现
-
相同的url
history会触发添加到浏览器历史记录栈中,hash不会触发, history需要后端配合,如果后端不配合刷新页面会出现404,hash不需要
hashRouter原理:通过window.onhashchange获取url中hash值
historyRouter原理:通过history.pushState,使用它做页面跳转不会触发页面刷新,使用window.onpopstate监听浏览器的前进和后退
15.Vue Diff算法
Diff算法是指对比两个树形结构的不同,这种算法最早有应用于文本编辑器的对比修改,而在前端领域中,则用于对比真实DOM树和虚拟DOM树,然后将该树与旧的virtual DOM树进行对比,并将差异更新到真实的DOM树上。这个对比的过程就是一个Diff算法。
具体来说,Vue中Diff算法是指对比两个virtual DOM树的差异,并且尽量找出一种最小的变更方式来完成从旧的virtual DOM到新的 virtual DOM的转换。这种方式非常高效,因为不需要每次对真实 DOM 进行重新渲染,而只需要找出变更的部分,更新到真实 DOM 上即可。
在比较两个 virtual DOM 树的差异时,Vue 的 Diff 算法采用的是递归遍历,先比较节点的类型,如果不同,则不再遍历其子节点,直接判断为需要替换当前节点;否则比较节点的属性和子节点,依照节点的属性、子节点排序等,找到最优的更新方式。
Vue 中的优化策略 在 Vue 的 diff 算法中引入了一些优化策略,以减少不必要的 diff 操作,提高 diff 性能,具体来说,有以下几点:
-
模板编译时静态节点标记
Vue 在模板编译时,会对那些不需要变更的静态节点做标记,这样在后续渲染时,就可以省略对这些节点进行 diff 操作,减少 diff 的复杂度,提高性能。
-
列表遍历的 key 值优化
在 Vue 中,当对一个列表进行遍历时,我们通常会为每个子元素指定一个 key 值来唯一标识它们,以便于后续的 diff 操作。在这个过程中,Vue 会通过记录 key 值来对比新旧节点是否发生了变化,如果没有变化,则会保留该节点对应的状态,避免不必要的重复渲染。
-
相同节点的合并优化
在 diff 算法中,如果新旧节点是相同节点(即两个节点都是相同的标签和属性),并且都不需要更新子节点,则认为这两个节点是相同的,可以直接跳过对该节点的 diff 操作,提高 diff 性能。
Vue 的 diff 算法是一种高效的前端响应式实现方式,能够快速地对比新旧节点间的差异,并快速更新页面视图,提升了用户体验和程序性能。