前端面试题---小米(总结知识点)

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 elementdiv p选择 <div> 元素内部的所有 <p> 元素。1
element>element(父子选择器)div>p选择父元素为 <div> 元素的所有 <p> 元素。2
element+elementdiv+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
:linka:link选择所有未被访问的链接。1
:visiteda:visited选择所有已被访问的链接。1
:activea:active选择活动链接。1
:hovera:hover选择鼠标指针位于其上的链接。1
:focusinput:focus选择获得焦点的 input 元素。2
:first-letterp:first-letter选择每个 <p> 元素的首字母。1
:first-linep:first-line选择每个 <p> 元素的首行。1
:first-childp:first-child选择属于父元素的第一个子元素的每个 <p> 元素。2
:beforep:before在每个 <p> 元素的内容之前插入内容。2
:afterp:after在每个 <p> 元素的内容之后插入内容。2
:lang(language)p:lang(it)选择带有以 "it" 开头的 lang 属性值的每个 <p> 元素。2
element1~element2p~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-typep:first-of-type选择属于其父元素的首个 <p> 元素的每个 <p> 元素。3
:last-of-typep:last-of-type选择属于其父元素的最后 <p> 元素的每个 <p> 元素。3
:only-of-typep:only-of-type选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。3
:only-childp: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-childp:last-child选择属于其父元素最后一个子元素每个 <p> 元素。3
:root:root选择文档的根元素。3
:emptyp:empty选择没有子元素的每个 <p> 元素(包括文本节点)。3
:target#news:target选择当前活动的 #news 元素。3
:enabledinput:enabled选择每个启用的 <input> 元素。3
:disabledinput:disabled选择每个禁用的 <input> 元素3
:checkedinput: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操作符可以用~操作来判断某个字符串里是否有某个字符。

  1. var str = '123456'

  2. if(~str.indexOf(0)){ // ~str.indexOf(0) != 0     包含

  3.   console.log('取反之后不为零,说明indexOf的结果不等于-1,所以表示str字符串里包含了对应字符')

  4. } else {             // ~str.indexOf(0) == 0     不包含

  5.   console.log('说明取反之后为零,说明indexOf的结果等于-1,所以表示str字符串里不包含了对应字符')

js中 ~(按位非)运算符妙用

2018-12-20 10:14:12 SSSkyCong 阅读数 136更多

分类专栏: 转载 学习-总结-转载 H5

转载: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...都大于0

     

    ps: 这种写法可不仅仅的B格高这么简单,位运算相对于比较运算符效率高,对于一次运算本身来说,可能相差无几,但在循环次数过大,比如超过了10000000次,效率就会有差距。


    2、~~value的使用 

    对于浮点数,~~value可以代替parseInt(value),而且前者效率更高些


    parseInt(-2.99) //-2 
    ~~(-2.99) //-2 

    ps: 这些技巧可能会给阅读代码的同学造成困扰,如果不知道原理的话,甚至让人费解。因此平时写代码的时候,要根据情况决定采用哪种写法。

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. 分析设计稿,找到那些现成的框
  3. 找出那些样式重复的元素(或框)——如1级标题、2级标题、段落等
  4. 写HTML代码,把内容盛放进框中
  5. 写CSS代码,定义元素(或框)的样式(从大的样式特征——如框的宽度,到小的——如字体字重)
  6. 保存代码,在浏览器中打开,检查和设计稿的差距,调整代码
  7. 重复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

直接进入正题!

  1. 函数方式:
    把金额当做字符串,从末尾开始处理,只处理整数部分,小数部分不管,每三位就加一个逗号
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,一般都用正则匹配的方式,就一行代码,显得逼格很高!

  1. 正则匹配方式:
    没有学过正则的看到正则表达式真的完全看不懂,学过正则语法的去看一般的正则表达式基本上还是能理解的,但是很多要自己写出来的话还需要努力。
    学正则语法的时候觉得还蛮简单的,其实正则要难起来也是无敌的。就目前我的水平还看不懂下面这个正则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(此方案仅限主域相同,子域不同的跨域应用场景。)

  1. // 两个页面都设置

  2. document.domain = 'test.com';

【2】跨文档通信 API:window.postMessage()

调用postMessage方法实现父窗口http://test1.com向子窗口http://test2.com发消息(子窗口同样可以通过该方法发送消息给父窗口)

它可用于解决以下方面的问题:

  • 页面和其打开的新窗口的数据传递
  • 多窗口之间消息传递
  • 页面与嵌套的iframe消息传递
  • 上面三个场景的跨域数据传递
  1. // 父窗口打开一个子窗口

  2. var openWindow = window.open('http://test2.com', 'title');

  3. // 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)

  4. openWindow.postMessage('Nice to meet you!', 'http://test2.com');

调用message事件,监听对方发送的消息

  1. // 监听 message 消息

  2. window.addEventListener('message', function (e) {

  3. console.log(e.source); // e.source 发送消息的窗口

  4. console.log(e.origin); // e.origin 消息发向的网址

  5. console.log(e.data); // e.data 发送的消息

  6. },false);

【3】JSONP

JSONP 是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,兼容性好(兼容低版本IE),缺点是只支持get请求,不支持post请求。

核心思想:网页通过添加一个<script>元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。

①原生实现:

  1. <script src="http://test.com/data.php?callback=dosomething"></script>

  2. // 向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字

  3. // 处理服务器返回回调函数的数据

  4. <script type="text/javascript">

  5. function dosomething(res){

  6. // 处理获得的数据

  7. console.log(res.data)

  8. }

  9. </script>

② jQuery ajax:

  1. $.ajax({

  2. url: 'http://www.test.com:8080/login',

  3. type: 'get',

  4. dataType: 'jsonp', // 请求方式为jsonp

  5. jsonpCallback: "handleCallback", // 自定义回调函数名

  6. data: {}

  7. });

③ Vue.js

  1. this.$http.jsonp('http://www.domain2.com:8080/login', {

  2. params: {},

  3. jsonp: 'handleCallback'

  4. }).then((res) => {

  5. console.log(res);

  6. })

【4】CORS

CORS 是跨域资源分享(Cross-Origin Resource Sharing)的缩写。它是 W3C 标准,属于跨源 AJAX 请求的根本解决方法。

1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin

2、带cookie跨域请求:前后端都需要进行设置

【前端设置】根据xhr.withCredentials字段判断是否带有cookie

①原生ajax

  1. var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

  2. // 前端设置是否带cookie

  3. xhr.withCredentials = true;

  4. xhr.open('post', 'http://www.domain2.com:8080/login', true);

  5. xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

  6. xhr.send('user=admin');

  7. xhr.onreadystatechange = function() {

  8. if (xhr.readyState == 4 && xhr.status == 200) {

  9. alert(xhr.responseText);

  10. }

  11. };

② jQuery ajax 

$.ajax({

  1. url: 'http://www.test.com:8080/login',

  2. type: 'get',

  3. data: {},

  4. xhrFields: {

  5. withCredentials: true // 前端设置是否带cookie

  6. },

  7. crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie

  8. });

③vue-resource

Vue.http.options.credentials = true

④ axios 

axios.defaults.withCredentials = true

【服务端设置】

服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。

① Java后台

  1. /*

  2. * 导入包:import javax.servlet.http.HttpServletResponse;

  3. * 接口参数中定义:HttpServletResponse response

  4. */

  5. // 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/'

  6. response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");

  7. // 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示

  8. response.setHeader("Access-Control-Allow-Credentials", "true");

  9. // 提示OPTIONS预检时,后端需要设置的两个常用自定义头

  10. response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

② Nodejs后台

  1. var http = require('http');

  2. var server = http.createServer();

  3. var qs = require('querystring');

  4. server.on('request', function(req, res) {

  5. var postData = '';

  6. // 数据块接收中

  7. req.addListener('data', function(chunk) {

  8. postData += chunk;

  9. });

  10. // 数据接收完毕

  11. req.addListener('end', function() {

  12. postData = qs.parse(postData);

  13. // 跨域后台设置

  14. res.writeHead(200, {

  15. 'Access-Control-Allow-Credentials': 'true', // 后端允许发送Cookie

  16. 'Access-Control-Allow-Origin': 'http://www.domain1.com', // 允许访问的域(协议+域名+端口)

  17. /*

  18. * 此处设置的cookie还是domain2的而非domain1,因为后端也不能跨域写cookie(nginx反向代理可以实现),

  19. * 但只要domain2中写入一次cookie认证,后面的跨域接口都能从domain2中获取cookie,从而实现所有的接口都能跨域访问

  20. */

  21. 'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly' // HttpOnly的作用是让js无法读取cookie

  22. });

  23. res.write(JSON.stringify(postData));

  24. res.end();

  25. });

  26. });

  27. server.listen('8080');

  28. console.log('Server is running at port 8080...');

③ PHP后台

  1. <?php

  2. 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、未完待续。。。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值