登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
Gitee 2025年度个人数据报告已发布,快来看看你的成长👉
代码拉取完成,页面将自动刷新
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
3
Star
47
Fork
21
DreamCoders
/
CoderGuide
代码
Issues
1169
Pull Requests
0
Wiki
统计
流水线
服务
JavaDoc
PHPDoc
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
更新失败,请稍后重试!
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
说说你对SPA的理解
待办的
#IAG9PC
陌生人
拥有者
创建于
2024-07-29 16:07
<h2>一、什么是SPA</h2><p>SPA(single-page application),翻译过来就是单页应用<code>SPA</code>是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中,所有必要的代码(<code>HTML</code>、<code>JavaScript</code>和<code>CSS</code>)都通过单个页面的加载而检索,或者根据需要(通常是为响应用户操作)动态装载适当的资源并添加到页面页面在任何时间点都不会重新加载,也不会将控制转移到其他页面举个例子来讲就是一个杯子,早上装的牛奶,中午装的是开水,晚上装的是茶,我们发现,变的始终是杯子里的内容,而杯子始终是那个杯子结构如下图</p><p>我们熟知的JS框架如<code>react</code>,<code>vue</code>,<code>angular</code>,<code>ember</code>都属于<code>SPA</code></p><h2>二、SPA和MPA的区别</h2><p>上面大家已经对单页面有所了解了,下面来讲讲多页应用MPA(MultiPage-page application),翻译过来就是多页应用在<code>MPA</code>中,每个页面都是一个主页面,都是独立的当我们在访问另一个页面的时候,都需要重新加载<code>html</code>、<code>css</code>、<code>js</code>文件,公共文件则根据需求按需加载如下图</p><h4>单页应用与多页应用的区别</h4><table style="width: auto;"><tbody><tr><th colspan="1" rowspan="1" width="auto" style="text-align: left;"></th><th colspan="1" rowspan="1" width="auto" style="text-align: left;">单页面应用(SPA)</th><th colspan="1" rowspan="1" width="auto" style="text-align: left;">多页面应用(MPA)</th></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">组成</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">一个主页面和多个页面片段</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">多个主页面</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">刷新方式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">局部刷新</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">整页刷新</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">url模式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">哈希模式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">历史模式</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">SEO搜索引擎优化</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">难实现,可使用SSR方式改善</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">容易实现</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">数据传递</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">容易</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">通过url、cookie、localStorage等传递</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">页面切换</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">速度快,用户体验良好</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">切换加载资源,速度慢,用户体验差</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">维护成本</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">相对容易</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">相对复杂</td></tr></tbody></table><h4>单页应用优缺点</h4><p>优点:</p><ul><li>具有桌面应用的即时性、网站的可移植性和可访问性</li><li>用户体验好、快,内容的改变不需要重新加载整个页面</li><li>良好的前后端分离,分工更明确</li></ul><p>缺点:</p><ul><li>不利于搜索引擎的抓取</li><li>首次渲染速度相对较慢</li></ul><p><br></p><h2>三、实现一个SPA</h2><h4>原理</h4><ol><li>监听地址栏中<code>hash</code>变化驱动界面变化</li><li>用pushsate记录浏览器的历史,驱动界面发送变化</li></ol><h4>实现</h4><h5><code>hash</code> 模式</h5><p>核心通过监听<code>url</code>中的<code>hash</code>来进行路由跳转</p><pre><code class="language-js">// 定义 Router class Router { constructor () { this.routes = {}; // 存放路由path及callback this.currentUrl = ''; // 监听路由change调用相对应的路由回调 window.addEventListener('load', this.refresh, false); window.addEventListener('hashchange', this.refresh, false); } route(path, callback){ this.routes[path] = callback; } push(path) { this.routes[path] && this.routes[path]() } } // 使用 router window.miniRouter = new Router(); miniRouter.route('/', () => console.log('page1')) miniRouter.route('/page2', () => console.log('page2')) miniRouter.push('/') // page1 miniRouter.push('/page2') // page2 </code></pre><h5>history模式</h5><p><code>history</code> 模式核心借用 <code>HTML5 history api</code>,<code>api</code> 提供了丰富的 <code>router</code> 相关属性先了解一个几个相关的api</p><ul><li><code>history.pushState</code> 浏览器历史纪录添加记录</li><li><code>history.replaceState</code>修改浏览器历史纪录中当前纪录</li><li><code>history.popState</code> 当 <code>history</code> 发生变化时触发</li></ul><pre><code class="language-js">// 定义 Router class Router { constructor () { this.routes = {}; this.listerPopState() } init(path) { history.replaceState({path: path}, null, path); this.routes[path] && this.routes[path](); } route(path, callback){ this.routes[path] = callback; } push(path) { history.pushState({path: path}, null, path); this.routes[path] && this.routes[path](); } listerPopState () { window.addEventListener('popstate' , e => { const path = e.state && e.state.path; this.routers[path] && this.routers[path]() }) } } // 使用 Router window.miniRouter = new Router(); miniRouter.route('/', ()=> console.log('page1')) miniRouter.route('/page2', ()=> console.log('page2')) // 跳转 miniRouter.push('/page2') // page2 </code></pre><h3>四、题外话:如何给SPA做SEO</h3><p>下面给出基于<code>Vue</code>的<code>SPA</code>如何实现<code>SEO</code>的三种方式</p><ol><li><strong>SSR服务端渲染</strong></li></ol><p>将组件或页面通过服务器生成html,再返回给浏览器,如<code>nuxt.js</code></p><ol><li><strong>静态化</strong></li></ol><p>目前主流的静态化主要有两种:(1)一种是通过程序将动态页面抓取并保存为静态页面,这样的页面的实际存在于服务器的硬盘中(2)另外一种是通过WEB服务器的 <code>URL Rewrite</code>的方式,它的原理是通过web服务器内部模块按一定规则将外部的URL请求转化为内部的文件地址,一句话来说就是把外部请求的静态地址转化为实际的动态页面地址,而静态页面实际是不存在的。这两种方法都达到了实现URL静态化的效果</p><ol><li><code><strong>使用Phantomjs针对爬虫处理</strong></code></li></ol><p>原理是通过<code>Nginx</code>配置,判断访问来源是否为爬虫,如果是则搜索引擎的爬虫请求会转发到一个<code>node server</code>,再通过<code>PhantomJS</code>来解析完整的<code>HTML</code>,返回给爬虫。下面是大致流程图</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/2024062711131181392.png" alt="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/2024062711131181392.png" data-href="" style=""/></p>
<h2>一、什么是SPA</h2><p>SPA(single-page application),翻译过来就是单页应用<code>SPA</code>是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换打断用户体验在单页应用中,所有必要的代码(<code>HTML</code>、<code>JavaScript</code>和<code>CSS</code>)都通过单个页面的加载而检索,或者根据需要(通常是为响应用户操作)动态装载适当的资源并添加到页面页面在任何时间点都不会重新加载,也不会将控制转移到其他页面举个例子来讲就是一个杯子,早上装的牛奶,中午装的是开水,晚上装的是茶,我们发现,变的始终是杯子里的内容,而杯子始终是那个杯子结构如下图</p><p>我们熟知的JS框架如<code>react</code>,<code>vue</code>,<code>angular</code>,<code>ember</code>都属于<code>SPA</code></p><h2>二、SPA和MPA的区别</h2><p>上面大家已经对单页面有所了解了,下面来讲讲多页应用MPA(MultiPage-page application),翻译过来就是多页应用在<code>MPA</code>中,每个页面都是一个主页面,都是独立的当我们在访问另一个页面的时候,都需要重新加载<code>html</code>、<code>css</code>、<code>js</code>文件,公共文件则根据需求按需加载如下图</p><h4>单页应用与多页应用的区别</h4><table style="width: auto;"><tbody><tr><th colspan="1" rowspan="1" width="auto" style="text-align: left;"></th><th colspan="1" rowspan="1" width="auto" style="text-align: left;">单页面应用(SPA)</th><th colspan="1" rowspan="1" width="auto" style="text-align: left;">多页面应用(MPA)</th></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">组成</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">一个主页面和多个页面片段</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">多个主页面</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">刷新方式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">局部刷新</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">整页刷新</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">url模式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">哈希模式</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">历史模式</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">SEO搜索引擎优化</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">难实现,可使用SSR方式改善</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">容易实现</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">数据传递</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">容易</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">通过url、cookie、localStorage等传递</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">页面切换</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">速度快,用户体验良好</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">切换加载资源,速度慢,用户体验差</td></tr><tr><td colspan="1" rowspan="1" width="auto" style="text-align: left;">维护成本</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">相对容易</td><td colspan="1" rowspan="1" width="auto" style="text-align: left;">相对复杂</td></tr></tbody></table><h4>单页应用优缺点</h4><p>优点:</p><ul><li>具有桌面应用的即时性、网站的可移植性和可访问性</li><li>用户体验好、快,内容的改变不需要重新加载整个页面</li><li>良好的前后端分离,分工更明确</li></ul><p>缺点:</p><ul><li>不利于搜索引擎的抓取</li><li>首次渲染速度相对较慢</li></ul><p><br></p><h2>三、实现一个SPA</h2><h4>原理</h4><ol><li>监听地址栏中<code>hash</code>变化驱动界面变化</li><li>用pushsate记录浏览器的历史,驱动界面发送变化</li></ol><h4>实现</h4><h5><code>hash</code> 模式</h5><p>核心通过监听<code>url</code>中的<code>hash</code>来进行路由跳转</p><pre><code class="language-js">// 定义 Router class Router { constructor () { this.routes = {}; // 存放路由path及callback this.currentUrl = ''; // 监听路由change调用相对应的路由回调 window.addEventListener('load', this.refresh, false); window.addEventListener('hashchange', this.refresh, false); } route(path, callback){ this.routes[path] = callback; } push(path) { this.routes[path] && this.routes[path]() } } // 使用 router window.miniRouter = new Router(); miniRouter.route('/', () => console.log('page1')) miniRouter.route('/page2', () => console.log('page2')) miniRouter.push('/') // page1 miniRouter.push('/page2') // page2 </code></pre><h5>history模式</h5><p><code>history</code> 模式核心借用 <code>HTML5 history api</code>,<code>api</code> 提供了丰富的 <code>router</code> 相关属性先了解一个几个相关的api</p><ul><li><code>history.pushState</code> 浏览器历史纪录添加记录</li><li><code>history.replaceState</code>修改浏览器历史纪录中当前纪录</li><li><code>history.popState</code> 当 <code>history</code> 发生变化时触发</li></ul><pre><code class="language-js">// 定义 Router class Router { constructor () { this.routes = {}; this.listerPopState() } init(path) { history.replaceState({path: path}, null, path); this.routes[path] && this.routes[path](); } route(path, callback){ this.routes[path] = callback; } push(path) { history.pushState({path: path}, null, path); this.routes[path] && this.routes[path](); } listerPopState () { window.addEventListener('popstate' , e => { const path = e.state && e.state.path; this.routers[path] && this.routers[path]() }) } } // 使用 Router window.miniRouter = new Router(); miniRouter.route('/', ()=> console.log('page1')) miniRouter.route('/page2', ()=> console.log('page2')) // 跳转 miniRouter.push('/page2') // page2 </code></pre><h3>四、题外话:如何给SPA做SEO</h3><p>下面给出基于<code>Vue</code>的<code>SPA</code>如何实现<code>SEO</code>的三种方式</p><ol><li><strong>SSR服务端渲染</strong></li></ol><p>将组件或页面通过服务器生成html,再返回给浏览器,如<code>nuxt.js</code></p><ol><li><strong>静态化</strong></li></ol><p>目前主流的静态化主要有两种:(1)一种是通过程序将动态页面抓取并保存为静态页面,这样的页面的实际存在于服务器的硬盘中(2)另外一种是通过WEB服务器的 <code>URL Rewrite</code>的方式,它的原理是通过web服务器内部模块按一定规则将外部的URL请求转化为内部的文件地址,一句话来说就是把外部请求的静态地址转化为实际的动态页面地址,而静态页面实际是不存在的。这两种方法都达到了实现URL静态化的效果</p><ol><li><code><strong>使用Phantomjs针对爬虫处理</strong></code></li></ol><p>原理是通过<code>Nginx</code>配置,判断访问来源是否为爬虫,如果是则搜索引擎的爬虫请求会转发到一个<code>node server</code>,再通过<code>PhantomJS</code>来解析完整的<code>HTML</code>,返回给爬虫。下面是大致流程图</p><p><img src="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/2024062711131181392.png" alt="https://jsd.onmicrosoft.cn/gh/iGaoWei/codercdn@master/question/20240627/2024062711131181392.png" data-href="" style=""/></p>
评论 (
0
)
登录
后才可以发表评论
状态
待办的
待办的
进行中
已完成
已关闭
负责人
未设置
标签
Html/JS/CSS
未设置
标签管理
里程碑
未关联里程碑
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
未关联
master
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
参与者(1)
1
https://gitee.com/DreamCoders/CoderGuide.git
git@gitee.com:DreamCoders/CoderGuide.git
DreamCoders
CoderGuide
CoderGuide
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册