Vue
组件通信
props/$emit
父子组件通信最常用的方式是通过props传递数据和$emit触发事件。 Vue props
eventBus
使用一个中央事件总线(eventBus)来实现跨组件通信。可以通过Vue实例或第三方库(如mitt)来实现。
js
const eventBus = new Vue()
eventBus.$on(eventName, callback)
eventBus.$emit(eventName, ...args)
eventBus.$off(eventName, callback)provide/inject
在Vue中,provide/inject是一种用于跨层级组件通信的方式。父组件可以通过provide提供数据,子组件可以通过inject注入数据。 vue 依赖注入
$parent/$children
在Vue中,$parent和$children是用于访问父组件和子组件的实例属性。可以通过这些属性来直接访问父子组件之间的数据和方法。
$attrs/$listeners
在Vue中,$attrs和$listeners是用于访问父组件传递给子组件的属性和事件监听器的实例属性。$attrs包含了父组件传递的非prop属性,$listeners包含了父组件传递的事件监听器。 vue 透传attributes
$refs
在Vue中,$refs是一个对象,用于访问组件或DOM元素的引用。可以通过$refs来直接访问子组件或DOM元素的实例。
Vuex
Vuex是Vue的状态管理库,用于集中管理应用的状态。可以通过Vuex来实现跨组件通信和状态共享。
vue框架原理
设计理念
vue核心设计理念是组件化和响应式数据驱动。通过虚拟DOM提升渲染效率。
响应式原理
- vue2 使用
Object.defineProperty来实现数据的响应式。通过劫持对象属性的getter和setter来追踪依赖和触发更新。 - vue3 使用
Proxy来实现数据的响应式。通过拦截对象的属性访问和修改来追踪依赖和触发更新。相比于vue2,vue3的响应式系统更高效、更灵活。 - vue2的响应式系统在处理数组时需要额外的处理,因为
Object.defineProperty无法劫持数组的索引和长度属性。vue3使用Proxy可以更好地处理数组的响应式。 - vue3的响应式系统支持更复杂的数据结构,如Map、Set等。vue2的响应式系统只支持对象和数组。
js
// Vue 3响应式原理(简化)
const reactive = (target) => {
return new Proxy(target, {
get(target, key) {
track(target, key); // 依赖收集
return target[key];
},
set(target, key, value) {
target[key] = value;
trigger(target, key); // 触发更新
return true;
}
});
};虚拟DOM
虚拟 DOM 就是用 JS 来描述一个真实的 DOM 节点,vue 是通过 createElement 生成 VNode。
包括标签名、属性、子节点等信息。虚拟 DOM 的主要目的是为了提高性能,减少直接操作真实 DOM 的开销。
- vue3优化
- 使用静态标记,diff时直接跳过,提升性能。
js// 编译后带PatchFlag的VNode h('div', { class: 'container' }, [ h('span', null, '静态文本', PatchFlag.STATIC), // 静态节点 h('span', null, this.message, PatchFlag.TEXT) // 动态文本 ]);- 动态节点封装为Block,形成 BlockTree,减少重复计算。
- 支持自定义渲染器,如WebGL,Canvas等
Diff算法
Vue 的 diff算法基于双指针和同层比较策略。
- 双指针:通过两个指针分别指向新旧虚拟 DOM 的开始和结束位置,逐步比较。
- 同层比较:只比较同一层级的节点,避免跨层级比较带来的性能开销。通过key来优化节点的复用和移动。
- Vue VS React的Diff算法
- Vue的Diff算法更注重性能优化,使用静态标记和BlockTree来减少重复计算。
- React的Diff算法更注重灵活性和可扩展性,支持更多的渲染器和平台。使用Fiber架构来实现异步渲染和优先级调度。