[Vue] 组件之间的通信方式有哪些?
-
Props/Attributes:父组件通过向子组件传递属性(props),子组件通过props接收父组件传递的数据。这是一种单向数据流的方式。
-
Events/Custom Events:子组件可以通过触发自定义事件($emit),向父组件发送消息。父组件可以监听子组件的自定义事件,在事件回调中处理接收到的消息。
-
$refs:父组件可以通过在子组件上使用ref属性,获取子组件的实例,并直接调用子组件的方法或访问子组件的属性。
-
Event Bus:通过创建一个全局事件总线实例,可以在任何组件中触发和监听事件。组件之间可以通过事件总线进行通信。
-
Vuex/pinia:Vuex是Vue官方提供的状态管理库,用于在组件之间共享状态。组件可以通过Vuex的store来进行状态的读取和修改。
-
Provide/Inject:父组件通过provide选项提供数据,子组件通过inject选项注入数据。这样可以在跨层级的组件中进行数据传递。
-
浏览器缓存:localstorage/sessionstorage/cookie
-
路由跳转:在不同的组件跳转时通过router对象获取传递的信息
衡量页面性能的指标有哪些?
页面的性能可以通过一系列客观的度量指标来进行计算和评估。以下是一些关键的页面性能指标以及相应的计算方法:
加载时间指标:
首次内容绘制(First Contentful Paint, FCP):测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。这个指标反映了用户在屏幕上看到第一个内容元素的时间。
首次有效绘制(First Meaningful Paint, FMP):当主要内容呈现在页面上的时间。这标志着用户可以看到页面主要内容的时间点。
文档完全加载时间(Document Complete Time):所有资源(如HTML、CSS、JavaScript和图片)完成加载的时间。这反映了页面整体加载完成的速度。
交互性指标:
可交互时间(Time to Interactive, TTI):页面布局已经稳定,关键的页面内容是可见的,并且主进程可用于处理用户输入的时间。这表示用户可以开始与页面进行交互。
输入响应(Input responsiveness):界面响应用户输入所需的时间。一个快速的响应时间意味着页面能够迅速地对用户操作作出反应。
视觉稳定性指标:
- 累积布局偏移(Cumulative Layout Shift, CLS):测量页面在加载过程中发生的所有意外布局偏移的累积分数。一个较低的CLS分数意味着页面在加载过程中具有更好的视觉稳定性。
资源加载指标:
首字节时间(Time to First Byte, TTFB):从请求开始到收到服务器响应的第一个字节所花费的时间。这个指标反映了服务器响应请求的速度。
总阻塞时间(Total Blocking Time, TBT):在FCP与TTI之间,主线程被阻塞且无法执行任何任务的总时间。减少TBT可以提高页面的交互性。
优化页面性能的方法包括但不限于压缩图片、使用CDN加速资源加载、合并和压缩CSS和JavaScript文件、减少HTTP请求、使用缓存等。定期进行页面性能测试并根据测试结果进行相应的优化调整,可以显著提升页面的加载速度和用户体验。
proxy 能够监听到对象中的对象的引用吗?
Proxy监听对象中嵌套对象的引用,在访问或修改嵌套对象时触发相应的代理处理器方法。这种特性通常称为“深度监听”或“懒监听”。
在 Proxy 的陷阱(trap)函数中,当你尝试访问目标对象的某个属性,如果该属性值也是一个对象,你可以选择返回一个新的 Proxy 实例来代理这个嵌套对象,从而实现深度监听。例如,在 get 陷阱中,你可以检查获取的属性是否为对象,如果是,则返回其对应的 Proxy。
const obj = {
nestedObj: { foo: 'bar' }
}
const handler = {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver)
if (typeof value === 'object' && value !== null) {
return new Proxy(value, handler)
}
console.log('get', prop, target[prop])
return value
},
set(target, property, value) {
target[property] = value
console.log(`Setting property '${property}' to '${value}'`)
return true
}
}
const proxyObj = new Proxy(obj, handler)
proxyObj.nestedObj.foo = 'baz' // 输出: Setting property 'foo' to 'baz'
这样一来,对于任何嵌套层次的对象属性访问或修改,只要涉及到的对象都被包装进了 Proxy,就可以全面地监听到对象内部的变化。不过需要注意的是,这样的实现通常不会自动递归地对整个嵌套结构预先进行 Proxy 包装,而是在实际访问或修改时动态创建和返回 Proxy。这就是所谓的“懒监听”
在创建对象的时候, new class 和 new function 可有什么区别
主要区别
- 语法和语义:
class提供了一种清晰、模块化的方式来定义构造函数和原型方法。通过class关键字声明类使得代码更加直观易懂。 - 继承:使用
class语法,可以通过extends关键字更加简洁地实现继承。而在传统的函数式继承中,需要手动设置原型链。 - 严格模式:使用
class语法定义的类的方法自动运行在严格模式下("use strict"),而传统的构造函数则需要手动声明。 - 构造函数和原型方法的声明:
class语法使得构造函数和原型方法的声明更加直观和组织化,而在传统的构造函数中,需要分别设置构造函数的属性和其原型的方法。
结论
虽然new function()和new class都可以用来创建新的对象实例,但class提供了更现代、更丰富的语法和特性,使得代码更加直观、易于管理和维护。然而,重要的是理解两者在 JavaScript 底层使用相同的原型继承机制。