浅谈javascript之JSON和跨域
目录
一、JSON
1:前因 — 由于js对象只能识别js对象,java只能识别java对象,前后端数据交互,需要把数据转化为字符串,这也代表着需要一个转化工具,而这个转化工具就是JSON。
JSON就是一种特殊的字符串,这个字符串能被任意语言识别,并且能转化为任意语言的对象
2:后果 — JSON:JavaScript 对象表示法(JavaScript Object Notation)
JSON作用:主要用来数据交互中字符串和对象的互相转化
Javascript Object Notation js对象表示法
JSON和JS对象的格式一样,只不过JSON中的对象的属性名需要加""
3:JSON的分类: 对象-{} 数组-[]
4:JSON中允许的值: 1:字符串; 2:布尔值; 3:数值; 4:null; 5:数组; 6:对象;
5:JSON的转化方法
01:将JSON字符串转化为js对象的方法是 JSON.parse()
参数:为JSON字符串; 返回值:为js对
02:将js对象转化为JSON字符串的方法是 JSON.stringifg()
参数:为js对象; 返回值:为JSON字符串
(1):定义一个JSON字符串(对象或数组)
1:JSON对象 —就是字符串里面包含的是对象的格式
2:JSON数组 —就是字符串里面包含的是数组的格式
let obj = '{"name":"pink","age":"18"}'; //创建一个JSON对象
let arr = '[1,3,"haha"]' //创建一个JSON数组
let obj2 = '{"arr":"[1,3,"haha","pin"]"}'
let arr2 = '[{"name":"pink","age":"18"},{"name":"孙武汉","age":"38"}]'
console.log(typeof obj); //string
(2):JSON转化为js对象 ---- JSON.parse(str)
//将JSON字符串转化为对象 JSON.parse(str)
let str = '{"name":"小李","age":13,"sex":"男"}'; //定义一个JSON字符串格式里面存放对象
let str2 = '[{"name":"小谢","age":10,"sex":"男"},{"name":"小潘","age":16}]' //定义一个JSON字符串格式里面存放数组
let obj = JSON.parse(str);
console.log(typeof obj); //object
console.log(obj); //{name: "小李", age: 13, sex: "男"}
let arr = JSON.parse(str2);
console.log(typeof arr); //object
console.log(arr); //[{…}, {…}]
console.log(arr[0]); //{name: "小谢", age: 10, sex: "男"}
(3):JSON将js对象转化为JSON字符串
//2:将js对象转化为JSON字符串 JSON.stringifg(obj)
let obj = {
name: "pink",
age: 33,
sex: "男"
};
let str = JSON.stringify(obj);
console.log(typeof str); //string
console.log(str); //{"name":"pink","age":33,"sex":"男"}
二、跨域
同源和跨域的概念
所谓跨域就是协议号(http等)、域名(www.baidu.com等)、端口号(8080等)这三者之间出现一种不同,就是存在跨域。
-
同源策略请求 ajax / fetch
- 所谓同源:也就是同一个域下的两个页面的具有相同的协议,主机号(域名),端口号
- 所谓同源策略:浏览器出于安全性问题,阻止一个域的js脚本对另外一个域的内容进行交互。
- 跨域的原因:
浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
-
跨域传输
- 所谓跨域:就是协议,域名,端口号三者之间存在不同,就是跨域行为!
服务器的拆分
- Web服务器:静态资源
- data服务器:业务逻辑和数据分析
- 图片服务器:
跨域的详细分析
- 协议
- 域名
- 端口号
假设在自己服务器上编程
WEB服务器地址:http://127.0.01:3000/index.html
数据接口地址:http://127.0.01:4000/list
解决方法一:修改浏览器的安全配置
https://editor.csdn.net/md/?articleId=104475366
服务器代理跨域(Nginx反向代理)
常规的服务器有:apache和nginx等等
-
反向代理(Reverse Proxy)
- 是指以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器;并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个服务器。
-
反向代理的步骤:
01:查询配置的网站的网址和路径- 001:先在网站上查找你要的分类数据,点击堆糖的分类项中的美食菜谱!
- 002:然后你选择在Network中XHR中的ajax请求:
这边会请求到两个数据,一个是你用户的信息(user_id) 和一个美食菜谱的信息 (include_fields) - 003:然后点击General中的第一个Request URL 也就是请求的路径
https://www.duitang.com/napi/blog/list/by_filter_id/? include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&=1594534848872
解析1:是资源的路径 https://www.duitang.com/napi/blog/list/by_filter_id/?
解析2: 参数include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&=1594534848872 - 004:找到这些路径之后,我们可以配置nginx的代理了!
02:第一步找到nginx的配置文件! nginx.conf
- 001: 。。。 phpstudy_pro\Extensions\Nginx1.15.11\conf\vhosts 中的localhost_80.conf文件
- 002: 然后在内部配置需要跨域的网址:
- 003: 以下代码解析!
配置文件:
//解析:localhost = 的的意思就是:地址栏上的第一个位置必须为后面书写的东西 比如(/dt) 后面为一个对象
// 在对象里面书写的是 你要跨域访问的网站url 比如( https://www.juhe.cn/)
// 注意点:就是/dt 也就是等于了 {里面的网址了!} 使用的时候,只需要在前面添加 /dt?拼接后面的参数!
location = /dt {
proxy_pass https://www.duitang.com/napi/blog/list/by_filter_id/;
}
请求的方式的书写:
//需求:比如你想要拿到美食菜谱的img和title等等,渲染到页面,因此你可以发送一个ajax请求
//以 /dt? ---路径
// xhr.open("GET",
// "/dt?include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&_=1594534848872"
// )
//详细的请求代码:
var container = document.querySelector(".container"); //容器
var xhr = new XMLHttpRequest()
xhr.open("GET",
"/dt?include_fields=top_comments%2Cis_root%2Csource_link%2Citem%2Cbuyable%2Croot_id%2Cstatus%2Clike_count%2Csender%2Calbum%2Creply_count&filter_id=%E7%BE%8E%E9%A3%9F%E8%8F%9C%E8%B0%B1&start=24&_=1594534848872"
)
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
// console.log(xhr.responseText); //拿到请求的数据,转为为对象的形式更方便操作! 然后拿到里面的数据,在进行循环遍历!
var data = JSON.parse(xhr.responseText) //转化为对象的形式!
// console.log(data);//我所要拿的数据,是data下data下的object_list 直接遍历这个对象即可!
var data_arr = data.data.object_list; //数据
var html = ""
for (var i = 0; i < data_arr.length; i++) {
// console.log(data_arr[i]);
html += `
<div class="box">
<img class="img" src="${data_arr[i].photo.path}" alt="">
<div class="title">${data_arr[i].msg}</div>
</div>
`
}
container.innerHTML = html;
}
}
}
php的后端代理实现跨域
- 需求:拿到一个天气的数据接口,渲染到页面之中!
- 1:在php中设置
- 2:先找到你要设置的接口php,然后复制下来!
- 3:然后在php文件中添加以下这些!
//一个是中文 一个是秘钥 一个是传递的参数(城市)
header('Content-type:text/html;charset=utf-8');
//配置您申请的appkey
$appkey = "04dbb4728596499a891709faed440669";
$city = $_GET["city"];
详细的php
<?php
header('Content-type:text/html;charset=utf-8');
//配置您申请的appkey
// $appkey = "04dbb4728596499a891709faed440669";
$appkey = "0cd454fbe6ac6d76c67283bb90df9837";
$city = $_GET["city"];
//************1.根据城市查询天气************
// $url = "http://v.juhe.cn/toutiao/index";
$url = "http://op.juhe.cn/onebox/weather/query";
$params = array(
"cityname" => "$city",//要查询的城市,如:温州、上海、北京
"key" => $appkey,//应用APPKEY(应用详细页查询)
"type" => "json",//返回数据的格式,xml或json,默认json
);
$paramstring = http_build_query($params);
$content = juhecurl($url,$paramstring);
$result = json_decode($content,true);
if($result){
if($result['error_code']=='0'){
echo json_encode($result);
}else{
echo $result['error_code'].":".$result['reason'];
}
}else{
echo "请求失败";
}
//**************************************************
/**
* 请求接口返回内容
* @param string $url [请求的URL地址]
* @param string $params [请求的参数]
* @param int $ipost [是否采用POST形式]
* @return string
*/
function juhecurl($url,$params=false,$ispost=0){
$httpInfo = array();
$ch = curl_init();
curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
curl_setopt( $ch, CURLOPT_USERAGENT , 'JuheData' );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 60 );
curl_setopt( $ch, CURLOPT_TIMEOUT , 60);
curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true );
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
if( $ispost )
{
curl_setopt( $ch , CURLOPT_POST , true );
curl_setopt( $ch , CURLOPT_POSTFIELDS , $params );
curl_setopt( $ch , CURLOPT_URL , $url );
}
else
{
if($params){
curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params );
}else{
curl_setopt( $ch , CURLOPT_URL , $url);
}
}
$response = curl_exec( $ch );
if ($response === FALSE) {
//echo "cURL Error: " . curl_error($ch);
return false;
}
$httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE );
$httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) );
curl_close( $ch );
return $response;
}
?>
* {
margin: 0;
padding: 0;
}
.container {
margin: 0 auto;
width: 1300px;
min-height: 300px;
border: 1px solid red;
clear: both;
overflow: hidden;
}
.box {
margin: 5px;
float: left;
width: 250px;
height: 400px;
border: 1px solid #ccc;
}
.box:last-child {
margin-right: 0;
}
.city_code {
height: 30px;
line-height: 30px;
background: pink;
color: #fff;
}
.city_name {
height: 16px;
line-height: 16px;
color: #ccc;
}
.date {
height: 20px;
line-height: 20px;
}
.moon {
height: 20px;
line-height: 20px;
}
.box img {
display: block;
width: 200px;
height: 200px;
}
.time {
height: 20px;
line-height: 20px;
}
#list li {
margin-top: 5px;
height: 20px;
line-height: 20px;
background: yellow;
}
<div class="container">
<!-- <div class="box">
<div class="city_code"></div>
<div class="city_name"></div>
<div class="date"></div>
<div class="moon"></div>
<div class="time"></div>
<ul id="list">
<li></li>
</ul>
</div> -->
</div>
var container = document.querySelector(".container")
//需求:使用后端php代理的方式,去访问外部接口,拿到城市的头条新闻!
// var city = prompt("请输入你需要得到天气的城市:");
var xhr = new XMLHttpRequest();
xhr.open("GET", "./02.php?city=" + "北京")
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
var data = JSON.parse(xhr.responseText);
// console.log(data); //result - data
var data_arr = data.result.data.realtime;
// console.log(data_arr); //遍历对象
var html = ""
var obj = data_arr["weather"]
var arr = [] //定义一个空数组
for (var key in obj) {
arr.push(obj[key])
}
for (var key in data_arr) {
html = `
<div class="box">
<div class="city_code">${data_arr["city_code"]}</div>
<div class="city_name">${data_arr["city_name"]}</div>
<div class="date">${data_arr["date"]}</div>
<div class="moon">${data_arr["moon"]}</div>
<div class="time">${data_arr["time"]}</div>
<ul id="list">
${ arr.map(function(item,i){
return `<li>${item}</li>
`
}).join("") }
</ul>
</div>
`
}
container.innerHTML = html;
}
}
}
CORS 实现跨域
- 跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
- 操作:在后端php语言中添加一个响应头, header(“Access-Control-Allow-Origin:链接”);
- 这样使得链接能够实现跨域访问!
- 需求:
- 1:就是你发起请求的路径的为 http://127.0.0.1/0710/跨域/03.cors.php
- 2:然后你在浏览器输入的路径为localhost/0710/跨域/03.cors.php 这样的话会导致跨域问题!
- 3:解决方案:就是在后端的php之中,添加一个CORS跨域资源共享即可!
header(“Access-Control-Allow-Origin:http://localhost”);
这一句话的意思就是:可以接受请求的资源中域名为localhost的!
注意点:若是不添加以上的请求头,可接受请求域名为localhost的!会造成以下的错误!
Access to XMLHttpRequest at ‘http://127.0.0.1/0710/。。。。。’ from origin ‘http://localhost’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
- 以下为解决方案:
<?php
header("Access-Control-Allow-Origin:http://localhost");
echo "hello world";
?>
var xhr = new XMLHttpRequest()
xhr.open("GET", "http://127.0.0.1/0710/跨域/03.cors.php")
xhr.send()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
console.log(xhr.responseText);
//然后利用这个数据 遍历渲染!
}
}
}
jsonp 实现跨域
- jsonp:所谓的jsonp就是包裹着json数据! 而jsonp跨域就是把json数据存放在一个回调函数里面,用src发起http请求,来获取数据,来实现跨域!
当xhr被禁止的时候,那么可以使用jsonp来实现跨域的行为! - 原理:就是使用标签中的src开发策略,来发起http请求,
- 01:img中src可以发送一个http请求,只不过还会把这个请求的数据解析为img所能识别的,不方便操作,因此不适应!
- 02:script标签中的src发起一个http请求,这样拿到数据之后,可以存放在一个回调函数里面
- 注意点1:回调函数的作用:就是外部数据,可以通过调用的时候,传入参数来访问内部数据!
- 注意点2:拿到的数据的时候,需要设置为全局变量,这样才能实现共享!
- 方案:
- 01:前端定义一个全局函数
- 02:前端中,script标签中的src发起一个http请求(跨域请求,请求其他的js文件,来获取到数据!)
- 03:请求的内容调用前端函数(可以在其他的js文件中调用,也可以在后端php等调用)
- 04:调用时传入实参,在前端全局函数使用形参接受;(其他的文件中的js或者后端传入参数)
一个简单的jsonp跨域!
- 需求:在前端之中,定义一个全局函数,然后在外部或者后端使用这个回调函数
- 访问的时候:http://localhost/0711/01jsonp.html
//HTML
<script>
function callback(data) {
console.log(data);
}
</script>
<script src="http://127.0.0.1/0711/01jsonp.js"></script>
<script src="http://127.0.0.1/0711/01jsonp.php"></script>
//JS
callback("你好啊,世界!");
//PHP
<?php
echo "callback('你好啊,我不在是你了')";
?>
//结果: 你好啊,世界! 你好啊,我不在是你了
使用jsonp跨域的方式,来实现仿百度的搜索框!
//HTML
<p>
<input autofocus type="text" id="ipt">
<button id="seqrch">搜索</button>
<ul class="list">
<!-- <li><a href=""></a></li> -->
</ul>
</p>
//CSS
* {
margin: 0;
padding: 0;
}
li,
ul {
list-style: none;
}
p {
position: relative;
margin: 30px;
height: 30px;
line-height: 30px;
}
p input {
border: 0;
height: 30px;
line-height: 30px;
width: 200px;
background: yellow;
}
.list {
display: none;
position: absolute;
top: 62px;
left: 30px;
width: 200px;
min-height: 30px;
overflow: hidden;
background: #fff;
background: red;
}
//JS
var ipt = document.querySelector("#ipt") //表单
var btn = document.querySelector(".search") //按钮
var list = document.querySelector(".list"); //列表
//点击搜索按钮
ipt.oninput = function (e) {
iptVal = ipt.value; //拿到表单的值
//发起请求
ajax({
method: "jsonp",
url: "https://www.baidu.com/sugrec",
data: {
pre: 1,
p: 3,
ie: "utf-8",
json: 1,
prod: "pc",
from: "pc_web",
sugsid: "32218,1425,31672,32139,31254,32045,32230,32299,31639",
//这是你表单输入的时候,拿到的值,去数据库查询!
wd: iptVal,
req: 2,
csor: 5,
cb: "callback",
_: Date.now()
},
jsonpcallback: "callback",
callback: function (data) {
list.style.display = "block"
var arr = data.g //拿到数据 数组的形式
if (arr instanceof Array) {
list.innerHTML = arr.map(function (item, i) {
// console.log(item.q);
return `
<li><a href="">${item.q}</a></li>
`
}).join("")
} else {
list.style.display = "none"
}
}
})
}
document.onclick = function () {
list.style.display = "none"
}
本文地址:https://blog.csdn.net/weixin_43845137/article/details/107305924
上一篇: javascript仿es6的map类
下一篇: Vue路由的创建和使用方法