SPA 单页面
总:
SPA 称为单页应用程序,也就是整个网站只有一个 html 页面,相对于传统混合式开发性能更高,体积更小,但是使用了ajax 所以不利于seo
( 提示:seo 搜索引擎的优化 )
分:
单页应用与多页应用的区别:
单页面应用(SPA)
优点:
- 具有桌面应用的即时性、网站的可移植性和可访问性
- 用户体验好、快,内容的改变不需要重新加载整个页面
- 良好的前后端分离,分工更明确
缺点:
- 不利于搜索引擎的抓取
- 首次渲染速度相对较慢
应用场景:
适用于需要快速响应用户操作且具有较高交互性的应用程序,如在线游戏、社交网络、电子商务等,如果想要构建一个富交互、快速响应的 Web 应用程序,并且对 SEO 没有很高要求,则使用 SPA 可能是一个不错的选择。
cookie和本地存储的理解
总:
Cookie和本地存储(如Local Storage、Session Storage)都是在浏览器中存储数据的方式
分:
cookie和本地存储(如localStorage和sessionStorage)有几个重要区别:
(最大的 区别是 cookie 会携带请求头)
- 存储大小:cookie的大小限制为4KB左右,而本地存储可以存储更大量的数据。
- 存储位置:cookie保存在浏览器中,每次请求都会发送给服务器,而本地存储只保存在客户端浏览器中,不会随着每次请求发送给服务器。
- 安全性:cookie可以被篡改或窃取,容易遭受跨站点脚本攻击,而本地存储受到同源策略的保护,安全性相对较高。
实际应用:
但它们的应用场景有所不同:
Cookie:主要用于客户端和服务器之间传递信息,例如保存用户登录状态
本地存储:则通常用于客户端本地存储数据,例如保存表单数据、缓存页面内容等
总之,Cookie和本地存储都有自己的优劣势和应用场景,开发者需要根据实际需求选择合适的存储方式。
(拓展: 不同的浏览器对于cookie的存储容量、数量和过期时间等方面可能会有不同的限制。这些限制可以影响到网站在使用cookie时的功能和表现,例如某些浏览器只允许最多存储50个cookie或者每个cookie最大只能存储4KB的数据。此外,一些用户也可能会在浏览器中设置禁止cookie的选项,导致网站不能在用户计算机上存储cookie。因此,在使用cookie时需要考虑不同浏览器和用户设置的限制,以确保网站正常运行并保护用户隐私。)
XHR 是什么?
1.# SPA 单页面
总:
SPA 称为单页应用程序,也就是整个网站只有一个 html 页面,相对于传统混合式开发性能更高,体积更小,但是使用了ajax 所以不利于seo
( 提示:seo 搜索引擎的优化 )
分:
单页应用与多页应用的区别:
单页面应用(SPA)
优点:
- 具有桌面应用的即时性、网站的可移植性和可访问性
- 用户体验好、快,内容的改变不需要重新加载整个页面
- 良好的前后端分离,分工更明确
缺点:
- 不利于搜索引擎的抓取
- 首次渲染速度相对较慢
应用场景:
适用于需要快速响应用户操作且具有较高交互性的应用程序,如在线游戏、社交网络、电子商务等,如果想要构建一个富交互、快速响应的 Web 应用程序,并且对 SEO 没有很高要求,则使用 SPA 可能是一个不错的选择。
cookie和本地存储的理解
总:
Cookie和本地存储(如Local Storage、Session Storage)都是在浏览器中存储数据的方式
分:
cookie和本地存储(如localStorage和sessionStorage)有几个重要区别:
(最大的 区别是 cookie 会携带请求头)
- 存储大小:cookie的大小限制为4KB左右,而本地存储可以存储更大量的数据。
- 存储位置:cookie保存在浏览器中,每次请求都会发送给服务器,而本地存储只保存在客户端浏览器中,不会随着每次请求发送给服务器。
- 安全性:cookie可以被篡改或窃取,容易遭受跨站点脚本攻击,而本地存储受到同源策略的保护,安全性相对较高。
实际应用:
但它们的应用场景有所不同:
Cookie:主要用于客户端和服务器之间传递信息,例如保存用户登录状态
本地存储:则通常用于客户端本地存储数据,例如保存表单数据、缓存页面内容等
总之,Cookie和本地存储都有自己的优劣势和应用场景,开发者需要根据实际需求选择合适的存储方式。
(拓展: 不同的浏览器对于cookie的存储容量、数量和过期时间等方面可能会有不同的限制。这些限制可以影响到网站在使用cookie时的功能和表现,例如某些浏览器只允许最多存储50个cookie或者每个cookie最大只能存储4KB的数据。此外,一些用户也可能会在浏览器中设置禁止cookie的选项,导致网站不能在用户计算机上存储cookie。因此,在使用cookie时需要考虑不同浏览器和用户设置的限制,以确保网站正常运行并保护用户隐私。)
XHR 是什么?
- AJAX 是浏览器与服务器通信的技术,采用 XMLHttpRequest 对象相关代码
- axios 是对 XHR 相关代码进行了封装,让我们只关心传递的接口参数
- 学习 XHR 也是了解 axios 内部与服务器交互过程的真正原理
XHR 使用步骤?
- 创建 XHR 对象
- 调用 open 方法,设置 url 和请求方法
- 监听 loadend 事件,接收结果
- 调用 send 方法,发起请求
XHR 如何携带查询参数?
在调用 open 方法的时候,在 url? 后面按照指定格式拼接参数名和值
注意:原生 XHR 需要在 send 方法调用时,传入请求体携带
css 新特性
我知道的 C3 的新特性有很多,常见的如下:
- border-radius:圆角边框
- box-shadow:盒子阴影
- background-size:背景图片大小
- transition:过渡
- transform:转换(位移 旋转 缩放)
- animation:动画
- linear-gradient:线性渐变
- box-sizing:css3 盒子模型
深拷贝浅拷贝的区别?如何实现一个深拷贝?
浅拷贝:拷贝基本数据类型为他的值,拷贝引用数据类型为地址,生成新的数据,修改新的数据会影响原数据,实际开发常用的方法有:object.assgin,扩展运算符等等
深拷贝:在内存中开辟一个新的栈空间保存新的数据,修改新数据不会影响到原数据,开发中常用的方法有:loadsh 中的_.cloneDeep()方法,JSON.stringify()
一、数据类型存储
前面文章我们讲到,JavaScript
中存在两大数据类型:
- 基本类型
- 引用类型
基本类型数据保存在在栈内存中
引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中
二、浅拷贝
浅拷贝,指的是创建新的数据,这个数据有着原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址
即浅拷贝是拷贝一层
,深层次的引用类型则共享内存地址
下面简单实现一个浅拷贝
function shallowClone(obj) {
const newObj = {}
for (let prop in obj) {
if (obj.hasOwnProperty(prop)) {
newObj[prop] = obj[prop]
}
}
return newObj
}
在JavaScript
中,存在浅拷贝的现象有:
Object.assign
Array.prototype.slice()
,Array.prototype.concat()
- 使用拓展运算符实现的复制
Object.assign
var obj = {
age: 18,
nature: ['smart', 'good'],
names: {
name1: 'fx',
name2: 'xka',
},
love: function () {
console.log('fx is a great girl')
},
}
var newObj = Object.assign({}, fxObj)
slice()
const fxArr = ['One', 'Two', 'Three']
const fxArrs = fxArr.slice(0)
fxArrs[1] = 'love'
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
concat()
const fxArr = ['One', 'Two', 'Three']
const fxArrs = fxArr.concat()
fxArrs[1] = 'love'
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
拓展运算符
const fxArr = ['One', 'Two', 'Three']
const fxArrs = [...fxArr]
fxArrs[1] = 'love'
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
三、深拷贝
深拷贝开辟一个新的栈,两个对象属完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
常见的深拷贝方式有:
- _.cloneDeep()
- jQuery.extend()
- JSON.stringify()
- 手写循环递归
_.cloneDeep()
const _ = require('lodash')
const obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3],
}
const obj2 = _.cloneDeep(obj1)
console.log(obj1.b.f === obj2.b.f) // false
#jQuery.extend()
const $ = require('jquery')
const obj1 = {
a: 1,
b: { f: { g: 1 } },
c: [1, 2, 3],
}
const obj2 = $.extend(true, {}, obj1)
console.log(obj1.b.f === obj2.b.f) // false
JSON.stringify()
const obj2 = JSON.parse(JSON.stringify(obj1))
但是这种方式存在弊端,会忽略undefined
、symbol
和函数
const obj = {
name: 'A',
name1: undefined,
name3: function () {},
name4: Symbol('A'),
}
const obj2 = JSON.parse(JSON.stringify(obj))
console.log(obj2) // {name: "A"}
循环递归
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return obj // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj)
if (obj instanceof RegExp) return new RegExp(obj)
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== 'object') return obj
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj)
let cloneObj = new obj.constructor()
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj)
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash)
}
}
return cloneObj
}
什么是单点登录?如何实现?
一、是什么
单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一
SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统
SSO 一般都需要一个独立的认证中心(passport),子系统的登录均得通过passport
,子系统本身将不参与登录操作
当一个系统成功登录以后,passport
将会颁发一个令牌给各个子系统,子系统可以拿着令牌会获取各自的受保护资源,为了减少频繁认证,各个子系统在被passport
授权以后,会建立一个局部会话,在一定时间内可以无需再次向passport
发起认证
上图有四个系统,分别是Application1
、Application2
、Application3
、和SSO
,当Application1
、Application2
、Application3
需要登录时,将跳到SSO
系统,SSO
系统完成登录,其他的应用系统也就随之登录了
举个例子
淘宝、天猫都属于阿里旗下,当用户登录淘宝后,再打开天猫,系统便自动帮用户登录了天猫,这种现象就属于单点登录
如何实现
同域名下的单点登录
cookie
的domain
属性设置为当前域的父域,并且父域的cookie
会被子域所共享。path
属性默认为web
应用的上下文路径
利用 Cookie
的这个特点,没错,我们只需要将Cookie
的domain
属性设置为父域的域名(主域名),同时将 Cookie
的path
属性设置为根路径,将 Session ID
(或 Token
)保存到父域中。这样所有的子域应用就都可以访问到这个Cookie
不过这要求应用系统的域名需建立在一个共同的主域名之下,如 tieba.baidu.com
和 map.baidu.com
,它们都建立在 baidu.com
这个主域名之下,那么它们就可以通过这种方式来实现单点登录
不同域名下的单点登录(一)
如果是不同域的情况下,Cookie
是不共享的,这里我们可以部署一个认证中心,用于专门处理登录请求的独立的 Web
服务
用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将 token
写入 Cookie
(注意这个 Cookie
是认证中心的,应用系统是访问不到的)
应用系统检查当前请求有没有 Token
,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心
由于这个操作会将认证中心的 Cookie
自动带过去,因此,认证中心能够根据 Cookie
知道用户是否已经登录过了
如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录
如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标 URL
,并在跳转前生成一个 Token
,拼接在目标URL
的后面,回传给目标应用系统
应用系统拿到 Token
之后,还需要向认证中心确认下 Token
的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token
写入Cookie
,然后给本次访问放行。(注意这个 Cookie
是当前应用系统的)当用户再次访问当前应用系统时,就会自动带上这个 Token
,应用系统验证 Token 发现用户已登录,于是就不会有认证中心什么事了
此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法
不同域名下的单点登录(二)
可以选择将 Session ID
(或 Token
)保存到浏览器的 LocalStorage
中,让前端在每次向后端发送请求时,主动将LocalStorage
的数据传递给服务端
这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将 Session ID
(或 Token
)放在响应体中传递给前端
单点登录完全可以在前端实现。前端拿到 Session ID
(或 Token
)后,除了将它写入自己的 LocalStorage
中之外,还可以通过特殊手段将它写入多个其他域下的 LocalStorage
中
关键代码如下:
// 获取 token
var token = result.data.token;
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法将token传递给iframe
setTimeout(function () {
iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
iframe.remove();
}, 6000);
// 在这个iframe所加载的HTML中绑定一个事件监听器,当事件被触发时,把接收到的token数据写入localStorage
window.addEventListener('message', function (event) {
localStorage.setItem('token', event.data)
}, false);
前端通过 iframe
+postMessage()
方式,将同一份 Token
写入到了多个域下的 LocalStorage
中,前端每次在向后端发送请求之前,都会主动从 LocalStorage
中读取Token
并在请求中携带,这样就实现了同一份Token
被多个域所共享
此种实现方式完全由前端控制,几乎不需要后端参与,同样支持跨域
三、流程
单点登录的流程图如下所示:
- 用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
- sso认证中心发现用户未登录,将用户引导至登录页面
- 用户输入用户名密码提交登录申请
- sso认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话,同时创建授权令牌
- sso认证中心带着令牌跳转会最初的请求地址(系统1)
- 系统1拿到令牌,去sso认证中心校验令牌是否有效
- sso认证中心校验令牌,返回有效,注册系统1
- 系统1使用该令牌创建与用户的会话,称为局部会话,返回受保护资源
- 用户访问系统2的受保护资源
- 系统2发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
- sso认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
- 系统2拿到令牌,去sso认证中心校验令牌是否有效
- sso认证中心校验令牌,返回有效,注册系统2
- 系统2使用该令牌创建与用户的局部会话,返回受保护资源
用户登录成功之后,会与sso
认证中心及各个子系统建立会话,用户与sso
认证中心建立的会话称为全局会话
用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso
认证中心
全局会话与局部会话有如下约束关系:
- 局部会话存在,全局会话一定存在
- 全局会话存在,局部会话不一定存在
- 全局会话销毁,局部会话必须销毁
、