前端面试拼图-实践经验

摘要:最近,看了下慕课2周刷完n道面试题,记录并添加部分可参考的文档,如下...

1. 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,但这里回答也没有问题

        扩展:SSR

        SSR(Server-Side Rendering,服务器端渲染)是一种将页面内容在服务器端生成并直接返回给客户端的技术。相比于传统的客户端渲染(CSR,Client-Side Rendering),SSR 在首次加载页面时可以直接呈现出完整的 HTML 内容,而不需要等待 JavaScript 文件下载和执行完成后再进行页面渲染,从而提高了首屏加载速度搜索引擎优化(SEO)效果适用于内容密集型页面

        SSR是一门"古老"的技术,刚刚兴起Web1.0时,就是SSR技术:PHP ASP JSP等

Nuxt.js(Vue) 安装 - NuxtJS | Nuxt.js 中文网Nuxt.js 十分简单易用。一个简单的项目只需将 `nuxt` 添加为依赖组件即可。icon-default.png?t=N7T8https://www.nuxtjs.cn/guide/installation

Next.js(React) Next.jsNext.js 是一个轻量级的 React 服务端渲染应用框架。icon-default.png?t=N7T8https://nextjs.frontendx.cn/

2. 后端一次性返回10w条数据,你该如何渲染?

        后端返回10W条数据,本身技术方案设计不合理;

        JS可以处理10w条数据,但是渲染的DO会非常卡顿;

        自定义中间层

        自定义node.js中间层,获取并拆分这10W条数据

        前端对接node.js中间层(后端的问题优先考虑用后端的思维解决,中间件),而不是服务端

        成本比较高

        虚拟列表

        只渲染可视区域DOM

        其他区域不显示,只用<div>撑起高度

        随着浏览器滚动,创建和销毁DOM

        虚拟列表实现起来非常复杂(且效果不一定好,例如低配手机),可借用第三方lib,例如Vue-virtual-scroll-list、 React-virtualiszed

3. 前端常用的设计模式有哪些?并说明使用场景

        设计原则

        最重要的思想:开放封闭原则

        对扩展开放

        对修改封闭

        工厂模式

        用一个工厂那个函数,来创建实例,隐藏new

        如jQuery $函数,React 的createElement函数

class Foo{}
// 工厂模式
function factory(a, b, c) {
  // if else
  return new Foo()
}
const f = factory(1, 2, 3)

        单例模式

        全局唯一的实例(无法生成第二个)

        如Vuex Redux的store ;如全局唯一的dialog modal

class SingleTon {
  private static instance: SingleTon | null = null
  private constructor() {}
  public static getInstance():SingleTon {  // 静态方法,属于类不属于实例
    if (this.instance = null) {
      this.instance = new SingleTon()
    }
    return this.instance
  }
  fn1() {}
  fn2() {} //实例方法
}

const s = SingleTon.getInsance()
s.fn1()
const s1 = SingleTon.getInsance()
**s===s1   //true**

扩展:JS是单线程的,创建单例很简单;

        Java是支持多线程的,创建单例要考虑锁死线程,否则多个线程同时创建,单例就重复了(多线程共享进程内存)

        代理模式

        使用者不能直接访问对象,而是访问一个代理层

        在代理层可以监听get set 做很多事情,如ES6的Proxy 实现Vue3的响应式

Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写

ES6 入门教程icon-default.png?t=N7T8https://es6.ruanyifeng.com/#docs/proxy

        观察者模式(Observer Pattern)

        当一个对象的改变需要同时改变其他对象,并且不知道有多少对象需要改变时,可以使用观察者模式。例如,在事件监听、数据订阅等场景下可以使用观察者模式

// 一个主题,一个观察者,主题变化后触发观察者执行
btn.addEventListener('click', () => {...})

        发布订阅模式(Publish-Subscribe Pattern)

        主要用于解耦组件之间的通信,实现松耦合的架构。在事件总线、消息队列、数据订阅等场景广泛使用,例如事件总线在非父子组件之间传递数据或触发特定操作

// 绑定
event.on('event-key', () => {
  //事件1
})
event.on('event-key', () => {
  //事件2
})
// 触发执行
event.emit('event-key')

        装饰器模式

        是一种结构型设计模式,它允许向一个对象动态地添加新的功能,同时又不改变其结构。

        原功能不变,增加一些新功能(AOP面向切面编程),例如 Node.js 框架Nest.js

        ES和TypeScript的Decorator语法

        @testable就是一个类装饰器。它修改了MyTestableClass这个类的行为,为它加上了静态属性isTestable。testable函数的参数target是MyTestableClass类本身。

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true

        扩展:观察者模式和发布订阅模式的区别?

        观察者模式:Subject和Observer直接关联,没有中间媒介,如addEventListener绑定事件

        发布订阅模式:Publisher和Observer是松散耦合的,需要中间媒Event channel,如EventBus;发布者不直接与订阅者通信,而是将消息发布到消息代理,然后由代理负责将消息传递给所有订阅者

4. 实际工作中,做过那些Vue的优化?

        v-if 和v-show

        v-if 是条件渲染指令, 条件改变时会彻底销毁和创建组件,最初渲染消耗较小;

        v-show使用CSS display 属性来控制元素的显示与隐藏,切换性能开销较小,适用于频繁切换场景;

        大部分时候使用v-if更好,不要过度优化

        v-for使用key,且避免同时和v-if同时使用

        严格意义已经不能算优化项了,v-for不是key会报警;

        v-for的优先级比v-if高(vue2),因为这样会导致每次渲染都进行条件判断,影响性能;Vue3中优先级相反,建议使用计算属性替代实现兼容。

<ul>
  <!--而且,key不要用index-->
  <li v-for="(id,name) in list" :key="id">{{name}}</li>
</ul>

        使用computed缓存

        使用computed属性缓存计算属性,避免重复计算

export default {
  data() {
    return {
      msgList: [...] // 消息列表
    }
  },
  computed: {
    // 未读消息列表
    unreadCount() {
      return this.msglist.filter(m => m.read === false).length
    }
  }
}

        keep-alive缓存组件

        缓存大型列表或者表格,频繁切换的组件,如tabs;

        不要乱用,缓存太多会占用内存,且不好debug

        异步组件

        针对体积较大的组件,如编辑器、复杂表格、复杂表单等

        拆包,需要时异步加载,不需要则不加载

        减少主包体积,首页加载会更快

// 使用Vue.js中的defineAsyncComponent方法来实现异步组件加载
import {defineAsyncComponent} from 'vue'

export default {
  name: 'AsyncComponent',  // 定义了一个名为AsyncComponent的组件
  /**
  * 通过components属性注册了一个名为 Child 的子组件,并使用defineAsyncComponent方法来定义异步加载这个子组件
  * 在defineAsyncComponent方法传入了一个函数,在需要渲染这个异步组件时被调用;使用动态import的方式来异步加载 './Child.vue' 组件,Webpack 会将这个异步加载的组件作为一个单独的chunk进行打包,这个chunk 的名称被指定为'async-child'。
  */
  components: {
    Child: defineAsyncComponent(() => import(**/* webpackChunkeName: "async-child"*/** './Child.vue'))
  }
}

        路由懒加载

        项目比较大,拆分路由,保证首页先加载

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // 通过动态import异步加载的About组件,并使用Webpack进行代码分割成名为"about"的chunk
    component: () => import(/* webpackChunkeName: "about"*/  '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router

        服务端渲染SSR

        可使用Nuxt.js, 但按需优化,使用SSR的成本比较高

        扩展: 使用Vue遇到那些坑?

        内存泄漏

        全局变量,全局事件,全局定时器和自定义事件等绑定后未销毁

        Vue2响应式的缺陷(Vue3不再有)

        data新增属性用Vue.set

        data删除属性用Vue.delete

        无法直接修改数据arr[index] = value

        路由切换时scroll到顶部

        SPA的通病,不仅仅是Vue

        如列表页、滚动到第二屏,点击进入详情页,再返回列表页(此时组件重新渲染)就scroll到顶部

        解决方案:在列表页缓存数据和scrollTop的值;当再次返回列表页时,渲染组件,执行scrollTo(scrollTop的值)

        终极方案:MPA + APP webView

5. 实际工作中,对React做过的优化?(没实际用过)

        模拟v-show

        循环使用key

        Fragment减少层级

        JSX不要定义函数

        构造函数bind this

        使用shouldComponentUpdate

        使用shouldComponentUpdata判断组件是否要更新

        或者使用React.PureComponent

        函数组件使用React.memo

        Hooks缓存数据和函数

        useMemo useCallBack

        异步组件

import React, { Suspense } from 'react';

const AsyncComponent = React.lazy(
  /* webpackChunkName: 'AsyncComponent'*/
  () => import('./AsyncComponent')
);

function App() {
  return (
    <div>
      <h1>My React App</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <AsyncComponent />
      </Suspense>
    </div>
  );
}

export default App;

        路由懒加载

import React, { lazy, Suspense } from 'react';
import {BrowserRouter as Router, Route, Switch} from 'react-router-dom';

const Home = lazy(() => import('./Home'));
const List = React.lazy(() => import(/* webpackChunkName: 'List'*/ './List'));

const = App() => {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route exact path="/" component={Home}/>
          <Route path="./list" component={List}/>
        </Switch>
      </Suspense>
    </Router>
  );
}

        SSR - Next.js

        扩展: 使用React遇到过那些坑?

        自定义组件的名称首字母大写

{/* 原生HTML组件*/}
<input/>

{/* 自定义组件 */}
<Input/>

        JS关键字冲突

{/* for 改成 htmlFor, class要改成className*/}
<label htmlFor="input-name" className="xxx">
  姓名 <input id="input-name"/>
</label>

        JSX数据类型

        setState是异步更新的

const curNum = this.state.num
this.setState({num: curNum + 1}, () => {
  console.log('newNum', this.state.num) // 正确
})
console.log('newNum', this.state.num) // 错误,直接打印值尚未变化

6. 如果H5很慢,该如何排查性能问题?

        前端性能指标

        First Paint(FP):指浏览器从响应用户输入网址地址到浏览器开始显示内容的时间。

        First Contentful Paint(FCP):指浏览器从响应用户输入网址地址到页面首次绘制文本、图片、非白色的 canvas 或 SVG 的时间。

        First Meaningful Paint(FMP):以前是测量用户加载体验的主要指标,但已被 Largest Contentful Paint 取代。

        DomContentLoaded(DCL):DOM完全加载及解析事件触发

        Largest Contentful Paint( LCP):指可视区“内容”最大的可见元素开始出现在屏幕上的时间点。

        Load(L): Load 页面加载完成

        使用Chrome devTools可以监控上述指标识别那部分执行的慢:

        Performance可产看上述指标,并有网页快照(最好使用无痕模式避免缓存的影响)

        Network可以查看各资源的加载时间(开启Show overview)

        使用Lighthouse分析性能指标:

        lighthouse是非常流行的第三方性能评测工具

        支持移动端和PC端,可生成如下测试报告和优化建议

## lighthouse 安装
C:\Users\zhchen>**npm i lighthouse -g**
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: 'lighthouse@11.7.0',
npm WARN EBADENGINE   required: { node: '>=18.16' },
npm WARN EBADENGINE   current: { node: 'v18.14.2', npm: '8.19.1' }
npm WARN EBADENGINE }

added 163 packages, and audited 164 packages in 7m

12 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
## lighthouse 测试网页地址 --view表示查看测试报告  --preset=desktop
C:\Users\zhchen>**lighthouse https://www.imooc.com/ --view --preset=desktop使用PC端访问(默认移动端)**
? We're constantly trying to improve Lighthouse and its reliability.
  Learn more: https://github.com/GoogleChrome/lighthouse/blob/main/docs/error-reporting.md
  May we anonymously report runtime exceptions to improve the tool over time?
  We'll remember your choice, but you can also use the flag --[no-]enable-error-reporting (y/N) » false
  LH:CLI:warn No response to error logging preference, errors will not be reported. +0m


        lighthouse生成国内访问github的报告:

        识别问题:哪里慢?加载慢 OR渲染慢

        加载慢的优化方法

        优化服务端硬件配置,使用CDN

        路由懒加载,大组件异步加载—减少主包体积

        优化HTTP缓存

        渲染慢的优化方法

        优化服务端接口(如Ajax获取数据慢)

        继续分析,优化前端组件内部的逻辑(参考Vue React优化)

        服务端渲染SSR

        总结,排查性能问题的步骤:

        分析性能指标,找到慢的原因;

        对症下药,解决问题

        持续跟进,持续优化

7. 工作中遇到过那些项目难点,是如何解决的?

        描述问题:背景+现象+造成的影响

        问题如何被解决:分析+解决

        自己的成长:学到了什么 + 以后如何避免

  • 18
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
web前端拼图小游戏是一个通过HTML、CSS和JavaScript实现的游戏。你可以使用该游戏来学习和练习前端开发技术。该游戏的源代码可以在引用中找到,作者是博主青丝缠光阴。这个拼图游戏的画面精美,非常适合初学者学习使用。 如果你想要使用该游戏作为HTML网页设计结课作业的一部分,可以根据你的需要进行定制和修改。引用提供了一些常见的网页设计题材,你可以选择其中之一来设计你的网页。同时,引用中提供了一些代码实现,你可以根据需要进行参考和使用。 总的来说,这个web前端拼图小游戏是一个很好的学习和练习前端开发技术的工具,你可以根据自己的需求来使用和定制。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Web前端小实践之拼图游戏.rar](https://download.csdn.net/download/UZDW_/12755504)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [web前端期末大作业--HTML+CSS+JS实现美女拼图游戏](https://blog.csdn.net/BYGFJ/article/details/121869002)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值