前端项目问题

文章详细介绍了Vue.js中的组件封装,响应式设计的原理,包括数据劫持、依赖收集和订阅者机制。同时,讨论了网站性能优化的策略,如CDN、减少HTTP请求、HTTP2、缓存策略、图片懒加载和压缩等。此外,还涵盖了网络协议TCP/UDP和HTTP/HTTPS的基本概念以及数据结构和算法的基础知识。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

项目一:包括村居人员信息管理、房屋信息管理、报修服务等专题模块的功能开发。
项目二:包括用户的登录、商品的搜索、商品加购功能。

一、封装组件,实现功能与脚本复用

答: 我用vue开发的所有项目,都是采用组件化的思想开发的。一般我在搭建项目的时候,会创建一个views目录和一个commen目录和一个feature目录,views目录中放页面级的组件,commen中放公共组件(如:head(公共头组件),foot(公共底部组件)等),feature目录内放功能组件(如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))

首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性低等问题。

使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。但是我们一般用脚手架开发项目(vue-cli),每个 .vue单文件就是一个组件。在另一组件import 导入,并在components中注册,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。

https://blog.youkuaiyun.com/weixin_59519449/article/details/124202175

要封装一个 Vue 组件,可以按照以下步骤进行操作:

  • 创建一个新的 Vue 单文件组件(.vue 文件),并命名为你的组件名,例如 MyComponent.vue。

  • 在组件文件中,使用 标签定义组件的模板结构,使用 <script> 标签定义组件的逻辑,使用 <style> 标签定义组件的样式。

  • <script> 标签中,使用 export default 导出一个 Vue 组件对象。

  • 在组件对象中,定义组件的属性(props),数据(data),方法(methods),生命周期钩子(lifecycle hooks)等。

  • 如果需要,可以在组件中引入其他的子组件或插件。

  • 在需要使用该组件的地方,使用 import 语句导入该组件,然后在父组件的模板中使用该组件的标签。
    https://blog.youkuaiyun.com/m0_57263959/article/details/130751628

使用组件的好处

  • 组件是可以复用性的
  • 易于维护
  • 有封装性,易于使用
  • 大型项目中降低组件之间重复性
    原文链接:https://blog.youkuaiyun.com/weixin_43638968/article/details/108623317

二、响应式设计

vue响应式原理

vue响应式也叫作数据双向绑定,大致原理阐述:
​首先我们需要通过Object.defineProperty()方法把数据(data)设置为gettersetter的访问形式,这样我们就可以在数据被修改时在setter方法设置监视修改页面信息,也就是说每当数据被修改,就会触发对应的set方法,然后我们可以在set方法中去调用操作dom的方法。
​此外,如果页面有inputv-model绑定数据,我们需要在这种绑定了datainput元素上添加监听,添加input事件监听,每当input事件被触发时,就修改对应的data

vue实现数据响应式,是通过数据劫持侦测数据变化,发布订阅模式进行依赖收集与视图更新,换句话说是Observe,Watcher以及Compile三者相互配合,

  • Observe实现数据劫持,递归给对象属性,绑定setter和getter函数,属性改变时,通知订阅者
  • Compile解析模板,把模板中变量换成数据,绑定更新函数,添加订阅者,收到通知就执行更新函数
  • Watcher作为Observe和Compile中间的桥梁,订阅Observe属性变化的消息,触发Compile更新函数

2.1 什么是响应式

当price 发生变化的时候,Vue就知道自己需要做三件事情:

  • 更新页面上price的值
  • 计算表达式 price*quantity 的值,更新页面
  • 调用totalPriceWithTax 函数,更新页面

数据发生变化后,会重新对页面渲染,这就是Vue响应式,那么这一切是怎么做到的呢?想完成这个过程,我们需要:

  • 侦测数据的变化
  • 收集视图依赖了哪些数据
  • 数据变化时,自动“通知”需要更新的视图部分,并进行更新,对应专业俗语分别是:
  • 数据劫持 / 数据代理
  • 依赖收集
  • 发布订阅模式

2.2 如何侦测数据的变化

​​​​​​​首先有个问题,在Javascript中,如何侦测一个对象的变化?其实有两种办法可以侦测到变化:使用 Object.defineProperty和ES6的 Proxy,这就是进行数据劫持或数据代理

  • 方法1.Object.defineProperty
    Vue通过设定对象属性的 setter/getter 方法来监听数据的变化,通过getter进行依赖收集,而每个setter方法就是一个观察者,在数据变更的时候通知订阅者更新视图。
  • 方法2.Proxy
    Proxy 是 JavaScript 2015 的一个新特性。 Proxy 的代理是针对整个对象的,而不是对象的某个属性,因此不同于 Object.defineProperty 的必须遍历对象每个属性, Proxy 只需要做一层代理就可以监听同级结构下的所有属性变化,当然对于深层结构,递归还是需要进行的。此外 Proxy支持代理数组的变化。

2.3 为什么要收集依赖

我们之所以要观察数据,其目的在于当数据的属性发生变化时,可以通知那些曾经使用了该数据的地方。比如第一例子中,模板中使用了price 数据,当它发生变化时,要向使用了它的地方发送通知。

2.4 订阅者 Dep

1.为什么引入 Dep
收集依赖需要为依赖找一个存储依赖的地方,为此我们创建了Dep,它用来收集依赖、删除依赖和向依赖发送消息等。
于是我们先来实现一个订阅者 Dep 类,用于解耦属性的依赖收集和派发更新操作,说得具体点,它的主要作用是用来存放 Watcher 观察者对象。我们可以把Watcher理解成一个中介的角色,数据发生变化时通知它,然后它再通知其他地方。

2.5 观察者 Watcher

1.为什么引入Watcher
Vue 中定义一个 Watcher 类来表示观察订阅依赖。至于为啥引入Watcher,《深入浅出vue.js》给出了很好的解释:

当属性发生变化后,我们要通知用到数据的地方,而使用这个数据的地方有很多,而且类型还不一样,既有可能是模板,也有可能是用户写的一个watch,这时需要抽象出一个能集中处理这些情况的类。然后,我们在依赖收集阶段只收集这个封装好的类的实例进来,通知也只通知它一个,再由它负责通知其他地方。

依赖收集的目的是将观察者 Watcher 对象存放到当前闭包中的订阅者 Dep 的 subs 中,形成如下所示的这样一个关系(图参考《剖析 Vue.js 内部运行机制》)。

所谓的依赖,其实就是Watcher。至于如何收集依赖,总结起来就一句话,在getter中收集依赖,在setter中触发依赖。先收集依赖,即把用到该数据的地方收集起来,然后等属性发生变化时,把之前收集好的依赖循环触发一遍就行了。

具体来说,当外界通过Watcher读取数据时,便会触发getter从而将Watcher添加到依赖中,哪个Watcher触发了getter,就把哪个Watcher收集到Dep中。当数据发生变化时,会循环依赖列表,把所有的Watcher都通知一遍。

最后我们对 defineReactive函数进行改造,在自定义函数中添加依赖收集和派发更新相关的代码,实现了一个简易的数据响应式。

2.6 总结:

newVue() 后, Vue 会调用_init函数进行初始化,也就是init 过程,在 这个过程Data通过Observer转换成了getter/setter的形式,来对数据追踪变化,当被设置的对象被读取的时候会执行 getter 函数,而在当被赋值的时候会执行 setter函数。

render function 执行的时候,因为会读取所需对象的值,所以会触发getter函数从而将Watcher添加到依赖中进行依赖收集。

在修改对象的值的时候,会触发对应的 settersetter通知之前依赖收集得到的 Dep 中的每一个 Watcher,告诉它们自己的值改变了,需要重新渲染视图。这时候这些 Watcher就会开始调用 update 来更新视图。

原文链接:https://blog.youkuaiyun.com/weixin_48181168/article/details/120158346

三、对网站的性能优化和代码重构 ,以提高网站的加载速度和用户体验

3.1 静态资源使用 CDN

当网站所挂服务器离用户越来越远时,访问网站延迟越高。CDN(内容分发网络)就是为了解决这一问题,在多个不同地理位置部署 Web 服务器,根据用户位置分配最近的资源,缩短请求时间达到优化加载速度,降低传输延迟的效果。CDN 域名一般都会缓存到本地中,请求速度也较快。

3.2 减少不必要的 HTTP 请求

一个完整的 HTTP 请求需要经历连接与释放过程,需要一定的时间,减少 HTTP 请求能节省一定时间。

单纯说减少 HTTP 请求这个做法在实际工作中是需要权衡的,不是想减少就减少。

在项目中更应该注重的是:减少不必要的 HTTP 请求。比如接口请求后缓存了,发现在一些场景切换中,又重复请求了;或者在一些根本没用到该接口的其它页面,也请求了接口,这时就需要进行减少请求优化。

3.3 使用 HTTP2(更快的传输)

HTTP1.1 版本存在的问题:线程阻塞,在同一时间,同一域名的请求有一定的数量限制,超过限制数目的请求会被阻塞。

HTTP2 特性:

  • 支持二进制传送:解析速度更快
  • 支持多路复用:多个请求可以共用一个 TCP 连接,提高了连接的利用率,降低延迟
  • 压缩算法压缩头部:减小了传输的体积。且将相同的首部存储起来,仅发送不同的部分,也可以节省流量和加快请求时间
    由于 HTTP2 支持多路复用,可并行请求的特性,雪碧图这个性能优化点也随之过时,现在角度看,雪碧图维护成本也高,基本不会使用了。

3.4 HTTP 缓存

为了不让用户每次访问网站都需要重新请求文件,可以通过设置 HTTP 缓存(强缓存/协商缓存)来进行控制,符合缓存条件时直接读取缓存,减少发送请求速度,能提高加载速度。

落到实地,大部分进到公司里面这些都是早配好的。或者这是后端处理的前端没插手机会,如果前端接入 Node 的同学倒可以去搞搞,这一部分就不细说了,有兴趣动手试的可以看我这篇文章:动手搞懂 HTTP 缓存机制

3.5 图片懒加载

先不给图片设置 src 路径,当图片出现在浏览器可视区域时,才去加载图片,这就是延迟/懒加载。

图片设置 data-src属性在页面不可见时图片不会加载。

图片懒加载思路:

  • 先在 img 标签设置自定义属性 data-src
  • 首屏展示可视区域内的图片(计算对应页面可见时) src 值替换为 data-src,加载图片
    在实际场景中社区已有对应的各种 lazyLoad 库可使用

3.6 图片压缩

利用一些在线工具或插件,可以对图片进行压缩,适当的压缩大小通常看不出来区别。

webpack 的话有 image-webpack-loader,在线网站比如有TinyPNG

3.7缩略图

点击再或加载到之后再查看清晰/大图

如果有一个 1920 * 1080 大小的图片,用缩略图的方式展示给用户,并且当用户鼠标悬停在上面时才展示全图。如果用户从未真正将鼠标悬停在缩略图上,则浪费了下载图片的时间。

所以,可以用两张图片来进行优化。一开始,只加载缩略图,当用户悬停在图片上时,才加载大图

3.8渲染优化——减少重绘重排

  • 用 JavaScript 修改样式时,最好不要直接写样式,而是替换 class 来改变样式
  • 需要对元素进行复杂操作时,可以先隐藏元素(display:none)操作完成后再显示
  • 需要创建多个 DOM 节点时,使用 DocumentFragment 创建完最后再一次性加入文档

3.9渲染优化——优化高频事件

当页面有一些事件频繁触发时,为了优化体验,需要对这类事件进行调用次数的限制,于是可以使用防抖与节流来减少调用频率。

  • 防抖:一段时间后只执行一次,将多次执行变为最后一次执行
  • 节流:在固定的频率执行,将多次执行变为在规定时间内只执行一次

3.10渲染优化——优化动画

  • 优先使用 CSS 来实现动画效果
  • 使用translateZ/translate3d开启硬件加速
  • 合理使用 requestAnimationFrame 代替 setTimeout

3.11渲染优化——虚拟列表优化

如果在视口内列表有较多数据显示(如多达几百上千),如果数据量过大产生过多的 DOM 会造成页面卡顿,此时可以使用虚拟列表,监听视口位置变化,从而对视口内的虚拟列表进行控制。

  • react-virtualized
  • react-window

原文链接:https://blog.youkuaiyun.com/BigChicken3/article/details/125278025

四、使用Vue、Axios实现各页面的跳转、组件的封装。

五、项目难点

六、常见网络协议(TCP/UDP、HTTP/HTTPS等常见协议)

6.1TCP三次握手

在TCP连接中必须要明确客户端与服务器端,由客户端向服务器端发出连接请求,每次连接的创建都需经过"三次握手"
三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠。

  • 第一次握手:客户端向服务器端发出连接请求,等待服务器确认。
  • 第二次握手:服务器端向客户端回送一个响应,通知客户端收到了连接请求
  • 第三次握手:客户端再次向服务器端发送确认信息,确认连接。
    完成三次握手,连接建立后,客户端和服务器就可以开始进行数据传输。

6.2 UDP

UDP协议为用户数据报协议,UDP是无连接通信协议,不能保证数据的完整性,即在数据传输时,数据的发送端和接收端不需建立逻辑连接。
UDP协议传输的数据被限制在64kb,超出这个范围就不能发送,就如qq发送很大的压缩包失败,是UDP不允许而不是qq问题。
简单说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样的,接收端在收到数据时,也不会向发送端反馈是否收到数据。

6.3 HTTP

超文本传输协议
(英文: H yper T ext T ransfer P rotocol ,缩写: HTTP )是一种用于分布式、协作式和超媒体信息系统的 应用层协议 。
HTTP的无状态保存
HTTP是一种 无状态保存协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,也就是说HTTP协议对于发送过的请求或响应都不做持久化处理。
HTTP的长连接和短链接

过程:

  1. 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址 ;
  2. 解析出 IP 地址后,根据该 IP 地址和默认端口 80 ,和服务器建立 TCP 连接 ;
  3. 浏览器发出读取文件 (URL 中域名后面部分对应的文件 ) 的 HTTP 请求,该请求报文作为 TCP 三次握手的第三个 报文的数据发送给服务器;
  4. 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器 ;
  5. 浏览器将该 html 文本并显示内容

6.4 HTTPS

HTTPS通讯方式:

  • 客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。
  • Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
  • 客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。
  • 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
  • Web服务器利用自己的私钥解密出会话密钥。
  • Web服务器利用会话密钥加密与客户端之间的通信。

原文链接:https://blog.youkuaiyun.com/qq_40454863/article/details/114527665

七、常见数据结构与算法(线性表、栈、队列、二叉树等)

7.1 线性结构

对于数据结构而言,线性结构是n个数据元素的有序集合。
集合中必存在唯一的一个“第一个元素”;
集合中必存在唯一的一个“最后的元素”;
除最后元素之外,其他数据元素均有唯一的“后继”;
除第一个元素之外,其他数据元素均有唯一的“前驱”。

7.2 栈

定义
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”。
特点
栈只能在一端进行数据操作
栈模型具有先进后出的规律

7.3 队列

定义:队列是限制在两端进行插入操作和删除操作的线性表,允许进行存入操作的一端称为“队尾”,允许进行删除操作的一端称为“队头”。
特点:
队列只能在队头和队尾进行数据操作
队列模型具有先进先出或后进后出的规律

7.4 树形结构

指的是数据元素之间存在着“一对多”的树形关系的数据结构,是一类重要的非线性数据结构。在树形结构中,树根节点没有前驱节点,其余每个节点有且仅有一个前驱节点。叶子结点没有后续节点,其余每个节点的后续节点数可以是一个也可以是多个。

https://blog.youkuaiyun.com/xiecheng1995/article/details/104490989

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值