1、CSS选择器有哪些?
选择器 | 例子 | 例子描述 | CSS |
---|---|---|---|
.class(Class选择器) | .intro | 选择 class="intro" 的所有元素。 | 1 |
#id(ID选择器) | #firstname | 选择 id="firstname" 的所有元素。 | 1 |
*(全局选择器) | * | 选择所有元素。 | 2 |
element(标签选择器) | p | 选择所有 <p> 元素。 | 1 |
element,element(兄弟选择器) | div,p | 选择所有 <div> 元素和所有 <p> 元素。 | 1 |
element element | div p | 选择 <div> 元素内部的所有 <p> 元素。 | 1 |
element>element(父子选择器) | div>p | 选择父元素为 <div> 元素的所有 <p> 元素。 | 2 |
element+element | div+p | 选择紧接在 <div> 元素之后的所有 <p> 元素。 | 2 |
[attribute] | [target] | 选择带有 target 属性所有元素。 | 2 |
[attribute=value] | [target=_blank] | 选择 target="_blank" 的所有元素。 | 2 |
[attribute~=value] | [title~=flower] | 选择 title 属性包含单词 "flower" 的所有元素。 | 2 |
[attribute|=value] | [lang|=en] | 选择 lang 属性值以 "en" 开头的所有元素。 | 2 |
:link | a:link | 选择所有未被访问的链接。 | 1 |
:visited | a:visited | 选择所有已被访问的链接。 | 1 |
:active | a:active | 选择活动链接。 | 1 |
:hover | a:hover | 选择鼠标指针位于其上的链接。 | 1 |
:focus | input:focus | 选择获得焦点的 input 元素。 | 2 |
:first-letter | p:first-letter | 选择每个 <p> 元素的首字母。 | 1 |
:first-line | p:first-line | 选择每个 <p> 元素的首行。 | 1 |
:first-child | p:first-child | 选择属于父元素的第一个子元素的每个 <p> 元素。 | 2 |
:before | p:before | 在每个 <p> 元素的内容之前插入内容。 | 2 |
:after | p:after | 在每个 <p> 元素的内容之后插入内容。 | 2 |
:lang(language) | p:lang(it) | 选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。 | 2 |
element1~element2 | p~ul | 选择前面有 <p> 元素的每个 <ul> 元素。 | 3 |
[attribute^=value] | a[src^="https"] | 选择其 src 属性值以 "https" 开头的每个 <a> 元素。 | 3 |
[attribute$=value] | a[src$=".pdf"] | 选择其 src 属性以 ".pdf" 结尾的所有 <a> 元素。 | 3 |
[attribute*=value] | a[src*="abc"] | 选择其 src 属性中包含 "abc" 子串的每个 <a> 元素。 | 3 |
:first-of-type | p:first-of-type | 选择属于其父元素的首个 <p> 元素的每个 <p> 元素。 | 3 |
:last-of-type | p:last-of-type | 选择属于其父元素的最后 <p> 元素的每个 <p> 元素。 | 3 |
:only-of-type | p:only-of-type | 选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。 | 3 |
:only-child | p:only-child | 选择属于其父元素的唯一子元素的每个 <p> 元素。 | 3 |
:nth-child(n) | p:nth-child(2) | 选择属于其父元素的第二个子元素的每个 <p> 元素。 | 3 |
:nth-last-child(n) | p:nth-last-child(2) | 同上,从最后一个子元素开始计数。 | 3 |
:nth-of-type(n) | p:nth-of-type(2) | 选择属于其父元素第二个 <p> 元素的每个 <p> 元素。 | 3 |
:nth-last-of-type(n) | p:nth-last-of-type(2) | 同上,但是从最后一个子元素开始计数。 | 3 |
:last-child | p:last-child | 选择属于其父元素最后一个子元素每个 <p> 元素。 | 3 |
:root | :root | 选择文档的根元素。 | 3 |
:empty | p:empty | 选择没有子元素的每个 <p> 元素(包括文本节点)。 | 3 |
:target | #news:target | 选择当前活动的 #news 元素。 | 3 |
:enabled | input:enabled | 选择每个启用的 <input> 元素。 | 3 |
:disabled | input:disabled | 选择每个禁用的 <input> 元素 | 3 |
:checked | input:checked | 选择每个被选中的 <input> 元素。 | 3 |
:not(selector) | :not(p) | 选择非 <p> 元素的每个元素。 | 3 |
::selection | ::selection | 选择被用户选取的元素部分。 | 3 |
jQuery 选择器
选择器 | 实例 | 选取 |
---|---|---|
* | $("*") | 所有元素 |
#id | $("#lastname") | id="lastname" 的元素 |
.class | $(".intro") | 所有 class="intro" 的元素 |
element | $("p") | 所有 <p> 元素 |
.class.class | $(".intro.demo") | 所有 class="intro" 且 class="demo" 的元素 |
:first | $("p:first") | 第一个 <p> 元素 |
:last | $("p:last") | 最后一个 <p> 元素 |
:even | $("tr:even") | 所有偶数 <tr> 元素 |
:odd | $("tr:odd") | 所有奇数 <tr> 元素 |
:eq(index) | $("ul li:eq(3)") | 列表中的第四个元素(index 从 0 开始) |
:gt(no) | $("ul li:gt(3)") | 列出 index 大于 3 的元素 |
:lt(no) | $("ul li:lt(3)") | 列出 index 小于 3 的元素 |
:not(selector) | $("input:not(:empty)") | 所有不为空的 input 元素 |
:header | $(":header") | 所有标题元素 <h1> - <h6> |
:animated | 所有动画元素 | |
:contains(text) | $(":contains('W3School')") | 包含指定字符串的所有元素 |
:empty | $(":empty") | 无子(元素)节点的所有元素 |
:hidden | $("p:hidden") | 所有隐藏的 <p> 元素 |
:visible | $("table:visible") | 所有可见的表格 |
s1,s2,s3 | $("th,td,.intro") | 所有带有匹配选择的元素 |
[attribute] | $("[href]") | 所有带有 href 属性的元素 |
[attribute=value] | $("[href='#']") | 所有 href 属性的值等于 "#" 的元素 |
[attribute!=value] | $("[href!='#']") | 所有 href 属性的值不等于 "#" 的元素 |
[attribute$=value] | $("[href$='.jpg']") | 所有 href 属性的值包含以 ".jpg" 结尾的元素 |
:input | $(":input") | 所有 <input> 元素 |
:text | $(":text") | 所有 type="text" 的 <input> 元素 |
:password | $(":password") | 所有 type="password" 的 <input> 元素 |
:radio | $(":radio") | 所有 type="radio" 的 <input> 元素 |
:checkbox | $(":checkbox") | 所有 type="checkbox" 的 <input> 元素 |
:submit | $(":submit") | 所有 type="submit" 的 <input> 元素 |
:reset | $(":reset") | 所有 type="reset" 的 <input> 元素 |
:button | $(":button") | 所有 type="button" 的 <input> 元素 |
:image | $(":image") | 所有 type="image" 的 <input> 元素 |
:file | $(":file") | 所有 type="file" 的 <input> 元素 |
:enabled | $(":enabled") | 所有激活的 input 元素 |
:disabled | $(":disabled") | 所有禁用的 input 元素 |
:selected | $(":selected") | 所有被选取的 input 元素 |
:checked | $(":checked") | 所有被选中的 input 元素 |
2、position的几种定位
一、常见/用的四种
1.static
positon定位的默认值,没有定位
2.relative
生成相对定位的元素,相对于其正常位置进行定位,一般在子元素设置absoute定位时,给父元素设置relative
元素的位置通过top、right、bottom、left 控制,其值的定位起点都是是父元素左上角(这点和absoute、fixed不一样)
3.absoute
生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位
元素的位置通过top、right、bottom、left 控制,top、left的定位起点是包含块左上角,right、bottom的定位起点是包含块右下角
4.fixed (ie6不兼容)
生成绝对定位的元素,相对于浏览器窗口进行定位,和absoute的区别是fixed不会跟随屏幕滚动(常见的各种贴屏广告)
元素的位置通过top、right、bottom、left 控制,top、left的定位起点是包含块左上角,right、bottom的定位起点是包含块右下角
二、不常用的四种
1.inherit
规定应该从父元素继承 position 属性的值
inherit 关键字可用于任何 HTML 元素上的任何 CSS 属性
兼容:ie7及以下版本不支持此属性
2.initial
设置positon的值为默认值(static)
兼容:ie不支持此属性
问:有了static为什么还会存在此属性,不是多此一举?
答:initial 关键字可用于任何 HTML 元素上的任何 CSS 属性,不是postion特有的
3.unset
设置positon的值为不设置:
如果该属性的默认属性是 继承属性(例如字体相关的默认属性基本都是继承),该值等同于 inherit
如果该属性的默认属性 不是继承属性(例如pisition的默认属性为static),该值等同于 initial
兼容:ie不支持此属性
4.sticky(粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。)
css3新属性,它的表现就像position:relative和position:fixed的合体:
1.在目标区域在屏幕中可见时,它的行为就像position:relative;
2.页面滚动时
当父元素是body时
a.滚动距离小于屏幕高度或宽度,它会固定在目标位置
b.滚动距离大于屏幕高度或宽度,它的表现就像position:relative和1一样
元素不是body,在父元素高度内滚动时它会固定在目标位置,就像fixed
在父元素滚动为不可视时它的表现就像position:relative和1一样
兼容: ie不兼容、google不完全兼容(thead、tr标签不支持)、firefox59以后兼容,之前版本不完全兼容(table标签不支持)
附上链接:https://developer.mozilla.org/zh-CN/docs/Web/CSS/position
3、数组去重
1.第一种方式就是最简单的set去重(o(n))
var arr = [1,2,2,4,3,4,1,3,2,7,5,6,1];var newArr = new Set(arr)
2.第二种方式就是用indexOf来去重(o(n^3))
判断新数组中某个数字是否存在
function fn(arr){ let newArr = [] arr.forEach((val)=>{ if(newArr.indexOf(val) == -1){ newArr.push(val) } }) return newArr }
3.第三种方式普通去重(o(n^3))
for(var i=0;i<arr.length;i++){ for(var j=i+1;j<arr.length;j++){ if(arr[i]==arr[j]){ arr.splice(j,1) } } }
4.键值去重(o(n^3))
根据键值是唯一的来去重
function fn(arr){let arr1 = [],
arr2 = []
arr.forEach((val)=>{
arr1[val]=val
})
//arr1数组会存在空的情况
//所以返回arr2
arr1.forEach((val)=>{
if(!!val){
arr2.push(val)
}
})
return arr2
}
5.sort排序后去重(o(n^2))
只比set复杂度低
function fn(arr){ let newArr = [] arr.sort((a,b)=>{ return a-b }) arr.forEach((val,index)=>{ if(val != arr[index+1]){ newArr.push(val) } }) return newArr }
6、for遍历
function distinct(a, b) { let arr = a.concat(b) let result = [] let obj = {} for (let i of arr) { if (!obj[i]) { result.push(i) obj[i] = 1 } } return result }
7、include去重
function unique(arr) {
if (!Array.isArray(arr)) {
console.log('type error!')
return
}
var array =[];
for(var i = 0; i < arr.length; i++) {
if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
array.push(arr[i]);
}
}
return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}] //{}没有去重
8、利用hasOwnProperty
function unique(arr) {
var obj = {};
return arr.filter(function(item, index, arr){
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //所有的都去重了
利用hasOwnProperty 判断是否存在对象属性
9、利用filter
function unique(arr) {
return arr.filter(function(item, index, arr) {
//当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
return arr.indexOf(item, 0) === index;
});
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
10、利用reduce+includes
function unique(arr){
return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
延伸知识点:
常规indexOf与if判断写法:
1 if("112233".indexOf("22")>-1) { 2 console.log("很二"); 3 }else { 4 console.log("怎么一点都不二"); 5 }
以上代码是否是我们平时在写js逻辑时最常用写法,是否觉得有点out?来看看下面的装逼写法(PS:大神请忽略)
1 if(~"112233".indexOf("22")) { 2 console.log("很二"); 3 }else { 4 console.log("怎么一点都不二"); 5 }
注意indexOf前面的“~”,位运算:-1取反为0,0在if判断里面false
按位非 ~ 处理的巧用就来看看~1的计算步骤:
本文链接:https://blog.csdn.net/zjl199303/article/details/82586323
将1(这里叫:原码)转二进制 = 00000001
按位取反 = 11111110
发现符号位(即最高位)为1(表示负数),将除符号位之外的其他数字取反 = 10000001(符号位为0代表正数)
末位加1取其补码 = 10000010
转换回十进制 = -2
如 ~1 = -2; ~2 = -3;
应用:
~取反的用法是,是因为-1的取反操作等于0,而其他数的取反操作不等于0。
所以用indexOf操作符可以用~操作来判断某个字符串里是否有某个字符。
var str = '123456'
if(~str.indexOf(0)){ // ~str.indexOf(0) != 0 包含
console.log('取反之后不为零,说明indexOf的结果不等于-1,所以表示str字符串里包含了对应字符')
} else { // ~str.indexOf(0) == 0 不包含
console.log('说明取反之后为零,说明indexOf的结果等于-1,所以表示str字符串里不包含了对应字符')
js中 ~(按位非)运算符妙用
2018-12-20 10:14:12 SSSkyCong 阅读数 136更多
转载:https://www.aliyun.com/jiaocheng/363385.html
- 摘要:基础知识:某个数值的按位非操作,可以简单的理解为该值取负值后减1例如:~5=-5-1=-6~-5=5-1=4~4=-4-1=-5原理:二进制数的负数是取该二进制数的补码,然后+1。二进制数,最高位为0表示正数,最高位为1表示负数。(最高位分不同情况存储不一样)5的二进制表示:00000101(假设最高位为8位)补码:11111010-5:11111011(~)按位非操作其实就是取补码的过程,也就是上述求该值负数的逆过程,所以可以简单的理解为该值取负值后减1。5的补码就是~5,
基础知识:某个数值的按位非操作,可以简单的理解为该值取负值后减1
例如:
~5 = -5-1 = -6
~-5 = 5-1 = 4
~4 = -4-1 = -5
原理:二进制数的负数是取该二进制数的补码,然后+1。
二进制数,最高位为0表示正数,最高位为1表示负数。(最高位分不同情况存储不一样)
5的二进制表示:00000101 (假设最高位为8位)
补码:11111010
-5:11111011(~)按位非操作其实就是取补码的过程,也就是上述求该值负数的逆过程,所以可以简单的理解为该值取负值后减1。
5的补码就是~5,那么~5+1 = -5,所以~5 = -5-1 = -6
应用:
1、indexOf()判断数组或者字符串中是否存在某个元素,一般使用indexOf()如下:
if(str.indexOf(query) != -1) {}
if(str.indexOf(query) >= 0) {}现在可以更加清爽和高端的写成:
if(~str.indexOf(query)) {}原理:
不存在返回-1,~-1 = 0 ,大于-1的值,0,1,2,3 ... 按位非的值1,2,3,4...都大于0ps: 这种写法可不仅仅的B格高这么简单,位运算相对于比较运算符效率高,对于一次运算本身来说,可能相差无几,但在循环次数过大,比如超过了10000000次,效率就会有差距。
2、~~value的使用对于浮点数,~~value可以代替parseInt(value),而且前者效率更高些
parseInt(-2.99) //-2
~~(-2.99) //-2ps: 这些技巧可能会给阅读代码的同学造成困扰,如果不知道原理的话,甚至让人费解。因此平时写代码的时候,要根据情况决定采用哪种写法。
4、两个字符串找最大公共子串
//查找两个字符串的最长公共子串
function
findSubStr(s1,s2){
var
S=sstr=
""
,L1=s1.length,L2=s2.length;
if
(L1>L2){
var
s3=s1;s1=s2,s2=s3,L1=s2.length;}
for
(
var
j=L1;j> 0 ;j--)
for
(
var
i= 0 ;i<=L1-j;i++){
sstr = s1.substr(i,j);
if
(s2.indexOf(sstr)>= 0 )
return
sstr;
}
return
""
;
}
document .writeln(findSubStr(
"aaa3333"
,
"baa333cc"
));
//aa333
document .writeln(findSubStr(
"aaaX3333--"
,
"baa333ccX3333333x"
));
//X3333
延伸:
JS求最长公共子序列、最大公共子串、最大子段和
2018.09.19 13:38:10字数 86阅读 1628
一、最长公共子序列
// 求最长公共子序列的长度
function lcs(str1, str2) {
var len1 = str1.length;
var len2 = str2.length;
var dp = []; // 首先定义一个一维数组
for (var i = 0; i <= len1; i++) {
dp[i] = []; // 将一维数组升级为二维数组
for (var j = 0; j <= len2; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
continue;
}
if (str1[i - 1] == str2[j - 1]) { // dp 的维度为 (len1+1)*(len2+1),str 的维度为 (len1)*(len2)
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]); // 否则取当前位置上或左的最大数
}
}
}
return dp[len1][len2]; // 返回二维数组最后一个值
}
console.log(lcs('abcda', 'bcdda')); // 4
// 打印出最长公共子序列
function lcs(str1, str2) {
var len1 = str1.length,
len2 = str2.length;
var dp = [];
for (var i = 0; i <= len1; i++) {
dp[i] = [];
for (var j = 0; j <= len2; j++) {
if (i == 0 || j == 0) {
dp[i][j] = 0;
continue;
}
if (str1[i - 1] == str2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
var result = printLCS(dp, str1, str2, len1, len2);
return result;
}
// 打印公共子序列
function printLCS(dp, str1, str2, i, j) {
if (i == 0 || j == 0) {
return "";
}
if (str1[i - 1] == str2[j - 1]) {
return printLCS(dp, str1, str2, i - 1, j - 1) + str1[i - 1];
} else if (dp[i][j - 1] > dp[i - 1][j]) {
return printLCS(dp, str1, str2, i, j - 1);
} else {
return printLCS(dp, str1, str2, i - 1, j);
}
}
console.log(lcs('abcda', 'bcdda')); // bcda
二、最大公共子串
function findSubStr(str1, str2){
if (str1.length > str2.length) {
var temp = str1;
str1 = str2;
str2 = temp;
}
var len1 = str1.length,
len2 = str2.length;
for (var j = len1; j > 0; j--) {
for (var i = 0; i < len1 - j; i++) {
var current = str1.substr(i, j);
if (str2.indexOf(current) >= 0) {
return current;
}
}
}
return "";
}
console.log(findSubStr("aaa3333", "baa333cc")); // aa333
console.log(findSubStr("aaaX3333--", "baa333ccX3333333x")) // X3333
三、最大子段和
function maxSum(arr) {
var current = 0,
sum = 0;
for (var i = 0; i < arr.length; i++) {
if (current > 0) {
current += arr[i];
} else {
current = arr[i];
}
if (current > sum) {
sum = current;
}
}
return sum;
}
console.log(maxSum([1, 2, -1, 3, -8, -4])); // 5
5、字符串找最长连续数字子序列,输出长度
js 正则找出最长连续子串长度
function maxLenStr(str){
var len = 0, max_len = 0;
var reg = new RegExp("(.)\\1{1,}","g");
var res = reg.exec(str);
while(res != null){
len = res[0].length;
if(max_len < len){
max_len = len;
}
res = reg.exec(str)
}
return max_len;
}
6、唠一唠cookie和webStorage?
本文链接:https://www.jianshu.com/p/084ea697f33d
Cookies和WebStorage区别
Cookie的诞生
由于HTTP协议是无状态的,而服务器端的业务必须是要有状态的。Cookie诞生的最初目的是为了存储web中的状态信息,以方便服务器端使用。比如判断用户是否是第一次访问网站。目前最新的规范是RFC 6265,它是一个由浏览器服务器共同协作实现的规范。
Cookie的实行步骤
1.服务器像客户端发送cookie。
2.浏览器将将cookie以key/value保存到某个目录的文本文件内。
3.之后每次http请求浏览器都会将cookie发送给服务器端。(前提是浏览器设置为启用cookie)
4.cookie通过HTTP请求报文和响应报文配合完成会话过程。
cookie 的缺点
1.cookie体积过大会造成请求和响应速度变慢。
2.默认浏览器会任何请求都把cookie带上去(即使不需要),哪怕是静态资源。
3.cookie可以在前后端修改,数据容易篡改或伪造。
4.cookie对于敏感数据的保护基本是无效的。
5.有些用户是禁用掉cookie的。
6.cookie 不能跨越多个域名使用。
7.单个 cookie 保存的数据不能超过 4k ,很多浏览器都限制一个站点最多保存 20 个 cookie。
为了破解Cookie的一系列限制,HTML5通过JS的新的API就能直接存储大量的数据到客户端浏览器,而且支持复杂的本地数据库,让JS更有效率。 HTML5支持两种的WebStorage:
1.永久性的本地存储(localStorage):持久化的本地存储(浏览器关闭重新打开数据依然存在),:永久的,除非手动删除 。
特点:
① 域内安全、永久保存。即客户端或浏览器中来自同一域名的所有页面都可访问localStorage数据且数据除了删除否则永久保存,但客户端或浏览器之间的数据相互独立。
② 数据不会随着Http请求发送到后台服务器;
③ 存储数据的大小机会不用考虑,因为在HTML5的标准中要求浏览器至少要支持到4MB。
2.会话级别的本地存储(sessionStorage): 针对一个session的本地存储,临时的,窗口关闭就没有了。(会话级别)。
特点:
①会话控制、短期保存。会话概念与服务器端的session概念相似,短期保存指窗口或浏览器或客户端关闭后自动消除数据。
**Cookie和webstorage区别 **
image.png
webStorage的优势:
相比cookie存储容量增加
可以将请求的表单数据存于本地,减少http请求,节约带宽
webStorage拥有易用的API
webStorage的局限性:
不同浏览器webStorage 和LocalStorage的大小不统一。
在浏览器的隐私模式下面是不可读取的
本质上是对字符串的读取,因此存储内容过多时页面会变卡
不能被爬虫抓取到
WebStorage是什么?
本文链接:https://www.jianshu.com/p/26e1e9fa7089
WebStorage
使用HTML5可以在本地存储用户的浏览数据。早些时候,本地存储使用的是 cookie。但是Web 存储需要更加的安全与快速,这些数据不会被保存在服务器上,但是这些数据只用于用户请求网站数据上。它也可以存储大量的数据,而不影响网站的性能。数据以 键/值 对存在, web网页的数据只允许该网页访问使用。
Web Storage的目的是为了克服由cookie带来的一些限制,当数据需要被严格控制在客户端上时,无须持续地将数据发回服务器。Web Storage的两个主要目标是:
- 提供一种在cookie之外存储会话数据的途径。
- 提供一种存储大量可以跨会话存在的数据的机制。
Web Storage又分为两种: sessionStorage 和localStorage ,即这两个是Storage的一个实例。从字面意思就可以很清楚的看出来,sessionStorage将数据保存在session中,浏览器关闭也就没了;而localStorage则一直将数据保存在客户端本地。其API提供的方法有以下几种:
- setItem (key, value) —— 保存数据,以键值对的方式储存信息。
- getItem (key) —— 获取数据,将键值传入,即可获取到对应的value值。
- removeItem (key) —— 删除单个数据,根据键值移除对应的信息。
- clear () —— 删除所有的数据
- key (index) —— 获取某个索引的key
localStorage
localStorage的生命周期是永久性的。假若使用localStorage存储数据,即使关闭浏览器,也不会让数据消失,除非主动的去删除数据,使用的方法如上所示。localStorage有length属性,可以查看其有多少条记录的数据。使用方法如下:
var storage = null;
if(window.localStorage){ //判断浏览器是否支持localStorage
storage = window.localStorage;
storage.setItem("name", "Rick"); //调用setItem方法,存储数据
alert(storage.getItem("name")); //调用getItem方法,弹框显示 name 为 Rick
storage.removeItem("name"); //调用removeItem方法,移除数据
alert(storage.getItem("name")); //调用getItem方法,弹框显示 name 为 null
}
localStorage 相对sessionStorage简单一点,需要注意的地方不是很多。
sessionStorage
sessionStorage 的生命周期是在浏览器关闭前。也就是说,在整个浏览器未关闭前,其数据一直都是存在的。sessionStorage也有length属性,其基本的判断和使用方法和localStorage的使用是一致的。需要注意的有以下几点:
- 页面刷新不会消除数据;
- 只有在当前页面打开的链接,才可以访sessionStorage的数据;
- 使用window.open打开页面和改变localtion.href方式都可以获取到sessionStorage内部的数据;
网页设置cookie:
jQuery.cookie.js插件
//第一种类型:会话cookie
// //1、设置值
// $.cookie("phone","13188886666");
// $.cookie("email","123@qq.com");
// //2、获取值
// var phone=$.cookie("phone");
// console.log(phone);
// var email=$.cookie("email");
// console.log(email);
//第二种类型:设置长期cookie(具有指定有效期)
// $.cookie("address","广东深圳市",{
// expires:7 //expires不仅仅可以是日期类型的对象,也可以是以天为单位的数字
// });
// $.cookie("tel","0755-88888888",{
// expires:1/24 //该cookie值就会保存一小时
// });
// $.cookie("birthday","1.1",{
// expires:new Date("2018-01-01 08:00") //对于这样的过期时间,已经在内部处理好了时区问题
// });
//删除指定的cookie
$.removeCookie("birthday");
原文链接:https://blog.csdn.net/m0_37452696/article/details/78310238
项目中用到的cookie:
设置$.cookie: $.cookie('singlePage','1');
获取cookie:var valueB = $.cookie('singlePage');
清除cookie:$.cookie('singlePage', '', {expires: 0, path: location.pathname});
跨页面传值的几种简单方式
方法一:
通过URL传值
eg:
location.href="跨页面1-2.html?age=18&gender=man";
在下个页面接收:
//1、location.search获取get请求的参数 获取到的数据,是以?开头的
var search=location.search;
//2、如果还想要获取确定的数据,可以解析字符串
function parse(search){
//从第二个字符开始截取 ,获取到第二个开始后面所有的字符
var str=search.substring(1);
var result={};
//分割字符串 -->产生字符串数组
var strs=str.split("&");
//遍历数组中的每一个元素
strs.forEach(function(v){
//伪代码:v="age=18"
var keyvalue=v.split("=");
var name=keyvalue[0];
var value=keyvalue[1];
result[name]=value;
})
return result;
}
var r=parse(search);
方法二:
使用h5的localStorage,或者sessionStorage存储对象类型
存储对象的正确的方式:
var p2={name:"周瑜",age:16};
var s2=JSON.stringify(p2); //将对象"序列化"为JSON数据(字符串格式)
localStorage.setItem("p2",s2); //以字符串格式存储信息
var s2_2=localStorage.getItem("p2"); //获取存储的信息,也是字符串格式
var p2_2=JSON.parse(s2_2); //将JSON数据反序列化为对象
localStroage和sessionStorage使用大致相同,他们的不同之处在于,localstroage是永久保存,而sessionstroage是会话存在,
当会话结束,sessionstroage保存值也会清空。
方法三:
使用cookie保存:
原生cookie
//1、保存一条数据
document.cookie="name=abc";
document.cookie="age=18";
//2、获取所有数据
var cookie=document.cookie;
console.log(cookie); //"name=abc; age=18; PHPSESSID=fr1njdv6apf3neoj5nehntrps7"
//之后可以解析字符串,获取指定的数据内容
//3、设置cookie的有效期
document.cookie="id=666;expires="+new Date("2017-10-22 08:00");
7、如何还原设计稿
前端入门篇(一):如何把设计稿还原成真实网页
0.0962016.03.27 22:20:24字数 1641阅读 11171
如果你对网页设计及开发感兴趣,但是对标题里出现的第一个名词就摸不着头脑,先不要方。本文对小白友好,零基础可读,保证你读完能了解网页开发的基本思路和流程,明白网页设计稿是怎样被开发实现的。
一、什么是前端
首先,所谓的前端是指什么呢?前端(front-end)是相对后端(back-end)而言的,是描述进程开始和结束的通用词汇。在计算机程序中,前端作用于采集输入信息,后端进行处理。
而我们通常所说的「前端」,一般是指web前端,可以理解为网页的界面样式和视觉呈现。所以,前端设计一般视作网站的视觉设计,前端开发则是视觉设计的代码实现。
二、前端开发语言
HTML、CSS和JavaScript是前端开发中三种最基础的代码语言。看到代码你先别急着关网页,先来欣赏下使用不同程序语言的程序员之间的鄙视链(笑)。
汇编 >C >C++ >Python >Java 及 C# 及 PHP(这三者相互撕) >VB >那些坚持把HTML称为程序语言的人
所以你大概明白了,对于完全零基础的人来说,前端开发所用的语言(除了JavaScript),是相对比较容易学习和上手的。
2.1HTML/CSS/JavaScipt
你可以把网页想象成一间房子。HTML决定了网页的框架结构——有几间房间、作什么用途、里面摆放什么东西,CSS决定了网页的样式——房间是如何装潢的(如墙壁是什么颜色的),JavaScript则决定了网页上的用户交互和数据处理——用遥控器遥控电视。
下面简单介绍一下HTML和CSS语言的用处和用法,如果想继续学习,可以参考翁恺老师的两门公开课程——HTML5入门和CSS3。
2.2HTML
HTML是一种网页标记语言。它主要是利用标签来告诉浏览器,标签之间的东西是什么——是标题、段落、图片还是链接等。浏览器则会根据HTML标签,相应地作出显示。下面举几个栗子:
<h1>这是1级标题</h1>
<p>这是段落</p>
<a href=“这是链接地址”>这是链接的文字</a>
<img src=“这是图片的路径或链接地址”/>
2.3CSS
CSS中文名叫做「层叠样式表」,从名字里就可以看出,它是一种声明样式的文档。我们可以通过链接外部css文档,或者将样式写在HTML文档的<head></head>
标签中,抑或在HTML标签中内嵌属性style=""
来实现对样式的定义。举个例子,我们要让<p>这个段落</p>
的背景变成灰色,就可以用以下三种方法实现:
/*方法一:直接用style属性*/
<p style=“background-color:grey;”>这是段落</p>
/*方法二:在HTML文档的<head>标签中声明(会应用于页面中所有的<p></p>段落)*/
<head>
<style>
p{
background-color:grey;
}
</style>
</head>
/*方法三:通过外链实现*/
//另建一个css文档,在其中写上方法二中<style>标签间的内容,再在HTML文档中作如下声明
<head>
<link href=“css文档的路径” rel=“stylesheet" type=“text/css” />
</head>
三、网页上的框
代码语言只是前端开发实现的基础工具,要还原一个网页视觉稿,你还需要掌握以下的方法,并且记住——网页上的所有东西都盛放在框中。
3.1Chrome开发者工具
Chrome开发者工具是对前端开发最有用的神器,对,没有之一。它不仅可以让你看到网页的源码,每个元素的样式、构成,还能让你编辑源码并且实时查看页面效果。
你可以在Chrome的菜单栏中,点击更多工具>开发者工具
打开开发者工具,也可以在网页任意位置右击,点击检查
打开。打开后,可以同时看到网页页面和开发者工具窗口。其中开发者工具左半边是HTML的源码,里面有各种各样的元素,右边显示的是你在左半边选择的元素的样式。
Chrome开发者工具
点击开发者工具左半边窗口中的各种标签,你可以看到页面上你所选择的元素周围出现了一个亮色的框(如上图所示)。这就是所谓的「任何一个页面元素都盛放在框中」。
3.2如何框化视觉稿
知道了网页元素都盛放在框中对于前端开发有啥用呢?用处可大了去了。现在,假设你是一个前端开发工程师,设计师给了你如下的设计稿,你该做的第一步是什么呢?
apple.cn
那就是把设计稿上你能看到的所有元素都放进框中,不光是那些天然已经是框状的图片,还有那些不呈现为方框状的文字等。实际上,一个HTML的标签(例如<p>123</p>
)就是一个框。
框化视觉稿
还要注意的是,框是可以嵌套的。所以,要框化这个视觉稿,你首先应该找出一个包括整个页面的最大的框,然后再找出将页面明显分成几块的次大框,再找更小的框,一直找下去,直到无法再分下去。
3.3框化后的代码实现
等你把所有元素都框化以后,就可以着手开始写代码还原设计稿了。顺序是从最外面的框写起,不断往里面写。这里面有的框是并列关系,比如:
<p>我是段落一,也是框一,我和二是并列哒</p>
<p>我是段落二,也是框二,我和一是并列哒</p>
也可能是包含关系:
<div>
<p>我是段落方框,我被外面的div层的框所包围</p>
</div>
四、前端开发的流程
有了工具和方法,那网页设计稿的实现具体是怎样操作的呢?步骤可以概括如下:
- 从设计师那里(或者自己设计好)拿到网页的设计稿
- 分析设计稿,找到那些现成的框
- 找出那些样式重复的元素(或框)——如1级标题、2级标题、段落等
- 写HTML代码,把内容盛放进框中
- 写CSS代码,定义元素(或框)的样式(从大的样式特征——如框的宽度,到小的——如字体字重)
- 保存代码,在浏览器中打开,检查和设计稿的差距,调整代码
- 重复4-6步直到还原设计稿
8、上传文件和上传图片需要考虑些什么
使用表单上传文件的过程及需要考虑的问题
1、文件上传的原理分析
1.1 文件上传的必要前提:
a、提供form表单,method必须是post
b、form表单的enctype必须是multipart/form-data
c、提供input type="file"类的上传输入域
1.2 enctype属性
作用:告知服务器请求正文的MIME类型。(请求消息头:Content-Type作用是一致的)
可选值:
application/x-www-form-urlencoded(默认):
正文:name=admin&password=123
服务器获取数据:String name = request.getParameter(“name”);
multipart/form-data:
正文:
服务器获取数据:request.getParameter(String)方法获取指定的表单字段字符内容,但文件上传表单已经不在是字符内容,而是字节内容,所以失效。
文件上传:解析请求正文的每部分的内容。
2、借助第三方的上传组件实现文件上传
2.1 fileupload概述
fileupload是由apache的commons组件提供的上传组件。它最主要的工作就是帮我们解析request.getInputStream()。
导入commons-fileupload相关jar包
commons-fileupload.jar,核心包;
commons-io.jar,依赖包。
2.2 fileupload的核心类有:
DiskFileItemFactory、ServletFileUpload、FileItem。
a、解析原理
2.2 fileupload简单应用
使用fileupload组件的步骤如下:
1. 创建工厂类DiskFileItemFactory对象:
DiskFileItemFactory factory = new DiskFileItemFactory()
2. 使用工厂创建解析器对象:
ServletFileUpload fileUpload = new ServletFileUpload(factory)
3. 使用解析器来解析request对象:
List list = fileUpload.parseRequest(request)
FileItem对象对应一个表单项(表单字段)。可以是文件字段或普通字段
boolean isFormField():判断当前表单字段是否为普通文本字段,如果返回false,说明是文件字段;
String getFieldName():获取字段名称,例如:,返回的是username;
String getString():获取字段的内容,如果是文件字段,那么获取的是文件内容,当然上传的文件必须是文本文件;
String getName():获取文件字段的文件名称;(a.txt)
String getContentType():获取上传的文件的MIME类型,例如:text/plain。
int getSize():获取上传文件的大小;
InputStream getInputStream():获取上传文件对应的输入流;
void write(File):把上传的文件保存到指定文件中。
delete();
3、文件上传时要考虑的几个问题(经验分享)
a、保证服务器的安全
把保存上传文件的目录放在用户直接访问不到的地方。
b、避免文件被覆盖
让文件名唯一即可
c、避免同一个文件夹中的文件过多
方案一:按照日期进行打散存储目录
方案二:用文件名的hashCode计算打散的存储目录:二级目录
d、限制文件的大小:web方式不适合上传大的文件
单个文件大小:
ServletFileUpload.setFileSizeMax(字节)
总文件大小:(多文件上传)
ServletFileUpload.setSizeMax(字节)
e、上传字段用户没有上传的问题
通过判断文件名是否为空即可
f、临时文件的问题
DiskFileItemFactory:
作用:产生FileItem对象
内部有一个缓存,缓存大小默认是10Kb。如果上传的文件超过10Kb,用磁盘作为缓存。
存放缓存文件的目录在哪里?默认是系统的临时目录。
如果自己用IO流实现的文件上传,要在流关闭后,清理临时文件。
FileItem.delete();
前端上传文件的方法总结
最近做了阿里云的oss上传,顺便来总结下上传文件的几种主要方法。
第一种:经典的form和input上传。
设置form的aciton为后端页面,enctype="multipart/form-data",type=‘post’
<form action='uploadFile.php' enctype="multipart/form-data" type='post'> <input type='file'> <input type='hidden' name='userid'> <input type='hidden' name='signature'> <button>提交</button> </form>
使用input选择文件,设置好其他input的值,点击提交,将文件数据及签名等认证信息发送到form设置的action对应的页面,浏览器也会跳转到该页面。触发form表单提交数据的方式有2种,一种是在页面上点击button按钮或<input type='submit'>按钮触发,第二种是在js中执行form.submit()方法。
优点:使用简单方便,兼容性好,基本所有浏览器都支持。
缺点:1. 提交数据后页面会跳转(下面会讲如何禁止页面跳转)。
2.因为是浏览器发起的请求,不是一个ajax,所以前端无法知道什么时候上传结束。
3. form表单里发送除文件外的数据,一般是新建一个type=hidden的input,value=‘需要传的数据’,每发送一个数据就需要一个input,一旦多了就会使得dom看起来比较冗余。
小技巧:
form表单提交数据后会自动跳转到action指定的页面,为了禁止页面跳转,可以在页面中新建一个空的ifame,比如name='upload',然后设置form的target="Uploader",form有一个target的属性,规定在何处打开action,这样form提交数据后就会仍停留在当前页。代码如下:
<form action='uploadFile.php' enctype="multipart/form-data" type='post' target="uploader1"> <input type='file'> <button>提交</button> </form> <ifrmae name='upload' id='uploader1'></iframe>
这样写的另一个好处是,可以知道什么时候上传完成并接收到后端的回调结果。比如上面这个例子,文件数据发送到了 'uploadFile.php',假设该页面处理完数据后返回了一个地址,该地址会被写入到之前的iframe中。所以在ifame的onload函数触发时,也就是上传完成后,可以在iframe中读取到后端返回的数据。
var iframe = document.getElementById('upload1'); iframe.onload = function () { var doc = window.frames['uploader1'].document; var pre = doc.getElementsByTagName('pre'); var obj = JSON.parse(pre[0].innerHTML); }
使用这种方法时需要注意,iframe有跨域限制,创建出来的iframe的地址如果和当前页面地址不同源,会报错。这种情况下,建议大家在iframe的onload函数中,再次向后端请求一个接口获取文件地址,而不是直接去iframe里读取。或者返回这样的数据。
<script type="text/javascript"> window.top.window[callback](data) </script>
callback是和前端约定好的名字,上传完成后触发该函数并返回后端数据。
第二种:使用formData上传。
用js构造form表单的数据,简单高效,但最低只兼容IE10,所以需要兼容IE9的童鞋们就略过这个方法吧。
html:
<input type='file'>
js:
var formData = new FormData(); formData.append("userid", userid); formData.append("signature", signature); formData.append("file", file); //file是blob数据 //再用ajax发送formData到服务器即可,注意一定要是post方式上传
说明:第一种方法提到了创建多个type=‘hidden’的input来发送签名数据,这儿可以用formData.append方法来代替该操作,避免了dom中有多个input的情况出现。最后将file数据也append到formData发送到服务器即可完成上传。
优点:由于这种方式是ajax上传,可以准确知道什么时候上传完成,也可以方便地接收到回调数据。
缺点:兼容性差
第三种:使用fileReader读取文件数据进行上传。
HTML5的新api,兼容性也不是特别好,只兼容到了IE10。
var fr = new FileReader(); fr.readAsDataURL(file); fr.onload = function (event) { var data= event.target.result; //此处获得的data是base64格式的数据 img.src = data; ajax(url,{data} ,function(){}) }
上面获得的data可以用来实现图片上传前的本地预览,也可以用来发送base64数据给后端然后返回该数据块对应的地址。
优点: 同第二种
缺点:一次性发送大量的base64数据会导致浏览器卡顿,服务器端接收这样的数据可能也会出现问题。
9、千分位加逗号
金额添加千分位逗号分隔符
2018-08-04 23:28:07 xiao xu 阅读数 1788更多
分类专栏: js
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_42420703/article/details/81384921
直接进入正题!
- 函数方式:
把金额当做字符串,从末尾开始处理,只处理整数部分,小数部分不管,每三位就加一个逗号
function formatAmount(amount){
let result='';//存储格式化的结果
let j=0;//控制每3位加一个逗号
for(let i=amount.length-1;i>=0;i--){//从末尾开始遍历到第一个
j++;
result=amount[i]+result;
if(amount[i]=='.'){//逗号只加在整数部分
j=0;
}
if(j==3){
//金额的最后一个数字正好满足3位时,其前面不用加逗号,例:500.00
if(i!=0){
result=','+result;
}
j=0;
}
}
return result;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
恩,基本达到要求了吧!但是在开发过程中,使用函数方式代码比较长,还显得比较low,一般都用正则匹配的方式,就一行代码,显得逼格很高!
- 正则匹配方式:
没有学过正则的看到正则表达式真的完全看不懂,学过正则语法的去看一般的正则表达式基本上还是能理解的,但是很多要自己写出来的话还需要努力。
学正则语法的时候觉得还蛮简单的,其实正则要难起来也是无敌的。就目前我的水平还看不懂下面这个正则o(╥﹏╥)o 有需要的朋友自取不谢,以后我再写一些正则方面的博客~
- 只能处理没有小数的金额:
/(?=(?!\b)(\d{3})+$)/g
- 能处理有小数的金额:
/(?<=\d)(?< !.\d*)(?=(\d{3})+(.|$))/g
千分位加”,”,正则一步到位!有小数点的先切割小数点前后,保存小数点后的数值,千分位处理后合并前后
console.log(“49815159888”.replace(/(?=(?!\b)(\d{3})+$)/g,”,”))
输出 —> 49,815,159,888
10、解决跨域问题
什么是跨域?跨域解决方法
本文链接:https://blog.csdn.net/qq_38128179/article/details/84956552
一、为什么会出现跨域问题
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
二、什么是跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
当前页面url | 被请求页面url | 是否跨域 | 原因 |
http://www.test.com/ | http://www.test.com/index.html | 否 | 同源(协议、域名、端口号相同) |
http://www.test.com/ | https://www.test.com/index.html | 跨域 | 协议不同(http/https) |
http://www.test.com/ | http://www.baidu.com/ | 跨域 | 主域名不同(test/baidu) |
http://www.test.com/ | http://blog.test.com/ | 跨域 | 子域名不同(www/blog) |
http://www.test.com:8080/ | http://www.test.com:7001/ | 跨域 | 端口号不同(8080/7001) |
什么是浏览器跨域
例如:
一个域的页面去请求另一个域的资源;
A域的页面去请求B域的资源。
三、非同源限制
【1】无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
【2】无法接触非同源网页的 DOM
【3】无法向非同源地址发送 AJAX 请求
四、跨域解决方法
【1】设置document.domain解决无法读取非同源网页的 Cookie问题
因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)
-
// 两个页面都设置
-
document.domain = 'test.com';
【2】跨文档通信 API:window.postMessage()
调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)
它可用于解决以下方面的问题:
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://test2.com', 'title');
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');
调用message事件,监听对方发送的消息
// 监听 message 消息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);
【3】JSONP
JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。
核心思想:网页通过添加一个<script>元素
,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
①原生实现:
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(res){
// 处理获得的数据
console.log(res.data)
}
</script>
② jQuery ajax:
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
});
③ Vue.js
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
【4】CORS
CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。
1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
2、带cookie跨域请求:前后端都需要进行设置
【前端设置】根据xhr.withCredentials字段判断是否带有cookie
①原生ajax
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
② jQuery ajax
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
③vue-resource
Vue.http.options.credentials = true
④ axios
axios.defaults.withCredentials = true
【服务端设置】
服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
① Java后台
/*
* 导入包:import javax.servlet.http.HttpServletResponse;
* 接口参数中定义:HttpServletResponse response
*/
// 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true");
// 提示OPTIONS预检时,后端需要设置的两个常用自定义头
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");
② Nodejs后台
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request', function(req, res) {
var postData = '';
// 数据块接收中
req.addListener('data', function(chunk) {
postData += chunk;
});
// 数据接收完毕
req.addListener('end', function() {
postData = qs.parse(postData);
// 跨域后台设置
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie
'Access-Control-Allow-Origin': 'http://www.domain1.com', // 允许访问的域(协议+域名+端口)
/*
* 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),
* 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问
*/
'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是让js无法读取cookie
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080...');
③ PHP后台
<?php
header("Access-Control-Allow-Origin:*");
④ Apache需要使用mod_headers模块来激活HTTP头的设置,它默认是激活的。你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下内容即可
Header set Access-Control-Allow-Origin *
解决办法:
1、JSONP:
使用方式就不赘述了,但是要注意JSONP只支持GET请求,不支持POST请求。
2、代理:
例如www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.php,由这个接口在后端去调用www.456.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题。
3、PHP端修改header(XHR2方式)
在php接口脚本中加入以下两句即可:
header('Access-Control-Allow-Origin:*');//允许所有来源访问
header('Access-Control-Allow-Method:POST,GET');//允许访问的方式
11、未完待续。。。
转载:https://blog.csdn.net/weixin_42246997/article/details/101677505