文章目录
前言
项目一:包括村居人员信息管理、房屋信息管理、报修服务等专题模块的功能开发。
项目二:包括用户的登录、商品的搜索、商品加购功能。
一、封装组件,实现功能与脚本复用
答: 我用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)
设置为getter
和setter
的访问形式,这样我们就可以在数据被修改时在setter
方法设置监视修改页面信息,也就是说每当数据被修改,就会触发对应的set
方法,然后我们可以在set
方法中去调用操作dom
的方法。
此外,如果页面有input
用v-model
绑定数据,我们需要在这种绑定了data
的input
元素上添加监听,添加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
添加到依赖中进行依赖收集。
在修改对象的值的时候,会触发对应的 setter
, setter
通知之前依赖收集得到的 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的长连接和短链接
过程:
- 浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址 ;
- 解析出 IP 地址后,根据该 IP 地址和默认端口 80 ,和服务器建立 TCP 连接 ;
- 浏览器发出读取文件 (URL 中域名后面部分对应的文件 ) 的 HTTP 请求,该请求报文作为 TCP 三次握手的第三个 报文的数据发送给服务器;
- 服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器 ;
- 浏览器将该 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