Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
Y
yifu-study-front-share
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
yifu-study
front
yifu-study-front-share
Commits
de715ad7
Commit
de715ad7
authored
Sep 08, 2022
by
anrun
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of
https://git.worfu.com/yifu-study/front/yifu-study-front-share
parents
b73c3b91
b7ae4581
Pipeline
#16652
canceled with stage
Changes
5
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
459 additions
and
25 deletions
+459
-25
JavaScript中Worker初探.md
source/_posts/JavaScript中Worker初探.md
+2
-2
reduce函数详解
source/_posts/reduce函数详解
+139
-0
typeScript装饰器基础用法.md
source/_posts/typeScript装饰器基础用法.md
+1
-1
前端图片压缩.md
source/_posts/前端图片压缩.md
+279
-0
浅谈跨域.md
source/_posts/浅谈跨域.md
+38
-22
No files found.
source/_posts/JavaScript中Worker初探.md
View file @
de715ad7
...
...
@@ -5,7 +5,7 @@ author: 张顺
---
## 什么是Worker?他有什么作用?
因为js是单线程运行的,在遇到一些需要处理大量耗时的数据时,可能会阻塞页面的加载,造成面的假死。针对这个问题,H5出了新的功能worker,支持多线程,这时我们可以使用worker来开辟一个独立于主线程的子线程来进行一些耗时的大量运算。就可以用来解决因为大量耗时运算是造成页面假死的问题,详细内容查看
!
[
Worker
](
https://developer.mozilla.org/zh-CN/docs/Web/API/Worker
)
因为js是单线程运行的,在遇到一些需要处理大量耗时的数据时,可能会阻塞页面的加载,造成面的假死。针对这个问题,H5出了新的功能worker,支持多线程,这时我们可以使用worker来开辟一个独立于主线程的子线程来进行一些耗时的大量运算。就可以用来解决因为大量耗时运算是造成页面假死的问题,详细内容查看
[
Worker
](
https://developer.mozilla.org/zh-CN/docs/Web/API/Worker
)
### 如何使用Worker
...
...
@@ -146,7 +146,7 @@ worker 线程无法读取本地文件,即不能打开本机的文件系统(f
```

<br
/>

### SharedWorker一种特殊的worker,详细内容查看
!
[SharedWorker](https://developer.mozilla.org/zh-CN/docs/Web/API/SharedWorker)
### SharedWorker一种特殊的worker,详细内容查看[SharedWorker](https://developer.mozilla.org/zh-CN/docs/Web/API/SharedWorker)
sharedWorker 顾名思义,是 worker 的一种,可以由所有同源的页面共享。同Worker的api一样,传入js的url,就可以注册一个 sharedWorker 实例,
sharedWorker通过port来发送和接收消息
...
...
source/_posts/reduce函数详解
0 → 100644
View file @
de715ad7
**reduce()** 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。
reduce() 方法有两个参数,
- 第一个是回调函数,
- 第二个是初始值。
回调函数
回调函数在数组的每个元素上执行。回调函数的返回值是累加结果,并作为下一次调用回调函数的参数提供。回调函数带有四个参数。
accumulator 累计器 ——累加器累加回调函数的返回值。
currentValue 当前值——处理数组的当前元素。
currentIndex 当前索引 (可选)
array 数组 (可选)
初始值
如果指定了初始值,则将累加器设置为 initialValue 作为初始元素。否则,将累加器设置为数组的第一个元素作为初始元素。
arr.reduce(callback(accumulator, currentValue[,index[,array]])[, initialValue])
下面的代码片段中,第一个累加器(accumulator)被分配了初始值0。currentValue 是正在处理的 numbersArr 数组的元素。在这里,currentValue 被添加到累加器,在下次调用回调函数时,会将返回值作为参数提供。
```
const numbersArr = [67, 90, 100, 37, 60];
const total = numbersArr.reduce(function(accumulator, currentValue){
console.log("accumulator is " + accumulator + " current value is " + currentValue);
return accumulator + currentValue;
}, 0);
console.log("total : "+ total);
输出:
accumulator is 0 current value is 67
accumulator is 67 current value is 90
accumulator is 157 current value is 100
accumulator is 257 current value is 37
accumulator is 294 current value is 60
total : 354
```
**案例**
对数组的所有值求和
```
const studentResult = [67, 90, 100, 37, 60];
const total = studentResult.reduce((accumulator, currentValue) => accumulator +currentValue, 0);
console.log(total); // 354
```
代码中,studentResult 数组具有5个数字。使用 reduce() 方法,将数组减少为单个值,该值将 studentResult 数组的所有值和结果分配给 total。
对象数组中的数值之和
```
const studentResult = [
{ subject: '数学', marks: 78 },
{ subject: '物理', marks: 80 },
{ subject: '化学', marks: 93 }
];
const total = studentResult.reduce((accumulator, currentValue) => accumulator + currentValue.marks, 0);
console.log(total); // 251
```
我们从后端获取数据作为对象数组,因此,reduce() 方法有助于管理我们的前端逻辑。在下面的代码中,studentResult 对象数组有三个科目,这里,currentValue.marks 取了 studentResult 对象数组中每个科目的分数。
展平数组(去扁平化)
```
const twoDArr = [ [1,2], [3,4], [5,6], [7,8] , [9,10] ];
const oneDArr = twoDArr.reduce((accumulator, currentValue) => accumulator.concat(currentValue));
console.log(oneDArr);
// [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
```
“展平数组”是指将多维数组转换为一维。在下面的代码中,twoDArr 2维数组被转换为 oneDArr 一维数组。此处,第一个 [1,2] 数组分配给累加器 accumulator,然后 twoDArr 数组的其余每个元素都连接到累加器。
按属性分组对象
```
const result = [
{subject: '物理', marks: 41},
{subject: '化学', marks: 59},
{subject: '高等数学', marks: 36},
{subject: '应用数学', marks: 90},
{subject: '英语', marks: 64},
];
let initialValue = {
pass: [],
fail: []
}
const groupedResult = result.reduce((accumulator, current) => {
(current.marks >= 50) ? accumulator.pass.push(current) : accumulator.fail.push(current);
return accumulator;
}, initialValue);
console.log(groupedResult);
```
根据对象的属性,我们可以使用 reduce() 方法将对象数组分为几组。通过下面的代码片段,你可以清楚地理解这个概念。这里,result 对象数组有五个对象,每个对象都有 subject 和 marks 属性。如果分数大于或等于50,则该主题通过,否则,主题失败。reduce() 用于将结果分组为通过和失败。首先,将 initialValue 分配给累加器,然后 push() 方法在检查条件之后将当前对象添加到 pass 和 fail 属性中作为对象数组。
输出:
```
{
pass: [
{ subject: ‘化学’, marks: 59 },
{ subject: ‘应用数学’, marks: 90 },
{ subject: ‘英语’, marks: 64 }
],
fail: [
{ subject: ‘物理’, marks: 41 },
{ subject: ‘高等数学’, marks: 36 }
]
}
```
删除数组中的重复项
```
const duplicatedsArr = [1, 5, 6, 5, 7, 1, 6, 8, 9, 7];
const removeDuplicatedArr = duplicatedsArr.reduce((accumulator, currentValue) => {
if(!accumulator.includes(currentValue)){
accumulator.push(currentValue);
}
return accumulator;
}, []);
console.log(removeDuplicatedArr);
// [ 1, 5, 6, 7, 8, 9 ]
```
在下面的代码片段中,删除了 plicatedArr 数组中的重复项。首先,将一个空数组分配给累加器作为初始值。accumulator.includes() 检查 duplicatedArr 数组的每个元素是否已经在累加器中可用。如果 currentValue 在累加器中不可用,则使用 push() 将其添加。
\ No newline at end of file
source/_posts/typeScript装饰器基础用法.md
View file @
de715ad7
---
title: TypeScript
泛型
title: TypeScript
装饰器
date: 2022/08/04 17:00:00
tags:
-
前端
...
...
source/_posts/前端图片压缩.md
0 → 100644
View file @
de715ad7
---
title
:
前端图片压缩
date
:
2022/8/31 22:00:00
tags
:
-
前端
-
JavaScript
-
压缩
author
:
王许晓
---
> 使用VUE或者React框架加载HTML大图时极容易导致前端页面卡死报out of memory错误,报出这个错误还好,如果没有报错浏览器可能就无法操作了。
<!-- more -->
# 前端压缩
为保前端页面正常渲染html大图,需要在html加载前压缩图片。前端解决这个问题有两种方案,一个是上传前压缩,一个是上传后压缩。上传前可以保证当前图片无论在哪里显示大小已经被压缩过,无需再去管理。上传后压缩可以保证服务器端拥有高清原图,显示前需要做一次压缩。
无论那种压缩,压缩方式基本一致
1.
获取图片尺寸
2.
计算压缩比率
3.
通过canvas.toDataUrl 参数转化压缩图片
4.
将base64字符转转成文件或者直接显示
## 上传前压缩
获取到本地文件后,通过FileReader将本地文件写入到内存中
```
// 获取文件图片的宽高
function getImageWHFromFile(file, fn, err) {
try {
// 读取上传之后的文件对象
const imageReader = new FileReader()
// 将图片的内存url地址添加到FileReader中
imageReader.readAsDataURL(file)
// 当图片完全加载到FileReader对象中后,触发下面的事件
imageReader.addEventListener('loadend', function(e) {
// 获取上传到本机内存中的图片的url地址
const imageSrc = e.target.result
// 调用计算图片大小的方法
calculateImageSize(imageSrc).then(function({ image, width, height }) {
// 得到图片的宽和高
fn(image, width, height)
}).catch(e => {
err()
})
})
// 可以做一些其他状态监听
} catch (e) {
err(file)
}
}
```
计算内存中图片的宽高
```
// 根据图片地址获取图片的宽和高
function calculateImageSize(src) {
return new Promise(function(resolve, reject) {
const image = new Image()
image.addEventListener('load', function(e) {
resolve({
image: image,
width: e.target.width,
height: e.target.height,
})
})
image.addEventListener('error', function(e) {
reject(Error('获取尺寸失败'))
})
// 将图片的url地址添加到图片地址中
image.setAttribute('crossOrigin', 'Anonymous')
image.src = src
})
}
```
得到图片宽高后就可以计算压缩比率,通过图片真水的宽高和期望的宽高计算压缩率,基本上可以得到合适的图片尺寸
```
// 计算压缩比率
function getRatio(oriW, oriH, width, height) {
const proW = (oriW / width).toFixed(5)
const proH = (oriH / height).toFixed(5)
return proW < proH ? proW : proH
}
```
得到压缩比率就可以执行压缩,压缩使用canvas实现
```
// 缩放img对象中的图片
function compressImageToBase64(image, quality) {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const imageWidth = image.width * quality
const imageHeight = image.height * quality
canvas.width = imageWidth
canvas.height = imageHeight
context.drawImage(image, 0, 0, imageWidth, imageHeight)
return canvas.toDataURL('image/jpeg', quality)
}
```
压缩完得到图片的base64(DataURL)数据,可以用这个数据直接输出到img标签显示,或者继续加工生成图片文件
将base64转成blob对象
```
// DataURL转Blob对象
function dataURLToBlob(dataurl) {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
```
将Blob转成File,调用接口用FormData的形式上传文件
```
// 对图片进行压缩并返回文件格式
function compressToFile(image, quality) {
const blob = dataURLToBlob(compressImageToBase64(image, quality))
return new File([blob], new Date().getTime() + '.jpg')
}
```
到此,就得到了一个压缩后的文件对象
## 上传后压缩
上传后压缩的意思是,服务器返回一个图片url后,如果这个url指向的图片尺寸很大,比如:10M,这时候在浏览器中显示这个图片会导致页面卡死。我的解决方案是压缩后再显示,压缩方式大概与上传前压缩类似,从calculateImageSize方法开始计算图片尺寸,然后进行压缩,得到base64数据后回调显示这个图片。这里存在一个问题:压缩开始后chrome的控制台无法打开。原因则是image加载图片后会在控制台的Network中输出base64格式的日志,这个日志占用了太大的内存。
# 服务器压缩
服务器压缩是最好的且能满足产品对大图要求的解决方案。前端上传原图,服务器压缩后生成两个地址,一个缩略图一个原图,缩略图供前端显示,原图供下载。
> 附全部代码供参考
```
/**
* @param {待压缩图片文件} file
* @param {异步回调} fn
* @param {压缩期望尺寸} size [width ,height]
*/
const fileCompressToFile = function(file, fn, size) {
const _size = getComperssSize(size)
if (_size === null) {
fn(file)
return
}
// 开启后执行压缩
getImageWHFromFile(file, (image, width, height) => {
const pro = getRatio(_size[0], _size[1], width, height)
if (pro >= 1) {
fn(file)
return
}
// 开始压缩
fn(compressToFile(image, pro))
}, () => {
fn(file)
})
}
// 通过url压缩图片,压缩成功返回base64
const urlCompressToBase64 = function(url, fn, size) {
const _size = getComperssSize(size)
if (_size === null) {
fn(url)
return
}
calculateImageSize(url).then(function({ image, width, height }) {
const pro = getRatio(_size[0], _size[1], width, height)
if (pro >= 1) {
fn(url)
return
}
// 开始压缩
fn(compressImageToBase64(image, pro))
}).catch(e => {
console.error(e)
fn(url)
})
}
// 格式化压缩尺寸
function getComperssSize(size) {
if (!size) {
return null
}
const defaultSize = 500
if (Array.isArray(size)) {
return [size[0] || defaultSize, size[1] || defaultSize]
}
const pf = parseFloat(size)
return [pf || defaultSize, pf || defaultSize]
}
// 计算压缩比率
function getRatio(oriW, oriH, width, height) {
const proW = (oriW / width).toFixed(5)
const proH = (oriH / height).toFixed(5)
return proW < proH ? proW : proH
}
// 缩放img对象中的图片
function compressImageToBase64(image, quality) {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const imageWidth = image.width * quality
const imageHeight = image.height * quality
canvas.width = imageWidth
canvas.height = imageHeight
context.drawImage(image, 0, 0, imageWidth, imageHeight)
return canvas.toDataURL('image/jpeg', quality)
}
// 对图片进行压缩并返回文件格式
function compressToFile(image, quality) {
const blob = dataURLToBlob(compressImageToBase64(image, quality))
return new File([blob], new Date().getTime() + '.jpg')
}
// DataURL转Blob对象
function dataURLToBlob(dataurl) {
const arr = dataurl.split(',')
const mime = arr[0].match(/:(.*?);/)[1]
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
// 获取文件图片的宽高
function getImageWHFromFile(file, fn, err) {
try {
// 读取上传之后的文件对象
const imageReader = new FileReader()
// 将图片的内存url地址添加到FileReader中
imageReader.readAsDataURL(file)
// 当图片完全加载到FileReader对象中后,触发下面的事件
imageReader.addEventListener('loadend', function(e) {
// 获取上传到本机内存中的图片的url地址
const imageSrc = e.target.result
// 调用计算图片大小的方法
calculateImageSize(imageSrc).then(function({ image, width, height }) {
// 得到图片的宽和高
fn(image, width, height)
}).catch(e => {
err()
})
})
// 可以做一些其他状态监听
} catch (e) {
err(file)
}
}
// 根据图片地址获取图片的宽和高
function calculateImageSize(src) {
return new Promise(function(resolve, reject) {
const image = new Image()
image.addEventListener('load', function(e) {
resolve({
image: image,
width: e.target.width,
height: e.target.height,
})
})
image.addEventListener('error', function(e) {
reject(Error('获取尺寸失败'))
})
// 将图片的url地址添加到图片地址中
image.setAttribute('crossOrigin', 'Anonymous')
image.src = src
})
}
export {
fileCompressToFile,
urlCompressToBase64,
}
```
\ No newline at end of file
source/_posts/浅谈跨域.md
View file @
de715ad7
...
...
@@ -9,9 +9,11 @@ tags:
author
:
张芳利
---
<a
name=
"XDoI3"
></a>
## 一、什么是跨域
要知道什么是跨域,需要先知道另一个名词【
**同源政策**
】。
<br
/>
同源政策:是一个重要的安全政策,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
<br
/>
而什么才是同源呢?同源就是两个页面具有相同的协议,域名和端口 均一致。所以根据上面的了解,
**源=协议+主机/域名+端口,当源不同的时候也就是跨域了**
。
<br
/>
例如:
<br
/>
要知道什么是跨域,需要先知道另一个名词【
**同源政策**
】。
同源政策:是一个重要的安全政策,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。
而什么才是同源呢?同源就是两个页面具有相同的协议,域名和端口 均一致。所以根据上面的了解,
**源=协议+主机/域名+端口,当源不同的时候也就是跨域了**
。
例如:

|
**当前页面url**
|
**被请求页面url**
|
**是否跨域**
|
**原因**
|
...
...
@@ -25,25 +27,27 @@ author: 张芳利
**注意:**
> 在默认情况下 http 可以省略端口 80, https 省略 443。
<a
name=
"C9fUE"
></a>
## 二、跨域的限制
-
Cookie,LocalStorage,IndexDB 等存储性内容无法读取
-
DOM 节点无法访问
-
Ajax 请求发出去了,但是响应被浏览器拦截了
基本我们说的跨域是在第三点请求上面。
<br
/>
ajax请求报错:
基本我们说的跨域是在第三点请求上面。
ajax请求报错:
```
jsx
Access
to
XMLHttpRequest
at
'xxx'
from
origin
'xxx'
has
been
block
by
CORS
,
policy
:
No
'Access-Control-Allow-Origin'
header
is
present
on
the
requested
resource
.
```
<a
name=
"HSQ39"
></a>
## 三、解决跨域
<a
name=
"uTL8Z"
></a>
### 方法一:JSONP
JSONP 是 JSON with Padding 的缩写,主要就是利用了 script 标签没有跨域限制的这个特性来完成的。
<br
/>
**思路:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。**
<br
/>
缺点:只支持get请求,不支持post请求。
<br
/>
(下面的接口都是聚合数据里面的免费接口,如果想实验测试一下可以自己更换一下接口地址哈~)
<br
/>
**1、原生js**
```
jsx
JSONP 是 JSON with Padding 的缩写,主要就是利用了 script 标签没有跨域限制的这个特性来完成的。
思路:网页通过添加一个
`<script>`
元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
缺点:只支持get请求,不支持post请求。
(下面的接口都是聚合数据里面的免费接口,如果想实验测试一下可以自己更换一下接口地址哈~)
**1、原生js**
```
html
<script
src=
"http://test.com/data.php?callback=dosomething"
></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
...
...
@@ -67,7 +71,8 @@ script>
type
=
"text/javascript"
>
script
>
```
**2、vue.js **
<br
/>
2.1 安装jsonp,利用jsonp插件
**2、vue.js **
2.
1 安装jsonp,利用jsonp插件
```
jsx
yarn
add
jsonp
...
...
@@ -160,9 +165,12 @@ export const getTest = () => {
}
```
<a
name=
"LNDy8"
></a>
### 方法二:CORS
CORS是基于http1.1的一种跨域解决方案,它的全称是
**C**
ross-
**O**
rigin
**R**
esource
**S**
haring,跨域资源共享。
<br
/>
**思路:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许**
<br
/>
缺点:当你使用 IE
<
=
9
,
Opera
<
12
,
or
Firefox
<
3
.
5
或者更加老的浏览器,就不适合
<
br
/>
在 cors 中会有 简单请求 和 复杂请求的概念。简单请求:当请求
**同时满足**
以下条件时,浏览器会认为它是一个简单请求:
<br
/>
情况一: 使用以下方法(意思就是以下请求意外的都是非简单请求)
CORS是基于http1.1的一种跨域解决方案,它的全称是
**C**
ross-
**O**
rigin
**R**
esource
**S**
haring,跨域资源共享。
**思路:如果浏览器要跨域访问服务器的资源,需要获得服务器的允许**
缺点:当你使用 IE<=9, Opera<12, or Firefox<3.5 或者更加老的浏览器,就不适合
在 cors 中会有 简单请求 和 复杂请求的概念。简单请求:当请求
**同时满足**
以下条件时,浏览器会认为它是一个简单请求:
情况一: 使用以下方法(意思就是以下请求意外的都是非简单请求)
-
GET
-
HEAD
...
...
@@ -186,7 +194,10 @@ CORS是基于http1.1的一种跨域解决方案,它的全称是**C**ross-**O**
-
multipart/form-data
-
application/x-www-form-urlencoded
情况四:
<br
/>
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
<br
/>
情况五:
<br
/>
请求中没有使用 ReadableStream 对象。
情况四:
请求中的任意XMLHttpRequestUpload 对象均没有注册任何事件监听器;XMLHttpRequestUpload 对象可以使用 XMLHttpRequest.upload 属性访问。
情况五:
请求中没有使用 ReadableStream 对象。
```
jsx
// 简单请求
fetch
(
'http://crossdomain.com/api/news'
);
...
...
@@ -219,7 +230,9 @@ fetch('http://crossdomain.com/api/news', {
```
不满足上面的就是复杂请求。一般CORS的设置都是在后端的。
**1、**
普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
<br
/>
2、带cookie跨域请求:前后端都需要进行设置
<br
/>
**【前端设置】根据xhr.withCredentials字段判断是否带有cookie**
**1、**
普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
**【前端设置】根据xhr.withCredentials字段判断是否带有cookie**
```
jsx
// 原生ajax
var
xhr
=
new
XMLHttpRequest
();
// IE8/9需用window.XDomainRequest兼容
...
...
@@ -258,9 +271,9 @@ axios.defaults.withCredentials = true
```
<a
name=
"EBefT"
></a>
### 方法三:代理
**思路:利用服务端请求不会跨域的特性,让接口和当前站点同域。**
<br
/>
代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域。
<br
/>
**思路:利用服务端请求不会跨域的特性,让接口和当前站点同域。**
代理适用的场景是:生产环境不发生跨域,但开发环境发生跨域。

像是vue中,一般是这么处理。现在常用的vue等框架都有解决方案。
...
...
@@ -303,12 +316,13 @@ proxyTable: {
```
<a
name=
"qs5RQ"
></a>
### 方法四:Nginx 反向代理
Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
<br
/>
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。
<br
/>
主要是后端进行nginx配置,就不讲了。
<a
name=
"OoScp"
></a>
Nginx 实现原理类似于 Node 中间件代理,需要你搭建一个中转 nginx 服务器,用于转发请求。
使用 nginx 反向代理实现跨域,是最简单的跨域方式。只需要修改 nginx 的配置即可解决跨域问题,支持所有浏览器,支持 session,不需要修改任何代码,并且不会影响服务器性能。
主要是后端进行nginx配置,就不讲了。
### 方法五:websocket
Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。什么是全双工通信 ?简单来说,就是在建立连接之后,server 与 client 都能主动向对方发送或接收数据。
<br
/>
以第
**三方库 ws**
为例:
Websocket 是 HTML5 的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。什么是全双工通信 ?简单来说,就是在建立连接之后,server 与 client 都能主动向对方发送或接收数据。
以第
**三方库 ws**
为例:
```
jsx
........
const
WebSocket
=
require
(
'ws'
);
...
...
@@ -324,9 +338,9 @@ ws.on('message', function incoming(data) {
});
...
...
```
<a
name=
"BuN2e"
></a>
### 方法六:window.postMessage()
此方法可以安全地实现跨源通信。window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域,可以用这种消息传递技术来实现安全的通信。这项技术称为“
**跨文档消息传递**
”,又称为“
**窗口间消息传递**
”或者“
**跨域消息传递**
”。
<br
/>
它可用于解决以下方面的问题:
此方法可以安全地实现跨源通信。window.postMessage() 方法允许来自一个文档的脚本可以传递文本消息到另一个文档里的脚本,而不用管是否跨域,可以用这种消息传递技术来实现安全的通信。这项技术称为“
**跨文档消息传递**
”,又称为“
**窗口间消息传递**
”或者“
**跨域消息传递**
”。
它可用于解决以下方面的问题:
-
页面和其打开的新窗口的数据传递
-
多窗口之间消息传递
...
...
@@ -341,7 +355,9 @@ otherWindow.postMessage(message, targetOrigin, [transfer]);
> message:要发送的消息。它将会被结构化克隆算法序列化,所以无需自己序列化,html5规范中提到该参数可以是JavaScript的任意基本类型或可复制的对象,然而并不是所有浏览器都做到了这点儿,部分浏览器只能处理字符串参数,所以我们在传递参数的时候需要使用JSON.stringify()方法对对象参数序列化。
> **targetOrigin:**“目标域“。URI(包括:协议、主机地址、端口号)。若指定为”*“,则表示可以传递给任意窗口,指定为”/“,则表示和当前窗口的同源窗口。当为URI时,如果目标窗口的协议、主机地址或端口号这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会发送。
**接收消息**
<br
/>
如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。
<br
/>
获取postMessage传来的消息:为页面添加onmessage事件。
**接收消息**
如果指定的源匹配的话,那么当调用 postMessage() 方法的时候,在目标窗口的Window对象上就会触发一个 message 事件。
获取postMessage传来的消息:为页面添加onmessage事件。
```
jsx
window
.
addEventListener
(
'message'
,
function
(
e
)
{
var
origin
=
event
.
origin
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment