-
所谓数据响应式就是用户对数据层做的更改能够触发视图层做出更新响应的机制。
-
mvvm框架中要解决的⼀个核心问题是连接数据层和视图层,通过数据驱动应用,数据变化,视图更新,要做到这点的就需要实现⼀套响应式机制,这样⼀旦数据发生变化就可以立即做出更新处理。
-
以vue为例说明,通过数据响应式加上虚拟DOM和patch算法,可以使我们只需要操作数据,完全不用接触繁琐的dom操作,从而大大提升开发效率,降低开发难度。
-
vue2中的数据响应式会根据数据类型来做不同处理,如果是对象则采用Object.defineProperty()的方式定义数据拦截,当数据被访问或发生变化时,我们感知并作出响应;如果是数组则通过覆盖该数组原型的方法,扩展它的7个变更方法,使这些方法可以额外的做更新通知,从而作出响应。这种机制很好的解决了数据响应化的问题,但在实际使用中也存在⼀些缺点:比如初始化时的递归遍历会造成性能损失;新增或删除属性时需要用户使用Vue.set/delete这样特殊的api才能生效;对于es6中新产生的Map、Set这些数据结构不⽀持等问题。
-
为了解决这些问题,vue3重新编写了这⼀部分的实现:利用ES6的Proxy机制代理要响应化的数据,它有很多好处,编程体验是⼀致的,不需要使用特殊api,初始化性能和内存消耗都得到了大幅改善;另外由于响应化的实现代码抽取为独立的reactivity包,使得我们可以更灵活的使用它,我们甚至不需要引⼊vue都可以体验。
-
nextTick是Vue提供的⼀个全局API,由于vue的异步更新策略导致我们对数据的修改不会立刻体现在dom变化上,此时如果想要立即获取更新后的dom状态,就需要使用这个方法
-
Vue在更新DOM时是异步执行的。只要侦听到数据变化,Vue将开启⼀个队列,并缓冲在同⼀事件循环中发生的所有数据变更。如果同⼀个watcher被多次触发,只会被推⼊到队列中⼀次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作是⾮常重要的。nextTick方法会在队列中加⼊⼀个回调函数,确保该函数在前面的dom操作完成后才调用。
-
所以当我们想在修改数据后立即看到dom执行结果就需要用到nextTick方法。
-
比如,我在干什么的时候就会使用nextTick,传⼀个回调函数进去,在里面执行dom操作即可。
-
我也有简单了解nextTick实现,它会在callbacks里面加⼊我们传⼊的函数,然后用timerFunc异步方式调用它们,首选的异步方式会是Promise。这让我明白了为什么可以在nextTick中看到dom操作结果。
-
key的作用主要是为了更高效的对比虚拟DOM中的某个节点是否是相同节点。
-
vue在patch过程中判断两个节点是否是相同节点是key是⼀个必要条件,渲染⼀组列表时,key往往是唯⼀标识,所以如果不定义key的话,vue只能认为比较的两个节点是同⼀个,哪怕它们实际上不是,这导致了频繁更新元素,使得整个patch过程比较低效,影响性能。
-
实际使用中在渲染⼀组列表时key必须设置,而且必须是唯⼀标识,应该避免使用数组索引作为key,这可能导致⼀些隐蔽的bug;vue中在使用相同标签元素过渡切换时,也会使用key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
-
从源码中可以知道,vue判断两个节点是否相同时主要判断两者的key和元素类型等,因此如果不设置key,它的值就是undefined,则可能永远认为这是两个相同节点,只能去做更新操作,这造成了大量的dom更新操作,明显是不可取的。
-
vuex是vue专用的状态管理库。它以全局方式集中管理应用的状态,并且可以保证状态变更的可预测性。
-
vuex主要解决的问题是多组件之间状态共享的问题,利用各种组件通信方式,我们虽然能够做到状态共享,但是往往需要在多个组件之间保持状态的一致性,这种模式很容易出现问题,也会使程序逻辑变得复杂。vuex通过把组件的共享状态抽取出来,以全局单例模式管理,这样任何组件都能用一致的方式获取和修改状态,响应式的数据也能够保证简洁的单向数据流动,我们的代码将变得更结构化且易维护。
-
vuex并非必须的,它帮我们管理共享状态,但却带来更多的概念和框架。如果我们不打算开发大型单页应用或者我们的应用并没有大量全局的状态需要维护,完全没有使用vuex的必要。一个简单的store 模式就足够了。反之,Vuex 将会成为自然而然的选择。引用 Redux 的作者 Dan Abramov 的话说就是:Flux 架构就像眼镜:您自会知道什么时候需要它。
-
我在使用vuex过程中有如下理解:首先是对核心概念的理解和运用,将全局状态放入state对象中,它本身一棵状态树,组件中使用store实例的state访问这些状态;然后有配套的mutation方法修改这些状态,并且只能用mutation修改状态,在组件中调用commit方法提交mutation;如果应用中有异步操作或者复杂逻辑组合,我们需要编写action,执行结束如果有状态修改仍然需要提交mutation,组件中调用这些action使用dispatch方法派发。最后是模块化,通过modules选项组织拆分出去的各个子模块,在访问状态时注意添加子模块的名称,如果子模块有设置namespace,那么在提交mutation和派发action时还需要额外的命名空间前缀。
-
vuex在实现单项数据流时需要做到数据的响应式,通过源码的学习发现是借用了vue的数据响应化特性实现的,它会利用Vue将state作为data对其进行响应化处理,从而使得这些状态发生变化时,能够导致组件重新渲染。
- vue2数据响应式实现根据对象类型做不同处理,如果是object,则通过Object.defineProperty(obj,key,descriptor)拦截对象属性访问
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
return val
},
set(v) {
val = v
notify()
}
})
}
如果是数组,则覆盖数组的7个变更方法实现变更通知
const arrayProto = Array.prototype
const arrayMethods = Object.create(arrayProto)
;[‘push’,‘pop’,‘shift’,‘unshift’,‘splice’,‘sort’,‘reverse’]
.forEach(function (method) {
const original = arrayProto[method]
def(arrayMethods, method, function mutator (…args) {
const result = original.apply(this, args)
notify()
return result
})
})
- 可以看到vue2中有几个问题:
初始化时需要遍历对象所有key,如果对象层级较深,性能不好
通知更新过程需要维护大量dep实例和watcher实例,额外占用内存较多。
动态新增、删除对象属性无法拦截,只能用特定set/delete api代替
不支持新的Map、Set等数据结构。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
总结一下这三次面试下来我的经验是:
-
一定不要死记硬背,要理解原理,否则面试官一深入就会露馅!
-
代码能力一定要注重,尤其是很多原理性的代码(之前两次让我写过Node中间件,Promise.all,双向绑定原理,被虐的怀疑人生)!
-
尽量从面试官的问题中表现自己知识的深度与广度,让面试官发现你的闪光点!
-
多刷面经!
我把所有遇到的面试题都做了一个整理,并且阅读了很多大牛的博客之后写了解析,免费分享给大家,算是一个感恩回馈吧,有需要的朋友【点击我】免费获取。祝大家早日拿到自己心怡的工作!
篇幅有限,仅展示部分内容
ac0b1c2376da47d727e0dc8a77e76478.png)