实际工作经验 - 面试题


考察重点

  • 性能优化,错误监控
  • 设计模式的应用
  • 项目难点,角色之间的沟通

Vue 应该如何监听 JS 报错 ?

  • 全局错误捕获(全局监听)a. Vue.config.errorHandler在 Vue 实例初始化之前,可以通过配置 Vue 的全局错误处理器 Vue.config.errorHandler 来捕获整个应用程序中的未处理错误。
  • 生命周期钩子 errorCapturedVue 2.x 提供了一个实例级别的错误捕获钩子 errorCaptured,可以在组件树的任何地方捕获和处理错误
  • window.onerror 和 window.addEventListener(‘error’)对于非 Vue 组件内部引发的全局错误,可以监听全局的 window.onerror 事件
  • Vue 3.x 的全局异常捕获在 Vue 3.x 中,可以使用 app.config.globalProperties.$onError
// 1. 全局错误捕获(全局监听)a Vue.config.errorHandler在 Vue 实例初始化之前,可以通过配置 Vue 的全局错误处理器 Vue.config.errorHandler 来捕获整个应用程序中的未处理错误。
import Vue from 'vue'; 
Vue.config.errorHandler = function (err, vm, info) {
  // err:错误对象
  // vm:当前 Vue 实例
  // info:Vue 特性相关的错误信息,如在 render 函数中发生的错误
  console.error(err, info);
  // 这里可以加入上报错误到服务器、显示错误提示等功能
};

// 2. 生命周期钩子 errorCapturedVue 2.x 提供了一个实例级别的错误捕获钩子 errorCaptured,可以在组件树的任何地方捕获和处理错误:Vue.component('YourComponent', {
  // ...
  errorCaptured(err, vm, info) {
    // 同样可以在这里处理错误
    console.error(err, info);
    // ...
  },
  // ...
});

// 3. window.onerror 和 window.addEventListener('error')对于非 Vue 组件内部引发的全局错误,可以监听全局的 window.onerror 事件:window.onerror = function (errorMessage, fileName, lineNumber, columnNumber, error) {
  // 处理错误逻辑
  console.error(errorMessage, fileName, lineNumber, columnNumber, error);
};

// 或者使用 addEventListener
window.addEventListener('error', function(event) {
  const { message, filename, lineno, colno, error } = event;
  console.error(message, filename, lineno, colno, error);
  // 错误处理逻辑
});

// 4. Promise 的 unhandledrejection 事件对于未处理的 Promise 拒绝,可以监听 window 的 unhandledrejection 事件:window.addEventListener('unhandledrejection', function(event) {
  const reason = event.reason;
  const promise = event.promise;
  const handler = event.handledByCode ? 'handledByCode' : 'unhandled';
  
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // 错误处理逻辑
});

// 5. Vue 3.x 的全局异常捕获在 Vue 3.x 中,可以使用 app.config.globalProperties.$onError:const app = createApp(App);

app.config.globalProperties.$onError = (err, instance, info) => {
  // 处理错误逻辑
  console.error(err, instance, info);
};

app.mount('#app'); 

你遇到了哪些项目难点?如何解决的?

描述问题:背景+现象+造成的影响
问题如何被解决:分析 + 解决
自己的成长:学到了什么 + 以后如何避免

你使用vue遇到过哪些坑?

  • 路由切换时 scroll 到顶部
    • SPA 的通病,不仅仅是 Vue
    • 如列表页,滚动到第二屏,点击进入详情页
    • 解决:在列表页缓存数据和 scrollTop 值,当再次返回列表页时,渲染组件,执行 scrollTo(xx)
  • 路由切换时 scrol 到顶部

你在实际工作中,做过哪些vue优化

  • v-if和v-show (算一个优化点,但实际工作中基本都用v-if,用不上v-show)
  • v-for使用key (算一个优化点,但写代码时会强制你写上key,不写会报错)
  • 使用computed缓存
  • keep-alive缓存组件:
    • 频繁切换的组件,如 tabs
    • 不要乱用,缓存太多会占用内存,且不好 debug
  • 异步组件
    • 针对体积较大的组件,如编辑器、复杂表格,复杂表单等
    • 拆包,需要时异步加载,不需要时不加载
    • 减少主包的体积,首页会加载更快
  • 路由懒加载
  • 服务端渲染SSR

chatGPT回答

  • 列表渲染优化
    • 使用 v-for 时为每个循环项分配一个唯一的 key,确保Vue能够准确地跟踪每个节点的变化,从而更高效地进行DOM更新。
    • 对于大型列表,考虑使用虚拟滚动(virtual scrolling)技术,只渲染可视区域内的元素。
  • 组件懒加载
    • 通过Vue的异步组件功能或者Webpack的动态导入功能,将非首屏显示的组件延迟加载,减少初次加载时的资源开销。
  • 事件代理
    • 在使用 v-for 渲染大量具有相同事件处理器的元素时,可以将事件委托到它们的父级元素上,避免为每个子元素单独绑定事件监听器。
  • 状态管理与计算属性优化
    • 合理划分组件状态,避免在不必要的地方过度依赖全局状态管理(如Vuex)
    • 尽量利用计算属性(computed)缓存结果,减少重复计算。
  • 代码分割与懒加载:
    • 对路由配置进行懒加载设置,使得不同的路由对应的组件按需加载。
    • 分离通用库和业务逻辑代码,合理使用代码分割实现按需加载JS和CSS资源。
  • 资源优化
    • 图片资源使用懒加载,只有当图片进入视窗时才开始加载。
    • 使用GZIP压缩、CDN加速、文件最小化(minify)等方式优化静态资源。
  • Vue实例优化
    • 减少data对象中的属性数量,特别是不需要响应式的可以直接定义为普通对象或变量
    • 注意避免在生命周期钩子中进行大量计算密集型或IO操作,可考虑异步处理
  • Keep-Alive缓存
    • 对于需要频繁切换但又不希望每次都重新渲染的组件,可以使用 组件进行缓存。
  • SSR(Server-Side Rendering)与预渲染
    • 对SEO要求较高的页面或者希望改善首屏加载速度的应用,可以采用服务端渲染(SSR)或静态预渲染(prerender-spa-plugin)

设计模式

设计原则: 最重要的思想:开放封闭原则,对扩展开放,对修改封闭
设计模式:

  • 工厂模式
    • 用一个工厂函数,来创建实例,隐藏 new
    • 如 jQuery$ 函数
    • 如 React createElement 函数
  • 单例模式
    • 全局唯一的实例(无法生成第二个)
    • 如Vuex Redux 的 store
    • 如全局唯一的 dialog modal
  • 代理模式
    • 使用者不能直接访问对象,而是访问一个代理层
    • 在代理层可以监听 get set 做很多事情
    • 如ES6 Proxy实现Vue3响应式
    • 阮一峰es6入门 - proxy:Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
  • 观察者模式:一个主题一个观察者,主题变化之后触发观察者执行
  • 发布订阅模式:自定义on一个事件,emit触发
  • 装饰器模式:
    • 原功能不变,增加一些新功能(AOP 面向切面编程)
    • ES 和Typescript的 Decorator 语法
    • 类装饰器,方法装饰器
    • 阮一峰es6入门 - 装饰器
// 工厂模式
class Foo { } 
function factory(a, b, c) {
    return new Foo()
} 
const f = factory(1, 2, 3)

// 单例模式 
class SingleTon {
    private constructor() {}
    public static getInstance(): SingleTon {
        return new SingleTon()
    }
    fn1() {}
    fn2() {}
}

const s = SingleTon.getInstance()
s.fn1()
s.getInstance() // 报错

// 观察者模式
btn.addEventListener('click',()=>{...})

// 发布订阅模式
event.on('event-key', fn1) // on绑定事件事件1 - mounted
event.on('event-key', fn2) // on绑定事件事件2 
event.emit('event-key') // 触发执行
event.off('event-key', fn1) // beforeUnmount 时解绑,防止内存泄漏

// 装饰器模式

观察者模式和设计者模式的区别

  • 观察者模式
    • Subject和 Observer 直接绑定,没有中间媒介
    • 如 addEventlistener 绑定事件
  • 发布订阅
    • Publisher 和 Observer 互不相识,需要中间媒介 Event channel
    • 如 EventBus 自定义事件
      观察者模式和设计者模式

后端返回10W条数据怎么渲染

  • 设计不合理
  • 虚拟列表:虚拟列表实现起来非常复杂,可借用第三方 lib,Vue-virtual-scroll-list,React-virtualiszed
    • 只渲染可视区域 DOM
    • 其他隐藏区域不显示,只用< div>撑起高度
    • 随着浏览器滚动,创建和销毁 DOM

H5 页面如何进行 ** 首屏 ** 优化 ?

咱也没写过H5啊,为啥有这么多乱七八糟的东西

  • 路由懒加载
    • 适用于SPA(不适用于MPA)
    • 路由拆分,优先保证首页加载
  • 服务端渲染SSR
    • 传统的前后端分离(SPA)渲染页面的过程复杂
    • SSR 渲染页面过程简单,所有性能好
    • 如果是纯 H5 页面,SSR 是性能优化的终极方案
  • App 预取
    • 如果 H5 在 App WebView 中展示,可使用 App 预取
    • 用户访问列表页时,App 预加载文章首屏内容
    • 用户进入 H5 页,直接从 App 中获取内容,瞬间展示首屏
  • 图片懒加载 lazyLoad
    • 针对详情页
    • 默认只展示文本内容,然后触发图片懒加载
    • 注意:提前设置图片尺寸,尽量只重绘不重排
  • Hybrid
    • 提前将 HTML JS CSS 下载到 App 内部
    • 在 App webview 中使用 file://协议加载页面文件
    • 再用 Ajax 获取内容并展示(也结合 App 预取 )
  • 分页
  • 服务端 SSR 是 H5 的终极优化方案(但成本也高),移动端 H5 要结合 App 能力去优化,严格来说,hybrid 不是 H5,但这里回答出来没问题
  • 23
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值