5、数据相加赋值相等克隆、字符串|数组|对象之为空|含某项|项位置|位置项|遍历|相似、字符串|正则|数组|对象之方法、递归(虚拟DOM、快速排序、react框架)、两行布局、两列布局、三列布局、五种盒子居中、em与rem自适应、Flex布局、多图片延迟加载下载、canvas绘图之党徽|五角星|时钟、原生弹窗、可拖拽和缩放弹窗、表格排序、普通拖拽、z拖拽、在线网址、electron(2900行)
一、数据相加赋值相等克隆 来源,https://blog.csdn.net/yyh1994/article/details/129316857 1、小数相加出错 (1)现象,console.log( 0.1+0.2 ); //0.30000000000000004,3和4之间有15个0 (2)原因 A、人用十进制运算 B、计算机把人的十进制转化成自身的二进制,然后进行运算 C、在JS中,遵循IEEE754标准(有3个E),使用双精度浮点数(double)64位(8字节)来存储一个浮点数 (3)十进制转化为二进制--整数 A、十进制数除以2,得到商和余数,余数为二进制数的最低位 B、商除以2,得到商和余数,余数为二进制数的次低位 C、以此类推,直到商为0时为止,0为二进制数的最高位 (4)十进制转化为二进制--小数 A、将十进制小数乘以2,取出结果的整数部分,为小数部分的最高位 B、将得到的小数部分再次乘以2,取出结果的整数部分,为小数部分的次高位 C、直到小数部分为零或者达到所需的精度 (5)将0.875转换为二进制小数,过程如下 A、0.875乘以2得到1.75,取整数部分1,为小数部分的最高位 B、0.75乘以2得到1.5,取整数部分1,为小数部分的次高位 C、0.5乘以2得到1.0,取整数部分1 D、0.875的二进制表示为0.1110 2、i=i+1,编程理解与数学理解 (1)编程理解,赋值,把右边的计算结果赋值给左边的变量 (2)数学理解,移项,合并同类项0=1 3、数据相等的判断方法 // 封装一个判断两个js数据是否相等的方法 //(1)方法1 function isDeepEqualA(aaa, bbb) { if (typeof aaa !== typeof bbb || Array.isArray(aaa) !== Array.isArray(bbb)) { //以下,A、数据类型不同;B、数据类型相同,且1个是数组,1个不是数组(是对象) return false; } else if (Array.isArray(aaa)) { //以下,2个同为数组 for (let i = 0; i < aaa.length; i++) { if (!isDeepEqualA(aaa[i], bbb[i])) { return false; } } } else if (typeof aaa === 'object' && aaa !== null && bbb !== null) { //以下,2个都为对象(都不为null) const aaaKeys = Object.keys(aaa).sort(); const bbbKeys = Object.keys(bbb).sort(); if (JSON.stringify(aaaKeys) !== JSON.stringify(bbbKeys)) { return false; } for (let key of aaaKeys) { if (!isDeepEqualA(aaa[key], bbb[key])) { return false; } } } else { //以下,A、2个同为基本类型;B、2个同为对象,且1个为null,1个(不)为null return aaa === bbb; } return true; } //(2)方法2 function isDeepEqualB(aaa, bbb) { if (Object.prototype.toString.call(aaa) !== Object.prototype.toString.call(bbb)) { //以下,2个不同类型的数据 return false; } else if (Object.prototype.toString.call(aaa) === "[object Array]") { //以下,2个同为数组类型的数据 for (let i = 0; i < aaa.length; i++) { if (!isDeepEqualB(aaa[i], bbb[i])) { return false; } } } else if (Object.prototype.toString.call(aaa) === "[object Object]") { //以下,2个同为对象类型的数据 const aaaKeys = Object.keys(aaa).sort(); const bbbKeys = Object.keys(bbb).sort(); if (JSON.stringify(aaaKeys) !== JSON.stringify(bbbKeys)) { return false; } for (let key of aaaKeys) { if (!isDeepEqualB(aaa[key], bbb[key])) { return false; } } } else { //以下,2个同为基本类型或同为null的数据 return aaa === bbb; } return true; } //(3)数据 if(1 == 1){ console.log( '正在使用A组数据' ); var aaa = [ 0, 1, 2, 3 ]; var bbb = { 0:0, 1:1, 2:2, 3:3 }; }else{ console.log( '正在使用B组数据' ); var aaa = { a: 1, b: 'b', c: false, d: null, }; var bbb = { a: 1, b: 'b', c: false, d: null, e: undefined}; } //(4)比较 console.log('用,isDeepEqualA,比较',isDeepEqualA(aaa, bbb)); //false console.log('用,isDeepEqualB,比较',isDeepEqualB(aaa, bbb)); //false 4、深克隆 //(1)方法1,value为undefined的键值对将消失 function deepCloneA(arrayOrObject) { return JSON.parse(JSON.stringify(arrayOrObject)); } //(2)方法2 function deepCloneB(arrayOrObject) { var target = null; //{ }.toString.call也可以用Object.prototype.toString.call代替 if ({}.toString.call(arrayOrObject) === "[object Array]") target = []; if ({}.toString.call(arrayOrObject) === "[object Object]") target = {}; for (var key in arrayOrObject) { var value = arrayOrObject[key]; if ({}.toString.call(value) === "[object Array]" || {}.toString.call(value) === "[object Object]" ) { target[key] = deepCloneB(value); } else { target[key] = value; } } return target; } //(3)数据 var aaa = { a: 1, b: 'b', c: false, d: null, e: undefined}; var bbb = { a: 1, b: { c: 3 }, d: { e: [1, 2] } }; //(4)克隆 console.log('用,deepCloneA,克隆'); console.log(deepCloneA(aaa)); console.log(deepCloneA(bbb)); console.log('用,deepCloneB,克隆'); console.log(deepCloneB(aaa)); console.log(deepCloneB(bbb)); 二、字符串、数组、对象之为空、含某项、项位置、位置项、遍历、相似 1、字符串 (1)为空的判断方法 A、if(/^\s*$/.test(str))//只有0到多个空格时,为true B、if(!str.trim().length)//trim,修剪 (2)有“某个字符”的判断方法, A、if(str.indexOf(item) != -1) (3)遍历的方法,for,for…in,for…of, var str = 'abc'; for (var i = 0; i < str.length; i++) {//可以没有var console.log( 'for循环', str[i] ); } for(var index in str){//可以没有var console.log( 'for-in循环', index,str[index] ); } for(var item of str){//可以没有var console.log( 'for-of循环', item ); } (4)获取item项的位置,str.indexOf(item) (5)获取index位置的项 A、str.charAt(index) B、str[index] 2、数组 (1)为空的判断方法 A、if(JSON.stringify(ary)=="[]")//==字符串判断法,空数组里有空格,字符串里没有空格,结果也是true B、if(!ary.length)//==长度判断法, (2)有“某个项”的判断方法 A、if(ary.indexOf(item) != -1)//首选方案 B、if(ary.includes(item)) (3)遍历的方法,for,for…in,for…of,另有forEach、map var array = ['a','b']; for (var i = 0; i < array.length; i++) {//可以没有var console.log( 'for循环', array[i] ); } for(var index in array){//可以没有var console.log( 'for-in循环', index,array[index] ); } for(var item of array){//可以没有var console.log( 'for-of循环', item ); } // const person = { // name: 'Alice', // age: 30, // }; // const entries = Object.entries(person); //返回一个数组,其中每个元素都是一个包含对象属性名和属性值的数组 // console.log(entries); // for (const [key, value] of entries) { // console.log( key, value ); // } (4)获取item项的位置,ary.indexOf(item) (5)获取index位置的项,ary[index] 3、对象 (1)空对象的判断方法 A、if(JSON.stringify(obj)=="{}")//==字符串判断法,空对象里有空格,字符串里没有空格,结果也是true B、if(!Object.keys(obj).length)//==长度判断法,只包含可枚举属性 C、if(!Object.getOwnPropertyNames(obj).length)//还包含不可枚举属性 (2)对象里有“某个键值对”的判断方法 A、if(key in obj)//首选方案 B、if(obj.hasOwnProperty(key))//只会检查对象的自有属性 C、注意,if(obj.key)不可以,因为排除了obj={key:0},obj={key:false},obj={key:null},obj={key:undefined} (3)遍历的方法,for…in var object = { a: 1, b: 2 }; for(var key in object){//可以没有var console.log( object[key] ); } (4)获取key属性项的位置 A、对象里面的项是无序的,如果有位置要求,则应该写成数组形式 (5)获取index位置的项 A、对象里面的项是无序的,如果有位置要求,则应该写成数组形式 三、字符串方法:所有方法均不改变原字符串 菜鸟教程,https://www.runoob.com/js/js-strings.html MDN WEB,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String 注意,数组也有的方法,如concat、includes、indexOf、slice 1、charAt:通过索引获取字符,不存在时,返回空字符串。也可以用str[0] 2、charCodeAt:通过索引获取字符的unicode值 3、concat:把多个字符串拼接成一个字符串,相当于加号 4、includes (1)作用:判断字符串中是否有另一字符串 (2)参数:要判断的字符串 (3)返回值:boolean (4)是否改变原字符串:不变 var pets = 'catdogbat'; console.log(pets.includes('cat'));//true 5、indexOf:通过字符获取(该字符首次出现时所在位置的)索引,不存在时,返回-1。 console.log('20000' > '000');//true,前者是否包含后者,且不等于后者,又例location>"https" console.log('000' < '20000');//true,后者是否包含前者,且不等于前者 6、localeCompare,在当前语言环境中,比较两个字符串的前后(先比较第1个字符,相同则比较第2个字符) (1)参数:字符串 (2)返回值:-1,0,1,表示(前者在后者)之前、相等、之后 console.log( 'a'.localeCompare('b') ); (3)示例,字符串排序,借用数组的sort方法 var str = 'SSSadsdcc1CCC荣的Adkdk辱kkkDc观c4dddaaa发货ccCCs6SSSSSs'; str = str.split('').sort(function (one, two) { return one.localeCompare(two)//升序,反之为降序 }).join(''); console.log(str); 7、match,搜索一个字符串-能够-匹配某个模式-的字符,与正则中的exec相似 (1)参数是正则,不加g,匹配一次;返回值为数组,[大正则第1次匹配到的内容,第1、2、3...个小分组匹配到的内容,索引,整个字符串,groups] var reg=/(\d)A(\d)/; var before="000002223A45556A7888"; var after=before.match(reg); console.log('返回数组:',after);// [ '3A4', '3', '4', index: 8, input: '000002223A45556A7888', groups: undefined ] (2)参数是正则,加g,匹配多次;返回值为数组,[大正则第1次匹配到的内容,大正则第2次匹配到的内容,大正则第3次匹配到的内容,...] var reg=/(\d)A(\d)/g; var before="000002223A45556A7888"; var after=before.match(reg); console.log('返回数组:',after);//[ '3A4', '6A7' ] (3)参数是字符串;返回值为数组,和不加g的正则一样 const str = 'hello world'; const result1 = str.match(/world/); const result2 = str.match('world'); console.log(result1); //[ 'world', index: 6, input: 'hello world', groups: undefined ] console.log(result2); //[ 'world', index: 6, input: 'hello world', groups: undefined ] console.log(result2.index); //6 8、matchAll,搜索一个字符串-能够-匹配某个模式-的所有字符 var str = 'test-test2'; var regexp = /test(\d?)/g; var array = [...str.matchAll(regexp)]; console.log(array); 9、slice:复制字符串 (1)没有参数时,返回整个字符串 (2)一个参数时,返回参数到末尾的字符串 (3)两个参数时(m,n),返回从索引m到索引n,不包括n 另,console.log( '7654321'.slice(-3) );//从后往前取3项,构成的新字符串 10、split:把字符串按照指定的分隔符拆分成数组(与数组里join方法相反) console.log("ABCDEFG".split(""));//[ 'A', 'B', 'C', 'D', 'E', 'F', 'G' ] console.log("ABCDEFG".split("D"));//[ 'ABC', 'EFG' ] 11、substr:复制字符串(弃用) (1)没有参数时,返回整个字符串 (2)一个参数时,返回返回参数到末尾的字符串 (3)两个参数时(m,n),返回从索引m开始的n个字符 12、substring:复制字符串 (1)没有参数时,返回整个字符串 (2)一个参数时,返回返回参数到末尾的字符串 (3)两个参数时(m,n),返回索引m到索引n,不包括n 13、trim:去字符串前后空格 var str=" hello world "; console.log('('+str+')'); console.log('('+str.trim()+')'); 14、replaceAll:原字符串不变,返回值为新字符串 var before = "aba-aba-aba-aba-aba-aba-aba"; var after = before.replaceAll('a',"b") console.log( before );//aba-aba-aba-aba-aba-aba-aba console.log( after );//bbb-bbb-bbb-bbb-bbb-bbb-bbb 15、replace:原字符串不变,返回值为新字符串 (1)参数是“旧字符串+新字符串”时,旧字符串被新字符串取代 var before='old--CCC--old'; var after=before.replace("old","new"); console.log('返回字串:',after);//new--CCC--old (2)参数是“正则+新字符串”时, A、不加g,匹配一次 var reg=/(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)/; var before='AAA_12345678_BBB_87654321_CCC'; var after=before.replace(reg,"0000000"); console.log('返回字串:',after);//AAA_0000000_BBB_87654321_CCC B、加g,匹配多次 var reg=/(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)/g; var before='AAA_12345678_BBB_87654321_CCC'; var after=before.replace(reg,"0000000"); console.log('返回字串:',after);//AAA_0000000_BBB_0000000_CCC (3)正则+回调函数作参数时, A、不加g,匹配一次 var reg=/(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)/; var before='AAA_12345678_BBB_87654321_CCC'; var i=0; var after=before.replace(reg,function(totalRegexp,A1,A2,A3,A4,A5,A6,A7,A8,firstIndex,totalString){ i=i+1; console.log('"'+totalRegexp+'"是被大正则第1次匹配到的内容'); console.log('"'+A1+'"是被第1个小正1则匹配上的内容'); console.log('"'+A2+'"是被第2个小正1则匹配上的内容'); console.log('"'+A3+'"是被第3个小正1则匹配上的内容'); console.log('"'+A4+'"是被第4个小正1则匹配上的内容'); console.log('"'+A5+'"是被第5个小正1则匹配上的内容'); console.log('"'+A6+'"是被第6个小正1则匹配上的内容'); console.log('"'+A7+'"是被第7个小正1则匹配上的内容'); console.log('"'+A8+'"是被第8个小正1则匹配上的内容,以此类推'); console.log('"'+firstIndex+'"是本次(大正1则匹配到的)字符串的第1个字符,在整个字符串的索引'); console.log('"'+totalString+'"是整个字符串,本轮匹配结束'); console.log("=========="); return '(我将取代被大正1则第'+i+'次匹配到的内容)' }); console.log('返回字串:',after); // 返回值为基于原字符串的新字符串,用函数第1次返回的内容-代替-原字符串第1次被大正则匹配到的内容; // "12345678"是被大正1则第1次匹配到的内容 // "1"是被第1个小正1则匹配上的内容 // "2"是被第2个小正1则匹配上的内容 // "3"是被第3个小正1则匹配上的内容 // "4"是被第4个小正1则匹配上的内容 // "5"是被第5个小正1则匹配上的内容 // "6"是被第6个小正1则匹配上的内容 // "7"是被第7个小正1则匹配上的内容 // "8"是被第8个小正1则匹配上的内容,以此类推 // "4"是本次(大正1则匹配到的)字符串的第1个字符,在整个字符串的索引 // "AAA_12345678_BBB_87654321_CCC"是整个字符串,本轮匹配结束 // ========== // 返回字串: AAA_(我将取代被大正1则第1次匹配到的内容)_BBB_87654321_CCC B、加g,匹配多次 var reg=/(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)/g; var before='AAA_12345678_BBB_87654321_CCC'; var i=0; var after=before.replace(reg,function(totalRegexp,A1,A2,A3,A4,A5,A6,A7,A8,firstIndex,totalString){ i=i+1; console.log('"'+totalRegexp+'"是被大正则第'+i+'次匹配到的内容'); console.log('"'+A1+'"是被第1个小正1则匹配上的内容'); console.log('"'+A2+'"是被第2个小正1则匹配上的内容'); console.log('"'+A3+'"是被第3个小正1则匹配上的内容'); console.log('"'+A4+'"是被第4个小正1则匹配上的内容'); console.log('"'+A5+'"是被第5个小正1则匹配上的内容'); console.log('"'+A6+'"是被第6个小正1则匹配上的内容'); console.log('"'+A7+'"是被第7个小正1则匹配上的内容'); console.log('"'+A8+'"是被第8个小正1则匹配上的内容,以此类推'); console.log('"'+firstIndex+'"是本次(大正1则匹配到的)字符串的第1个字符,在整个字符串的索引'); console.log('"'+totalString+'"是整个字符串,本轮匹配结束'); console.log("=========="); return '(我将取代第'+i+'次被大正1则匹配到的内容)' }); console.log('返回字串:',after); // 返回值为基于原字符串的新字符串,用函数第1、2、3...次返回的内容-代替-原字符串第1、2、3...次被大正则匹配到的内容; // "12345678"是被大正1则第1次匹配到的内容 // "1"是被第1个小正1则匹配上的内容 // "2"是被第2个小正1则匹配上的内容 // "3"是被第3个小正1则匹配上的内容 // "4"是被第4个小正1则匹配上的内容 // "5"是被第5个小正1则匹配上的内容 // "6"是被第6个小正1则匹配上的内容 // "7"是被第7个小正1则匹配上的内容 // "8"是被第8个小正1则匹配上的内容,以此类推 // "4"是本次(大正1则匹配到的)字符串的第1个字符,在整个字符串的索引 // "AAA_12345678_BBB_87654321_CCC"是整个字符串,本轮匹配结束 // ========== // "87654321"是被大正1则第2次匹配到的内容 // "8"是被第1个小正1则匹配上的内容 // "7"是被第2个小正1则匹配上的内容 // "6"是被第3个小正1则匹配上的内容 // "5"是被第4个小正1则匹配上的内容 // "4"是被第5个小正1则匹配上的内容 // "3"是被第6个小正1则匹配上的内容 // "2"是被第7个小正1则匹配上的内容 // "1"是被第8个小正1则匹配上的内容,以此类推 // "17"是本次(大正1则匹配到的)字符串的第1个字符,在整个字符串的索引 // "AAA_12345678_BBB_87654321_CCC"是整个字符串,本轮匹配结束 // ========== // 返回字串: AAA_(我将取代第1次被大正1则匹配到的内容)_BBB_(我将取代第2次被大正1则匹配到的内容)_CCC C、罕见用法 var reg=/(\d)(\d)(\d)(\d)(\d)(\d)(\d)(\d)/; var before='AAA_12345678_BBB_87654321_CCC'; var after=before.replace(reg,'$1'); //返回值为基于原字符串的新字符串,用第1个小分组的内容-代替-原字符串第1次被大正1则匹配到的内容; console.log('返回字串:',after); // AAA_1_BBB_87654321_CCC 16、字符串里字符重复次数 (1)对象法:把一个字母作为对象的属性名,字母出现的次数作为属性值;进而比较属性值的大小。 var str = 'SSSadsdccCCCAdkdkkkkDccdddaaaccCCsSSSSSs'; function maxstr(str) { var obj = {}; var maxNum = 0; var maxVal = ""; for (var i = 0; i < str.length; i++) { var strNum = str.charAt(i).toLowerCase(); if (obj[strNum]) { obj[strNum]++; } else { obj[strNum] = 1; } } for (var attr in obj) { if (obj[attr] > maxNum) { maxNum = obj[attr]; maxVal = attr; } else if (obj[attr] == maxNum) { maxVal += attr } } return "出现次数最多的字母是:" + maxVal + ";次数是:" + maxNum } var valNum = maxstr(str); console.log(valNum); (2)排序法:先对它们进行排序,再取出小分组和小分组被匹配的次数。 var str = 'SS张SadsdccCCC四Adkdkk张kkDccdddaa三acc四CCsS李SSSSs'; function maxstr(str) { var maxNum = 0; var maxVal = ""; str = str.split('').sort(function (one, two) { return one.localeCompare(two) }).join(''); console.log("排序后的字符串是:" + str); //下面正则的意思是:"(\w)"字符、"\1"第1个括号、"+"1次到多次、"g全局"、"i"不区分大小写 str.replace(/(\w)\1+/gi, function (bigReg,item) { if (bigReg.length > maxNum) { maxNum = bigReg.length; maxVal = item; } else if (bigReg.length == maxNum) { maxVal += item; } }); return "出现次数最多的字母是:" + maxVal + ",次数" + maxNum; } var valNum = maxstr(str); console.log(valNum); 四、正则 附、修饰符 (1)g,使用全局匹配 (2)i,忽略大小写 附、正则实例获取 (1)console.log(/ab+c/i);// /ab+c/i (2)console.log(new RegExp("ab+c", "i"));// /ab+c/i (3)console.log(new RegExp(/ab+c/, "i"));// /ab+c/i 1、test,检测一个字符串-是否-匹配某个模式 var before='程序员:123'; var reg=/\d/; var after=reg.test(before); console.log('返回布尔值:',after); 2、exec,搜索一个字符串-能够-匹配某个模式-的字符,与字符串中的match相似 (1)不加g,匹配一次;返回值为数组,[大正则第1次匹配到的内容,第1、2、3...个小分组匹配到的内容,索引,整个字符串,groups] var reg=/(\d)A(\d)/; var before="000002223A45556A7888"; var after=reg.exec(before); console.log('返回数组:',after); console.log('索引:',after.index); (2)加g,匹配多次;返回值为数组,[大正则第1次匹配到的内容,大正则第2次匹配到的内容,大正则第3次匹配到的内容,...] var reg=/(\d)A(\d)/g; var before="000002223A45556A7888"; var after=reg.exec(before); console.log('返回数组:',after); 3、正则元字符 (1)\w:匹配数字、字母、下划线 (2)\W:匹配非数字、字母、下划线 (3)\n:匹配换行符 (4).:匹配非换行符 (5)\s:匹配空格 (6)\S:匹配非空格 (7)^:匹配输入字符串的开始位置;在方括号中使用时,表示排除方括号中的所有字符 (8)$:匹配输入字符串的结尾位置 (9)*:匹配前面的子表达式0-n次 (10)+:匹配前面的子表达式1-n次 (11)?:匹配前面的子表达式0或1次 (12)\r:匹配回车 (13)正则元字符的使用:MAC var MACMatch=/^[A-Fa-f0-9]{2}(:[A-Fa-f0-9]{2}){5}$|^[A-Fa-f0-9]{2}(-[A-Fa-f0-9]{2}){5}$/, 4、用正则封装解析方法(解析URL中的问号参数值以及HASH值) function queryUrlParam1(url) { var obj = {}; var reg1 = /([^?=&#]+)=([^?=&#]+)/g; var reg2 = /#([^?=&#]+)/; url.replace(reg1, function (keyValue,key,value) { obj[key] = value; }); if (reg2.test(url)) { obj['HASH'] = reg2.exec(url)[1]; } return obj; } function queryUrlParam2(url) { var obj = {}; var askText = ''; var hashText = ''; var askIndex = url.indexOf('?') === -1 ? url.length : url.indexOf('?'); var hashIndex = url.indexOf('#') === -1 ? url.length : url.indexOf('#'); if (askIndex < hashIndex) { askText = url.substring(askIndex + 1, hashIndex); hashText = url.substring(hashIndex + 1); } else { askText = url.substring(askIndex + 1); hashText = url.substring(hashIndex + 1, askIndex); } if (askText) { askText.split('&').forEach(function(item){ let [key, value] = item.split('='); obj[key] = value; }); } if (hashText) obj['HASH'] = hashText; return obj; }; var str = "https://www.baidu.com/newspage/data/landingsuper?AAA=1111&BBB=222&CCC=333#1234" console.log(queryUrlParam1(str)); console.log(queryUrlParam2(str)); var baidu = queryUrlParam1("https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&wd=%E5%9C%B0%E5%9D%80%E6%A0%8F%20js%E4%BA%92%E8%BD%AC&rn=50&oq=%25E5%259C%25B0%25E5%259D%2580%25E6%25A0%258F%25E7%25BC%2596%25E7%25A0%2581%25E4%25B8%258E%25E6%25B1%2589%25E5%25AD%2597%2520js%25E4%25BA%2592%25E8%25BD%25AC&rsv_pq=d283c8db0000cb86&rsv_t=c351Ro%2FA%2FmhiIiW6LtAjCUz3gfW%2FzY%2FIdrQZsY%2BfrFrUBGGwf1OSd4mVEUY&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_btype=t&inputT=2982&rsv_sug3=7&rsv_sug1=7&rsv_sug7=100&bs=%E5%9C%B0%E5%9D%80%E6%A0%8F%E7%BC%96%E7%A0%81%E4%B8%8E%E6%B1%89%E5%AD%97%20js%E4%BA%92%E8%BD%AC") var wd = decodeURIComponent(baidu.wd) var oq = decodeURIComponent(decodeURI(baidu.oq)) var bs = decodeURIComponent(baidu.bs) var rsv_t = decodeURIComponent(baidu.rsv_t) var rsv_pq = baidu.rsv_pq console.log('baidu...',baidu); console.log('wd...',wd); console.log('oq...',oq); console.log('bs...',bs); console.log('rsv_t...',rsv_t); console.log('rsv_pq...',rsv_pq); 5、用正则封装解析方法(HASH值) function hashA(url){ var reg=/#([^#&=?]+)/; if(reg.test(url)){ return reg.exec(url)[1]; } } console.log(hashA("https://www.baidu.com/newspage/data/landingsuper?AAA=1111&BBB=222&CCC=333#1234")); 6、用正则封装解析方法 var ary = ["零","一","二","三","四","五","六","七","八","九"]; var str = "今年是2017年"; var result = str.replace(/\d/g,function (value) { return ary[value] }); console.log( result ); 7、用正则择出汉字 var str = '<img src="haha.png" alt="你的朋友"/>'; var reg=/alt="(.+)"/; console.log(reg.exec(str)[1]); 8、someNumber为数字,当它的小数位数少于number时,则保留原数字,否则四舍五入保留至小数number位 function formatTime(someNumber, number) { var lastNum = null; if (typeof someNumber == "number") { var strNum = someNumber.toString().match(/\.\d*/); if (strNum == null || strNum[0].length <= number + 1) { lastNum = someNumber; } else { lastNum = someNumber.toFixed(number); } } return lastNum; } console.log(formatTime(3.1283456, 2)); console.log(formatTime(3.55, 3)); console.log(formatTime(3, 3)); 五、数组方法 菜鸟教程,https://www.runoob.com/js/js-obj-array.html MDN WEB,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array 注意,数组也有的方法,如concat、includes、indexOf、slice 附、区别 (1)every、some,返回true或false (2)filter、find,返回多项或单项 1、concat (1)作用:把多个数组拼接在一起 (2)参数:要拼接的数组或字符串。 如果是数组,就把数组里的每一项放到原数组的后面; 如果是字符串,把字符串作为一项,放在原数组后面; 浅克隆数组:ary.concat();ary.concat([]); var obj = {b:3} var ary = [1,2,obj] var aaa = ary.concat(); console.log( obj == aaa[2] ); //true (3)返回值:拼接好的数组 (4)是否改变原数组:不变 2、every (1)方法用于检测数组的所有元素是否-都-满足指定条件,返回值为boolean const array1 = [1, 30, 39, 29, 10, 13]; console.log(array1.every((curr) => curr < 40));//true 3、filter (1)作用:找出所有满足条件的项 (2)参数:匿名函数,匿名函数可以有三个参数 (3)返回值:所有满足条件的项组成的数组 const array = [10, 20, 30, 40, 50]; const single = array.filter(function(num){ return num > 30 }); console.log(single, typeof single); //[ 40, 50 ] object (4)是否改变原数组:不变 (5)示例一 var aryOld = [1, 2, 3, 4, 5]; var aryNew=aryOld.filter(function(item){ return item > 3; }); console.log(aryNew); (6)示例二 var todos = [{ score: 10, completed: true }, { score: 2, completed: false }, { score: 30, completed: true }, { score: 40, completed: true }, { score: 5, compelted: false }]; var trueScore = todos.filter(function(item){ return item.completed; }); console.log(trueScore); 4、find (1)作用:找出最先满足条件的那一项 (2)参数:匿名函数,匿名函数可以有三个参数 (3)返回值:最先满足条件的那一项 const array = [10, 20, 30, 40, 50]; const single = array.find(function(num){ return num > 30 }); console.log(single, typeof single); //40 number (4)是否改变原数组:不变 (5)示例一 var ary=[1, 5, 10, 15] ary.find(function(value) { return value > 9; }) // 10 (6)示例二 var studentAll = [ { name: '张三', gender: '男', age: 20 }, { name: '王小毛', gender: '男', age: 20 }, { name: '李四', gender: '男', age: 20 } ]; var studentOne=studentAll.find(function (ele) { return ele.age == 20 }); console.log(studentOne); 5、forEach (1)作用:循环遍历每一项,循环次数为数组项数 (2)参数:匿名函数,匿名函数可以有三个参数,项、项索引、数组 (3)返回值:undefined (4)是否改变原数组:不变 6、includes (1)作用:判断数组中是否有某项 (2)参数:要判断的数组项 (3)返回值:boolean (4)是否改变原数组:不变 var pets = ['cat', 'dog', 'bat']; console.log(pets.includes('cat'));//true 7、indexOf (1)作用:获取数组项第一次在数组中出现的位置索引 (2)参数:要判断的数组项 (3)返回值:数组项的索引,没有该项返回-1 (4)是否改变原数组:不变 8、join(与字符串里split方法相反) (1)作用:把数组的每一项按照指定的分隔符拼接成字符串 (2)参数:指定的分隔符,项与项之间用分隔符连接 (3)返回值:拼接好的字符串 (4)是否改变原数组:不变 (5)实例1:console.log(["ABC", "EFG"].join(""));//ABCEFG (6)实例2:console.log(["ABC", "EFG"].join("D"));//ABCDEFG 9、map (1)作用:循环遍历每一项,循环次数为数组项数 (2)参数:匿名函数,匿名函数可以有三个参数,项、项索引、数组 (3)返回值:返回一个新数组,新数组的每一项是匿名函数每次执行后的返回值 (4)是否改变原数组:不变 10、pop (1)作用:删除项数组末尾项 (2)参数:没有参数 (3)返回值:被删除的项 (4)是否改变原数组:改变 11、push (1)作用:向数组末尾追加一项 (2)参数:要添加的数组项(多项用逗号隔开) (3)返回值:新数组的长度 (4)是否改变原数组:改变 12、reduce (1)累加,将最后一次计算结果暴露出去;可以作为高阶函数,用于函数的compose (2)接受四个参数:初始值(或回调函数上1次的返回值),当前元素值,当前索引,调用 reduce 的数组 (3)示例一 var ary=[1,3,2,4,3,2]; var aryTotal=ary.reduce(function (total,num) { return total+num; }); console.log(aryTotal); (4)示例二 var todos = [{ score: 12, completed: true }, { score: 21, completed: false }, { score: 35, completed: true }, { score: 47, completed: true }, { score: 95, completed: false }]; const totalScore = todos.reduce(function(total, item){ return item.completed ? total + item.score : total },10000); console.log(totalScore); 13、reverse (1)作用:倒序数组 (2)参数:不需要参数 (3)返回值:倒序后的数组 (4)是否改变原数组:改变 示例:console.log(['21', 'a', 'e', 'c'].reverse()); 14、shift (1)作用:删除数组开头项 (2)参数:没有参数 (3)返回值:被删除的项 (4)是否改变原数组:改变 15、slice (1)作用:复制数组项 (2)没有参数:原数组不变,返回整个数组 (3)一个参数:返回从索引位置到末尾 (4)两个参数(n,m):返回索引n到m,不包含m (5)是否改变原数组:不变 另,console.log( [7,6,5,4,3,2,1].slice(-3) );//从后往前取3项,构成的新数组 16、some (1)方法用于检测数组的所有元素是否-有-满足指定条件,返回值为boolean const array1 = [1, 30, 39, 29, 10, 13]; console.log(array1.some((curr) => curr < 10));//true 17、sort (1)作用:按照指定规则排序 (2)参数: A、无 var ary = ['21', 'a', 32, '4', 5, '61', 'e', 'f', 'd', 'b', 'c']; ary.sort(); //升序,先比较每项的第1个字符,相同则比较第2个字符 console.log(ary) B、回调函数-纯数字项数组 var ary = [21, 32, 32, 5, 61, 61, 21, 4, 5, 61]; ary.sort(function (a, b) { return a - b //升序,比较数字的大小 }); console.log(ary) C、回调函数-任意项数组 var ary = [ { id: 2, name: 'b', age: 18 }, { id: 3, name: 'c', age: 20 }, { id: 1, name: 'a', age: 19 } ]; ary.sort(function (a,b) { //return a.id - b.id return a.name.localeCompare(b.name) ; //返回值为-1,0,1,表示(前者在后者)之前、相等、之后 }); console.log(ary) (3)返回值:排好序的数组 (4)是否改变原数组:改变 18、splice (1)作用:参数不同,作用不同,主要用来删除数组项 (2)没有参数:原数组不变,返回空数组 (3)一个参数:从索引位置删除到末尾,返回被删除项构成的数组 (4)两个参数(n,m):从索引n删除m个,返回被删除项构成的数组 (5)三个参数(n,m,X): 从索引n删除m个,被删除项用X填补,返回被删除项构成的数组 (6)是否改变原数组:改变 /* ===以上原数组改变;以下原数组不变=== */ 19、unshift (1)作用:向数组开头添加一项 (2)参数:要添加的数组项(多项用逗号隔开) (3)返回值:新数组的长度 (4)是否改变原数组:改变 20、call和apply (1)call的第2、3、4个参数,分别对应函数的第1、2、3个参数 (2)apply的第2个参数是一个数组,数组的第1、2、3项,分别对应函数的第1、2、3个参数 示例一 function test(a,b) { console.log(this) //默认情况下函数中的this指向的是Window对象 console.log(a,b) //a,b对应的是参数1和参数2 } const obj= { name:'zhangsan' } test.call(obj,'参数1','参数2') test.apply(obj,['参数1','参数2']) //数组的第一、二项,分别对应参数的第一、二个 示例二 var array1 = [1,1,1,1,1]; var array2 = [2,2,2,2,2]; array1.push.call(array2,6,7,8,9);//改变了array2 array2.push.apply(array1,[9,8,7,6]);//改变了array1 console.log(array1) console.log(array2) 21、数组4种去重方法 (1)新数组法:重新构建一个新数组,遍历原数组的每一项,如果该项在新数组的索引为-1,则把该项添加到新数组中。 var ary = [21, 32, 32, 4, 5, 61, 61, 21, 4, 5, 61]; function removeMany(ary){ var newAry=[]; for(var i=0; i<ary.length; i++){ if(newAry.indexOf(ary[i])===-1){ newAry[newAry.length]=ary[i]; } } return newAry } console.log(removeMany(ary)) (2)新对象法:如果对象中没有这一项,给对象添加属性名和属性值,如果对象中已经有了,说明是重复的,直接在数组中删除这一项; var ary = [21, 32, 32, 4, 5, 61, 61, 21, 4, 5, 61]; function removeMany(ary){ var obj={}; for(var i=0; i<ary.length; i++){ var cur=ary[i]; if(obj[cur]===cur){//说明重复了 ary.splice(i,1); i--; }else{ obj[cur]=cur; } } return ary } console.log(removeMany(ary)) (3)sort排序法:先用sort方法对数组进行排序,然后拿前一项与后一项进行比较,如果相等,则删除前一项,同时为了防止数组塌陷,下一次仍从该项开始比较。 var ary = [21, 32, 32, 4, 5, 61, 61, 21, 4, 5, 61]; function removeMany(ary){ ary.sort(function (a, b) { return a - b;//升序 }); for (var i = 0; i < ary.length; i++) { if (ary[i] === ary[i + 1]) { ary.splice(i, 1); i--; } } return ary } console.log(removeMany(ary)) (4)双循环法:第一个循环,依次取出数组的每一项A;第二个循环,从数组的A项开始,依次与A项进行比较,如果相等则删除,同时为了防止数组塌陷,下一次仍从该项开始比较。 var ary = [21, 32, 32, 4, 5, 61, 61, 21, 4, 5, 61]; function removeMany(ary){ for (var i = 0; i < ary.length; i++) { var cur = ary[i]; for (var j = i + 1; j < ary.length; j++) { if (cur === ary[j]) { ary.splice(j, 1); j--; } } } return ary } console.log(removeMany(ary)) 22、数组3种排序方法 (1)冒泡排序(目标:实现升序排列) var ary = [5, 4, 3, 2, 1]; function bubbleSort(ary) { for (var i = 0; i < ary.length - 1; i++) { //正在进行第几次循环 for (var j = 0; j < ary.length - i - 1; j++) { //本次循环需要执行几次 if (ary[j] > ary[j + 1]) { var tmp = ary[j]; ary[j] = ary[j + 1]; ary[j + 1] = tmp; } } console.log(ary); } return ary; } console.log(bubbleSort(ary)) (2)插入排序(目标:实现升序排列) var ary = [50, 40, 30, 20, 10]; function insertSort(ary) { var left = ary.splice(0, 1); for (var i = 0; i < ary.length; i++) { //正在进行第几次循环 var aryAry = ary[i]; for (var j = left.length - 1; j >= 0; ) { //本次循环需要执行几次 var leftAry = left[j]; if (aryAry < leftAry) { j--; if (j === -1) { left.unshift(aryAry); } } else { left.splice(j + 1, 0, aryAry); break; } } } return left; } console.log(insertSort(ary)); (3)快速排序(目标:实现升序排列) var ary = [500, 400, 300, 200, 100]; function quickSort(ary) { if (ary.length <= 1) { return ary; } var num = Math.floor(ary.length / 2); var numValue = ary.splice(num, 1)[0]; var left = []; var right = []; for (var i = 0; i < ary.length; i++) { var cur = ary[i]; if (cur < numValue) { left.push(cur); } else { right.push(cur); } } return quickSort(left).concat([numValue], quickSort(right)); } console.log(quickSort(ary)); 六、对象方法 菜鸟教程,https://www.runoob.com/jsref/dom-obj-object.html MDN WEB,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object 1、Object.assign(target,...sources),用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象 const target = { a: 1, b: 2 }; const source = { b: 3, c: 4 }; const result = Object.assign(target, source); console.log(result); // { a: 1, b: 3, c: 4 } 2、Object.create(proto, [propertiesObject]),创建一个新对象,使用指定的原型对象和可选的属性描述符对象 const personProto = { sayHello() { console.log('Hello!'); }, }; const person = Object.create(personProto); person.sayHello(); // Hello! 3、Object.defineProperty(obj, prop, descriptor),用于定义对象的新属性或修改现有属性,并返回修改后的对象 const obj = {}; Object.defineProperty(obj, 'property1', { value: 42, writable: false, }); console.log(obj.property1); // 42 obj.property1 = 43; // 由于 writable 为 false,赋值操作无效 console.log(obj.property1); // 42 4、Object.entries(obj),返回一个给定对象自身可枚举属性的键值对数组 const obj = { a: 1, b: 2 }; const entries = Object.entries(obj); console.log(entries); // [ [ 'a', 1 ], [ 'b', 2 ] ] 5、Object.freeze(obj),冻结一个对象,使其不可修改、添加或删除属性 const obj = { a: 1 }; Object.freeze(obj); obj.a = 2; // 操作被忽略,因为对象已被冻结 console.log(obj.a); // 1 6、Object.is(obj1, obj2),确定两个值是否是相同的值,与严格相等运算符(===)类似 console.log(Object.is(2, 2)); // true console.log(Object.is(NaN, NaN)); // true console.log(Object.is(0, -0)); // false console.log(Object.is({a:1}, {a:1})); // false 7、Object.keys(obj),返回一个给定对象自身可枚举属性的名称数组 const obj = { a: 1, b: 2 }; const keys = Object.keys(obj); console.log(keys); // [ 'a', 'b' ] 8、Object.values(obj),返回一个给定对象自身可枚举属性值的数组 const obj = { a: 1, b: 2 }; const values = Object.values(obj); console.log(values); // [ 1, 2 ] 七、递归 注意,递归前从外向里执行。递归后从里向外执行。 1、虚拟DOM中的递归 //虚拟DOM,Virtual DOM,堆内存的一个JS对象,包含很多虚拟节点VNode,Virtual Node <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>创建一个虚拟DOM实例</title> <style> .list { color: green; font-size: 30px; } </style> </head> <body> <div> <div>创建一个虚拟DOM实例</div> </div> <script> function Element(obj) { this.tagName = obj.tagName; this.props = obj.props || {}; this.children = obj.children || []; } Element.prototype.render = function () { var el = document.createElement(this.tagName); var props = this.props; for (propName in props) { propValue = props[propName]; el.setAttribute(propName, propValue); } this.children.forEach(function (child) { var elemChild = null; if (child instanceof Element) { elemChild = child.render();//从外向里逐个折回。看最后一次递归执行时,发生了什么。 } else { elemChild = document.createTextNode(child);//最后一次递归执行时,要经过这里。 } el.appendChild(elemChild);//从里向外逐个添加。 }); return el; }; var elem = new Element({ tagName: 'ul', props: { 'class': 'list' }, children: [ new Element({ tagName: 'li', children: [ new Element({ tagName: 'span', children: ['我是span1','我是span1','我是span1--'] }), new Element({ tagName: 'span', children: ['我是span2','我是span2','我是span2'] }) ] }), new Element({ tagName: 'li', children: ['我是span3','我是span3','我是span3',] }) ] }); var elemSelf = elem.render(); document.querySelector('body').appendChild(elemSelf); </script> </body> </html> 2、快速排序中的递归 var ary = [500, 400, 300, 200, 100]; function quickSort(ary) { if (ary.length <= 1) { return ary; } var num = Math.floor(ary.length / 2); var numValue = ary.splice(num, 1)[0]; var left = []; var right = []; for (var i = 0; i < ary.length; i++) { var cur = ary[i]; if (cur < numValue) { left.push(cur); } else { right.push(cur); } } return quickSort(left).concat([numValue], quickSort(right)); } console.log(quickSort(ary)); 3、react框架中的递归 (function (allFn) { if (typeof exports === "object" && typeof module !== "undefined") { module.exports = allFn() } else if (typeof define === "function" && define.amd) { define([], allFn) } else { var tempGlobal; if (typeof window !== "undefined") { tempGlobal = window } else if (typeof global !== "undefined") { tempGlobal = global } else if (typeof self !== "undefined") { tempGlobal = self } else { tempGlobal = this } tempGlobal.React = allFn() } })(function () { var define, module, exports; return (function outerFn(first, second, third) { function recursion(number) { if (!second[number]) { if (!first[number]) { var error = new Error("Cannot find module '" + number + "'"); throw error.code = "MODULE_NOT_FOUND", error } var module = second[number] = { exports: {} }; first[number][0].call(module.exports, function (key) { var value = first[number][1][key]; return recursion(value ? value : key) }, module, module.exports, outerFn, first, second, third) } return second[number].exports//在react实例化的过程中,这行代码不但因获取依赖而多次执行,而且还因获取react实例而最后执行。 } for (var number = 0; number < third.length; number++) recursion(third[number]);//fn(16)第1次执行,执行结果没有变量接收 return recursion //执行到这,整个逻辑就快结束了。前两行可以合并为一行:return recursion(third[0]),同时下面的"(48)"应当删掉。 })( { 2: [function (_dereq_, module, exports) { var thisVar = _dereq_(138) }, { "25": 25, "30": 30 }], }, { }, [16] )(16)// fn(16)第2次执行,因为n[num]为真,所以直接返回n[num].exports并被挂在g.React上 }); 八、两行布局 1、固定高,此增彼减;用flex计算下高 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { margin: 0; padding: 0; } .full { height: 600px; background: red; display: flex;/* 相关代码 */ flex-direction: column;/* 相关代码 */ } .up { background: blue; } .down { background: green; flex: 1;/* 相关代码 */ /*height:100%;*/ } </style> </head> <body> <div class="full"> <div class="up"> <p>ABCD</p> </div> <div class="down"> <p>DCBA</p> </div> </div> </body> </html> 1、正好占满全屏 (1)用calc计算下高、下右宽 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { padding: 0; margin: 0; } html, body { height: 100%; } .up { height: 50px; background: #BBE8F2; width: 100%; } .down { height: calc(100% - 60px);/* 相关代码 */ background: #D9C666; margin-top: 10px; font-size: 0; display: flex;/* 相关代码 */ } .left { width: 200px; height: 100%; overflow: auto; background: palevioletred; margin-right: 10px; font-size: 16px; } .right { width: calc(100% - 210px);/* 相关代码 */ height: 100%; overflow: auto; background: rebeccapurple; font-size: 16px; } </style> </head> <body> <div class="up"></div> <div class="down"> <div class="left"> </div> <div class="right"> </div> </div> </body> </html> (2)用flex计算下高、下右宽 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { padding: 0; margin: 0; } html, body { height: 100%; } .body { display: flex; flex-direction: column; } .up { height: 50px; background: #BBE8F2; width: 100%; } .down { flex: 1; background: #D9C666; font-size: 0; display: flex; } .left { width: 200px; height: 100%; overflow: auto; background: rebeccapurple; font-size: 16px; margin-right: 10px; } .right { flex: 1; overflow: auto; background: rebeccapurple; font-size: 16px; } </style> </head> <body class="body"> <div class="up"></div> <div class="down"> <div class="left"></div> <div class="right"></div> </div> </body> </html> 九、两列布局 附、两个需求 (1)左侧固定宽、右侧占满余屏 (2)左、右自适应高 附、四个实现 (1)table (2)flex (3)内外补+浮动 (4)大高赋给小高 1、table <!DOCTYPE html> <html lang="en"> <head> <title>两列高度自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } </style> </head> <body> <table style="width:100%"> <tr> <td style="width:200px;background: #ddd;"> <br/> </td> <td style="width:calc(100% - 200px);background: #ddd;"> <br/> <br/> <br/> <br/> </td> </tr> </table> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> 2、flex <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } </style> </head> <body> <div style="display:flex"> <div style="width:200px;background: #ddd;margin-right: 10px;"><br/></div> <div style="flex:1;background: #ddd;"><br/><br/><br/><br/><br/></div> </div> </body> </html> 3、内外补+浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>两列高度自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } #main { overflow: hidden; } .both { background: #ddd; padding-bottom: 10000px; margin-bottom: -10000px; } .left { float: left; width: 200px; } .right { margin-left: 210px; } </style> </head> <body> <div id="main"> <div class="left both"><br/></div> <div class="right both"><br/><br/><br/><br/><br/></div> </div> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> 4、大高赋给小高 (1)浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } #left { float: left; width: 200px; background: #ddd; } #right { margin-left: 210px; background: #ddd; } </style> </head> <body> <div> <div id="left"><br/><br/><br/></div> <div id="right"><br/><br/><br/><br/><br/><br/><br/></div> </div> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> <script type="text/javascript"> var left = document.getElementById("left"); var right = document.getElementById("right"); var leftHeight = parseFloat(getComputedStyle(left).height); var rightHeight = parseFloat(getComputedStyle(right).height); var distanceHeight = leftHeight - rightHeight; if (distanceHeight > 0) { right.style.height = leftHeight + "px";//right.style.height =rightHeight +distanceHeight+ "px"; //right.style.height只能赋值,不能获取,所以此处用rightHeight代替right.style.height } else { left.style.height = rightHeight + "px";//left.style.height = leftHeight-distanceHeight + "px"; } </script> (2)定位 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>左右固定宽,中间自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } .left { top: 0; left: 0; position: absolute; width: 200px; background: #ddd; } .right { top: 0; left: 210px; right: 0; position: absolute; background: #ddd; } </style> </head> <body> <div id="left" class="left"><br/><br/><br/><br/><br/><br/></div> <div id="right" class="right"><br/></div> </body> </html> <script type="text/javascript"> var left = document.getElementById("left"); var right = document.getElementById("right"); var leftHeight = parseFloat(getComputedStyle(left).height); var rightHeight = parseFloat(getComputedStyle(right).height); var distanceHeight = leftHeight - rightHeight; if (distanceHeight > 0) { right.style.height = leftHeight + "px";//right.style.height =rightHeight +distanceHeight+ "px"; //right.style.height只能赋值,不能获取,所以此处用rightHeight代替right.style.height } else { left.style.height = rightHeight + "px";//left.style.height = leftHeight-distanceHeight + "px"; } </script> 5、jQuery实现多div等高(与方案4相似) $(function() { var maxHeight = 0; //以下求最高的div的高度 $(".height").each(function() { var thisHeight = $(this).innerHeight(); maxHeight = thisHeight > maxHeight ? thisHeight : maxHeight; }) //以下将最高的div的高度赋值给每一个(需要与最高div等高的)div, $(".height").each(function() { var thisPadding = $(this).innerHeight() - $(this).height(); //在jQuery中,innerheight=padding+内容height $(this).height(maxHeight - thisPadding); }) }) 十、三列布局 附、两个需求 (1)左右两侧固定宽、中间占满余屏 (2)左、中、右自适应高 附、四个实现 (1)table (2)flex (3)内外补+浮动 (4)大高赋给小高 1、table <!DOCTYPE html> <html lang="en"> <head> <title>两列高度自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } </style> </head> <body> <table style="width:100%"> <tr> <td style="width:200px;background: #ddd;"><br/></td> <td style="width:calc(100% - 400px);background: #ddd;"><br/><br/><br/><br/></td> <td style="width:200px;background: #ddd;"><br/></td> </tr> </table> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> 2、flex <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>左右固定宽,中间自适应</title> <style> * { margin: 0; padding: 0; } .flex { display: flex; } .leftAndRight{ width: 200px; background: #ddd; } .middle{ flex: 1; margin:0 10px; background: #ddd; } </style> </head> <body> <div class="flex"> <div class="leftAndRight"><br/></div> <div class="middle"><br/><br/><br/><br/></div> <div class="leftAndRight"><br/></div> </div> </body> </html> 3、内外补+浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>三列高度自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } #main { overflow: hidden; } .three{ background: #ddd; padding-bottom: 10000px; margin-bottom: -10000px; float: left; } .leftAndRight { width: 200px; } .middle { margin-left: 10px; margin-right: 10px; width:calc(100% - 420px) } </style> </head> <body> <div id="main"> <div class="leftAndRight three"><br/></div> <div class="middle three"><br/><br/><br/><br/><br/></div> <div class="leftAndRight three"><br/></div> </div> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> 4、大高赋给小高 (1)浮动 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>三列高度自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } .three{ background: #ddd; float: left; } .leftAndRight { width: 200px; } .middle { margin-left: 10px; margin-right: 10px; width:calc(100% - 420px) } </style> </head> <body> <div> <div class="leftAndRight three" id="left"><br/></div> <div class="middle three" id="middle"><br/><br/><br/><br/><br/></div> <div class="leftAndRight three" id="right"><br/></div> </div> <p>我是尾部,我是尾部,我是尾部,我是尾部,我是尾部,我是尾部!</p> </body> </html> <script type="text/javascript"> var left = document.getElementById("left"); var middle = document.getElementById("middle"); var right = document.getElementById("right"); var leftHeight=parseFloat(getComputedStyle(left).height); var middleHeight=parseFloat(getComputedStyle(middle).height); var rightHeight=parseFloat(getComputedStyle(right).height); var maxHeight=0; if(leftHeight-middleHeight>0){ maxHeight= leftHeight; }else{ maxHeight= middleHeight; } if(rightHeight-maxHeight>0){ maxHeight= rightHeight; } left.style.height =maxHeight+ "px"; middle.style.height =maxHeight+ "px"; right.style.height =maxHeight+ "px"; </script> (2)定位 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>左右固定宽,中间自适应</title> <style type="text/css"> * { margin: 0; padding: 0; } .leftAndRight { top: 0; width: 200px; position: absolute; background: #ddd; } .left { left: 0; } .right { right: 0; } .middle { top: 0; left: 210px; right: 210px; background: #ddd; position: absolute; } </style> </head> <body> <div id="left" class="left leftAndRight"><br/><br/></div> <div id="middle" class="middle"><br/><br/><br/><br/><br/><br/></div> <div id="right" class="right leftAndRight"><br/></div> </body> </html> <script type="text/javascript"> var left = document.getElementById("left"); var middle = document.getElementById("middle"); var right = document.getElementById("right"); var leftHeight=parseFloat(getComputedStyle(left).height); var middleHeight=parseFloat(getComputedStyle(middle).height); var rightHeight=parseFloat(getComputedStyle(right).height); var maxHeight=0; if(leftHeight-middleHeight>0){ maxHeight= leftHeight; }else{ maxHeight= middleHeight; } if(rightHeight-maxHeight>0){ maxHeight= rightHeight; } left.style.height =maxHeight+ "px"; middle.style.height =maxHeight+ "px"; right.style.height =maxHeight+ "px"; console.log(maxHeight) </script> 十一、五种盒子四方居中 1、4种定位四方居中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>4种定位四方居中</title> <style> #mask1_1 { width: 100%; height: 100%; position: fixed; left: 0; top: 0; display: flex; justify-content: center; align-items: center; } #content1_1{ background-color: gray; } #mask2_4 { width: 100%; height: 100%; position: fixed; left: 0; top: 0; } #content2_2{ position: fixed; left: 50%;/* 父级宽度的50% */ top: 50%; transform: translate(-50%, -50%);/* 自身宽度的50% */ background-color: gray; } #content3_3{ position: fixed; top: 0; left: 0; right: 0; bottom: 0; margin: auto; width: 400px; height: 300px; background-color: gray; } #content4_4{ position: fixed; background-color: gray; } </style> </head> <body> <div id="mask1_1"><div id="content1_1">居中一</div></div> <!-- <div id="mask1_1"><div id="content1_1">居中一</div></div> --> <!-- <div id="mask2_4"><div id="content2_2">居中二</div></div> --> <!-- <div id="mask2_4"><div id="content3_3">居中三</div></div> --> <!-- <div id="mask2_4"><div id="content4_4">居中四</div></div> --> </body> </html> <script> var oDiv = document.getElementById('content4_4'); if(oDiv){ var clientWidth = document.documentElement.clientWidth || document.body.clientWidth; var clientHeight = document.documentElement.clientHeight || document.body.clientHeight; oDiv.style.left = (clientWidth - oDiv.clientWidth) / 2 + 'px'; oDiv.style.top = (clientHeight - oDiv.clientHeight) / 2 + 'px'; } </script> 2、1种无定位四方居中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CSS无定位居中</title> <style> .outer{ width: 1000px; height: 500px; background: gray; text-align: center;/* 此处,左右居中 */ } /* 以下,上下居中 */ .middleShow{ width: 200px; height: 100px; display: inline-block; vertical-align: middle; /* 以下,标识区域 */ background: gainsboro; } .middleHide{ width: 0; height: 100%; display: inline-block; vertical-align: middle; } </style> </head> <body> <div class="outer"> <div class="middleShow"></div> <div class="middleHide"></div> </div> </body> </html> 3、三种横向换行也居中 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>3种横向换行也居中</title> <style> .center{ display: flex; flex-wrap: wrap; flex-direction: column; border: 1px solid green; align-items: center;/* 独特之处 */ } .center1{ display: flex; flex-wrap: wrap; flex-direction: row; border: 1px solid green; justify-content: center;/* 独特之处 */ } .center2{ display: flex; flex-wrap: wrap; flex-direction: row; border: 1px solid green; justify-content: space-around;/* 独特之处 */ } .center3{ display: flex; flex-wrap: wrap; flex-direction: row; border: 1px solid green; justify-content: space-between;/* 独特之处 */ } .center > div,.center1 > div,.center2 > div,.center3 > div{ width: 400px; height: 80px; border: 1px solid red; } </style> </head> <body> <div class="center"> <div>竖向换行也居中</div> <div></div> </div> <div class="center1"> <div>横向换行也居中-1,之间无间距</div> <div>justify-content: center</div> </div> <div class="center2"> <div>横向换行也居中-2,之间大间距</div> <div>justify-content: space-around</div> </div> <div class="center3"> <div>横向换行也居中-3,之间超大间距</div> <div>justify-content: space-between</div> </div> </body> </html> 十二、em、rem自适应 1、em示例 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>em示例</title> </head> <body> <div style="font-size: 50px"> <div style="width: 20em;height:4em;background: red;border:1px solid green;border-radius:10px;font-family:'楷体';"> 用em做单位的都是相对于父级字体大小的,本例父级字体的大小是50px,所以这里的宽20em就是1000px,高4em就是200px! </div> </div> </body> </html> 2、rem自适应示例 (1)rem自适应示例之css版(实用程度低) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>rem自适应示例之css版(实用程度低)</title> <style> html { font-size: 20px; } /* :root { font-size: 20px; } */ </style> </head> <body> <div style="font-size: 1.6rem"> <div style="width: 50rem;height:18rem;background: red;border:1px solid green;border-radius:10px;font-family:'楷体';padding-left:20px;"> <p>根字体的大小即1rem,用rem做单位的都是相对于根字体大小的。</p> <p>CSS设置根字体,有2种方法,见style标签</p> </div> </div> </body> </html> (2)rem自适应示例之js版(实用程度高) <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>rem自适应示例之js版(实用程度高)</title> </head> <body> <div style="font-size: 16rem"> <div style="width: 500rem;height:180rem;background: red;border:1px solid green;border-radius:10px;font-family:'楷体';padding-left:20px;"> <p>根字体的大小即1rem,用rem做单位的都是相对于根字体大小的。</p> <p>下面把1rem定义为:(屏幕宽度/设计稿的宽度)+"px"。</p> <p>document.documentElement.style.fontSize=</p> <p>document.documentElement.clientWidth/750+"px";</p> </div> </div> </body> </html> <script> var designWidth = 1000 ; document.documentElement.style.fontSize = document.documentElement.clientWidth/designWidth+"px"; </script> 十三、Flex布局 1、flex是2009年,W3C提出了一种布局方案,子元素的float、clear和vertical-align属性失效 (1)一个固定,另一个占据剩余宽或高 .box{ width: 100%;//height: 100% display: flex; flex-direction: row;//flex-direction: column; } .box>.div1{ width:100px;//height: 100px; } .box>.div2{ flex:1; } height: calc(100vh - 200px) (2)横向按钮组居中居右 .div{ display: flex; justify-content: center; //flex-end } .div button{ margin-left: 20px; } (3)行内元素也可以使用 Flex 布局。 .box{ display: inline-flex; } 2、flex作为属性,区别于上面作为属性值 来源,https://blog.csdn.net/Shivy_/article/details/122361132 来源,https://www.runoob.com/w3cnote/flex-grammar.html .item { flex: flex-grow flex-shrink flex-basis flex: 1 1 //可放大,可缩小 flex: 0 0 //不放大,不缩小 } (1)flex-grow,项目的放大比例,默认为0,即使存在剩余空间,也不放大;设为1,子盒子占满父盒子的剩余空间 (2)flex-shrink,属性定义了项目的缩小比例,设为0,即使空间不足,也不缩小;默认为1,如果空间不足,该项目将缩小 (3)flex-basis,属性定义了在分配多余空间之前,项目占据的主轴空间,默认值为auto,即项目的本来大小 3、flex-direction:主轴的方向 .box { flex-direction: row | row-reverse | column | column-reverse; } (1)row(默认值):主轴为水平方向,起点在左端 (2)row-reverse:主轴为水平方向,起点在右端 (3)column:主轴为垂直方向,起点在上沿 (4)column-reverse:主轴为垂直方向,起点在下沿 4、flex-wrap:主轴的换行 .box{ flex-wrap: nowrap | wrap | wrap-reverse; } (1)nowrap(默认):不换行 (2)wrap:换行,第一行在上方 (3)wrap-reverse:换行,第一行在下方 5、justify-content:主轴的对齐 .box { justify-content: flex-start | flex-end | center | space-around | space-between; } 具体对齐方式与轴的方向有关 (1)flex-start(默认值):主轴起点对齐 (2)flex-end:主轴终点对齐 (3)center: 主轴居中对齐,之间0间距 (4)space-around:主轴居中对齐,之间小间距,项目与外边框的间隔,是项目之间间隔的一半 (5)space-between:主轴两端对齐,之间大间距,项目与外边框的间隔,是0 6、align-items:交叉轴对齐 .box { align-items: flex-start | flex-end | center | baseline | stretch; } 具体的对齐方式与交叉轴的方向有关 (1)flex-start:交叉轴的起点对齐 (2)flex-end:交叉轴的终点对齐 (3)center:交叉轴的中点对齐 (4)baseline: 项目的第一行文字的基线对齐 (5)stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度 7、flex-flow:flex-direction和flex-wrap的简写,默认值为row nowrap .box { flex-flow: <flex-direction> || <flex-wrap>; } 8、align-content属性 align-content属性定义了多根轴线的对齐方式如果项目只有一根轴线,该属性不起作用 .box { align-content: flex-start | flex-end | center | space-between | space-around | stretch; } (1)flex-start:与交叉轴的起点对齐 (2)flex-end:与交叉轴的终点对齐 (3)center:与交叉轴的中点对齐 (4)space-between:与交叉轴两端对齐,轴线之间的间隔平均分布 (5)space-around:每根轴线两侧的间隔都相等所以,轴线之间的间隔比轴线与边框的间隔大一倍 (6)stretch(默认值):轴线占满整个交叉轴 十四、多图片延迟加载下载 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0; } img { border: none; } div { margin: 0 auto; width: 800px; height: 400px; background: url("http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518060703_mthumb.jpg") no-repeat center #e1e1e1; } div img { width: 100%; height: 100%; } p { width: 800px; height: 600px; line-height: 60px; background: lightgrey; font-size: 30px; margin: 0 auto; text-indent: 13px; } </style> </head> <body> <p> <span>多图片延迟加载:</span><br/> <span>(1)多图片延迟加载;</span><br/> <span>(2)多图片延迟加载;</span><br/> <span>(3)多图片延迟加载。</span> </p> </body> <script> var data = [ { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, { src: "http://img.pconline.com.cn/images/upload/upc/tx/photoblog/1509/06/c5/12227263_12227263_1441518066203_mthumb.jpg", }, ]; var aDiv = document.getElementsByTagName("div"); var aImg = document.getElementsByTagName("img"); function bind() { var frg = document.createDocumentFragment(); for (var i = 0; i < data.length; i++) { var div = document.createElement("div"); div.innerhtml = "<img realImg='" + data[i].src + "' alt=''/>"; frg.appendChild(div); } document.body.appendChild(frg); frg = null; } bind(); window.onscroll = function () { var scrollBottom = document.documentElement.scrollTop + document.documentElement.clientHeight; for (var i = 0; i < aDiv.length; i++) { var thisImg = aImg[i]; var thisDiv = aDiv[i]; var imgPosition = thisDiv.offsetTop + thisDiv.offsetHeight; if (imgPosition - 200 < scrollBottom) { if (thisImg.isLoad) continue; thisImg.src = thisImg.getAttribute("realImg"); thisImg.isLoad = true; } } }; /* 当相关服务关闭时,登录页仍然可见,相关图片地址的配置如下 $timeout(function () { var thisImg = new Image(); thisImg.src = $scope.r_g_company.logoPage.logo.src; thisImg.onerror= function() { $scope.r_g_company.logoPage.logo.src = $scope.r_g_company.logoPage.logo.srcCY } },1000); $.get('/app_v3/oem/info?' +new Date().getTime()).then(function (res) { $scope.r_g_company.logoPage.logo.src = '/audit-html/static/img/cy_oem/logo.png'; }).catch(function(){ $scope.r_g_company.logoPage.logo.src = '/audit-html/static/img/cy_oem/logo.png'; $scope.r_g_company.logoPage.logo.srcCY = '/audit-html/static/img/cy_tech/logo.png'; }); */ </script> </html> 十五、canvas绘图 1、党徽 <!doctype html> <html> <head> <meta charset="UTF-8"> <title>党~徽</title> </head> <body> <canvas id="canvas" width="450" height="450"> 您的浏览器不支持canvas标签,无法看到党~徽 </canvas> </body> </html> <script> var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); context.beginPath(); context.arc(215, 215, 200, 0, 360); context.fillStyle = "#030d48"; context.strokeStyle = "grey"; context.lineWidth = "10"; context.stroke(); context.fill(); context.closePath(); context.beginPath(); for (var i = 0; i < 12; i++) { context.lineTo(Math.cos((i * 30) / 180 * Math.PI) * 200 + 215, Math.sin((i * 30) / 180 * Math.PI) * 200 + 215); context.lineTo(Math.cos((i * 30 + 15) / 180 * Math.PI) * 105 + 215, Math.sin((i * 30 + 15) / 180 * Math.PI) * 105 + 215); } context.fillStyle = "#ffffff"; context.fill(); context.closePath(); context.beginPath(); context.arc(215, 215, 105, 0, 360); context.strokeStyle = "#030d48"; context.lineWidth = "10"; context.stroke(); context.closePath(); </script> 2、五角星 <!doctype html> <html> <head> <meta charset="UTF-8"> <title>五~角~星</title> </head> <body> <canvas id="canvas" width="450" height="450"> 您的浏览器不支持canvas标签,无法看到五~角~星 </canvas> </body> </html> <script> var canvas = document.getElementById("canvas"); var context1 = canvas.getContext("2d"); context1.beginPath(); context1.rotate(18*Math.PI/180); for (i = 0; i < 5; i++) { context1.lineTo(Math.cos((i * 72+36) / 180 * Math.PI) * 200 + 250, Math.sin((i * 72+36) / 180 * Math.PI) * 200 + 150); context1.lineTo(Math.cos((i * 72+72) / 180 * Math.PI) * 75 + 250, Math.sin((i * 72+72) / 180 * Math.PI) * 75 + 150); } context1.fillStyle = "#ff0000"; context1.fill(); context1.closePath(); </script> 3、时钟 这是用HTML5的canvas制作的一个钟表,包含表盘、时针、分针、秒针及它们的运动;另外还添加了自动读时间的功能。 <!doctype html> <html> <head> <style> #clock{ display:block; background:url("") no-repeat; margin: 0 auto; } </style> </head> <body> <canvas id="clock" width="500" height="500" > 您的浏览器不支持canvas标签,无法看到时钟 </canvas> </body> </html> <script> var clock=document.getElementById('clock'); var context=clock.getContext('2d'); function drawClock() { context.clearRect(0, 0, 500, 500); function tow(n) { return n >= 0 && n < 10 ? '0' + n : '' + n; } var now = new Date(); var second = now.getSeconds(); var minute = now.getMinutes(); var hour = now.getHours(); var date = now.getDate(); var month = now.getMonth()+1; var year = now.getFullYear(); hour = hour + minute / 60; var hour1=hour; hour = hour > 12 ? hour - 12 : hour; //制作时钟外圈 context.lineWidth = 10; context.beginPath(); context.arc(250, 270, 200, 0, 360, false); context.stroke(); context.closePath(); //小时刻度制作 for (i = 0; i < 12; i++) { context.save(); context.lineWidth = 9; context.strokeStyle = "red"; context.translate(250, 270); context.rotate(i * 30 * Math.PI / 180); context.beginPath(); context.moveTo(0, -170); context.lineTo(0, -190); context.stroke(); context.closePath(); context.restore(); } //分钟刻度制作 for ( i = 0; i < 60; i++) { context.save(); context.lineWidth = 5; context.strokeStyle = "blue"; context.translate(250, 270); context.rotate(i * 6 * Math.PI / 180); context.beginPath(); context.moveTo(0, -180); context.lineTo(0, -190); context.stroke(); context.closePath(); context.restore(); } //钟面上表示小时的数字 for (var i = 1; i < 13; i++) { context.save(); var deg = i * Math.PI / 6; context.translate(250, 270); var x = Math.sin(deg); var y = -Math.cos(deg); context.fillStyle = "block"; context.font = "25px 宋体"; context.textAlign = "center"; context.textBaseline = "middle"; context.lineWidth=1; context.strokeStyle="white"; context.beginPath(); context.strokeText(i, x * 155, y * 155); context.closePath(); context.restore(); } //时针制作 context.save(); context.lineWidth=7; context.strokeStyle="#000"; context.translate(250,270); context.rotate(hour*30*Math.PI/180); context.beginPath(); context.moveTo(0,-110); context.lineTo(0,10); context.stroke(); context.closePath(); context.restore(); //分针制作 context.save(); context.lineWidth=5; context.strokeStyle="#000"; context.translate(250,270); context.rotate(minute*6*Math.PI/180); context.beginPath(); context.moveTo(0,-135); context.lineTo(0,15); context.stroke(); context.closePath(); context.restore(); //秒针制作 context.save();//保存当前环境; //以下是秒针的主体 context.strokeStyle="red"; context.lineWidth=3; context.translate(250,270); context.rotate(second*6*Math.PI/180);//秒针旋转的速度 context.beginPath(); context.moveTo(0,-170); context.lineTo(0,20); context.stroke(); context.closePath(); //以上是秒针的主体,以下是时针、分针、秒针的交叉点 context.beginPath(); context.arc(0,0,5,0,360,false); context.closePath(); context.fillStyle="gray"; context.fill(); context.stroke(); //以上是时针、分针、秒针的交叉点,以下是秒针的顶端装饰。 context.beginPath(); context.arc(0,-150,5,0,360,false); context.closePath(); context.fillStyle="gray"; context.fill(); context.stroke(); context.restore();//返回已保存过的环境。 //以下是文字报时; context.save(); context.font="23px 楷体"; context.lineWidth=1; context.strokeStyle="white"; context.strokeText("现在是北京时间:"+tow(year)+"年"+tow(month)+"月"+tow(date)+"日 " +tow(Math.floor(hour1))+"时"+tow(minute)+"分"+tow(second)+"秒",5,30); context.restore(); } drawClock(); setInterval(drawClock,1000); </script> 十六、原生弹窗、可拖拽和缩放弹窗 1、原生弹窗 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body style="font-size: 30px;"> <pre> alert: 1、弹窗有确定按钮,阻塞线程, 2、alert后面的代码,点击确认后才执行 confirm: 1、弹窗有两个按钮(确定和取消),阻塞线程, 2、confirm后面的代码,点击按钮后才执行, 3、点击确定返回true,点击取消返回false prompt: 1、弹窗有一个输入框、两个按钮(确定和取消),阻塞线程 2、prompt后面的代码,点击按钮后才执行, 3、点击确定返回输入内容,为空返回空字符串,点击取消返回null </pre> <input type="button" onclick="fnAlert()" value="显示alert框" /> <input type="button" onclick="fnConfirm()" value="显示confirm框" /> <input type="button" onclick="fnPrompt()" value="显示prompt框" /> </body> </html> <script> function fnAlert(){ var text = alert("你好,我是一个alert框!"); console.log( text ); } function fnConfirm(){ var text = confirm("你好,我是一个confirm框!"); console.log( text ); } function fnPrompt(){ var text = prompt("你好,我是一个prompt框!","这是默认输入!"); console.log( text ); } </script> 2、可拖拽和缩放弹窗 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>可拖拽、缩放弹窗</title> <style> * { padding: 0; margin: 0; } html,body { height: 100%; } .mask { position: fixed; width: 100%; height: 100%; background: #bbb; } #alert { position: absolute; background: #ddd; margin: auto; width: 600px; height: 800px; left: 50%; top: 50%; transform: translate(-50%, -50%); user-select: none; resize: both; overflow: auto; } .innerBox { padding: 0 30px; } p { line-height: 40px; } .title { height: 50px; line-height: 50px; background: gray; padding-left: 30px; cursor: pointer; } .submit{ text-align: center; background: gray; display: block; margin: 0 auto; width:100px; height:30px; line-height: 30px; } </style> </head> <body> <div class="mask"> <div id="alert"> <p id="alert-title-id" class="title"> 本弹窗特征(鼠标置于此处,方可拖动): </p> <div class="innerBox"> <p> 1、标题区可拖拽 </p> <p> 2、内容区可以是任意高度、宽度 </p> <p> 3、初始位置居中,由下面css决定 </p> <div style="padding-left:30px;"> <p> left: 50%; </p> <p> top: 50%;</p> <p> transform: translate(-50%, -50%);</p> </div> <p> 4、弹窗可缩放,由下面css决定 </p> <div style="padding-left:30px;"> <p> resize: both; </p> <p> overflow: auto;</p> </div> <p> 5、提交按钮和文字居中,由下面css决定 </p> <div style="padding-left:30px;"> <p> text-align:center; width:100px; background:gray;</p> <p> display:block; height:30px; line-height:30px; margin:0 auto;</p> </div> <p> 6、你使用时,在关闭弹窗之前,用上面3处css代码重置弹窗的位置,否则,下次使用弹窗时,弹窗将出现在上次关闭时的地方。 </p> <p> 7、弹窗向任何方向(上下左右)拖拽,当消失3/4时,停止移动。 </p> <p> 8、拖拽弹窗的右下方,可以实现缩放。 </p> </div> <div style="padding-top:30px;"> <span class="submit">提交</span> </div> </div> </div> </body> </html> <script> var oDiv = document.getElementById("alert"); oDiv.onmousedown = down; function processThis(fn, currentThis) { return function (event) { fn.call(currentThis, event); //”先触发,后执行“与”先执行,后触发“ }; } function down(event) { event = event || window.event; if (event.target.id != "alert-title-id") return; this.initOffsetLeft = this.offsetLeft; this.initOffsetTop = this.offsetTop; this.initClientX = event.clientX; this.initClientY = event.clientY; this.maxOffsetWidth = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth; this.maxOffsetHeight = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight; if (this.setCapture) { this.setCapture(); this.onmousemove = processThis(move, this); this.onmouseup = processThis(up, this); } else { document.onmousemove = processThis(move, this); document.onmouseup = processThis(up, this); } } function move(event) { var currentLeft = this.initOffsetLeft + (event.clientX - this.initClientX); var currentTop = this.initOffsetTop + (event.clientY - this.initClientY); //以下都是边界值的判断;弹窗向任何方向(上下左右)拖拽,当消失3/4时,停止移动。 if (currentLeft > this.maxOffsetWidth + this.clientWidth / 0.8) { currentLeft = this.maxOffsetWidth + this.clientWidth / 0.8; } else if (currentLeft < -this.clientWidth / 4) { currentLeft = -this.clientWidth / 4; } if (currentTop > this.maxOffsetHeight + this.clientHeight / 0.8) { currentTop = this.maxOffsetHeight + this.clientHeight / 0.8; } else if (currentTop < 300) { //-this.clientHeight / 4 currentTop = 300; //-this.clientHeight / 4 } //以上都是边界值的判断;弹窗向任何方向(上下左右)拖拽,当消失3/4时,停止移动。 //以下都是边界值的判断;弹窗向任何方向(上下左右)拖拽,当消失1/2时,停止移动。 /* if (currentLeft > this.maxOffsetWidth + this.clientWidth) { currentLeft = this.maxOffsetWidth + this.clientWidth; } else if (currentLeft < -this.clientWidth / 64) { currentLeft = -this.clientWidth / 64; } if (currentTop > this.maxOffsetHeight + this.clientHeight) { currentTop = this.maxOffsetHeight + this.clientHeight; } else if (currentTop < -this.clientHeight / 64) { currentTop = -this.clientHeight / 64; } */ //以上都是边界值的判断;弹窗向任何方向(上下左右)拖拽,当消失1/2时,停止移动。 //以下都是边界值的判断;弹窗向任何方向(上下左右)拖拽,触边时,停止移动。 /* if (currentLeft > this.maxOffsetWidth + this.clientWidth / 2) { currentLeft = this.maxOffsetWidth + this.clientWidth / 2; } else if (currentLeft < this.clientWidth / 2) { currentLeft = this.clientWidth / 2; } if (currentTop > this.maxOffsetHeight + this.clientHeight / 2) { currentTop = this.maxOffsetHeight + this.clientHeight / 2; } else if (currentTop < this.clientHeight / 2) { currentTop = this.clientHeight / 2; } */ //以上都是边界值的判断;弹窗向任何方向(上下左右)拖拽,触边时,停止移动。 this.style.left = currentLeft + "px"; this.style.top = currentTop + "px"; console.log(this.style.left); console.log(this.style.top); } function up() { if (this.releaseCapture) { this.releaseCapture(); this.onmousemove = null; this.onmouseup = null; } else { document.onmousemove = null; document.onmouseup = null; } } </script> 十七、表格排序 说明,这里的表格排序,包含按姓名、年龄、分数、性别等汉字和数字的排序。用纯原生JavaScript代码实现,同时还实现了隔行变色。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> #table { width: 600px; border: 3px solid darkgreen; margin: 20px auto; text-align: center; } #table tr { height: 40px; line-height: 40px; } .bg0 { background: mediumvioletred; } .bg1 { background: greenyellow; } .bg2 { background: yellow; } .cursor { cursor: pointer } </style> </head> <body> <table id="table" class="table"> <thead> <tr class="bg2"> <th class="cursor">姓名</th> <th class="cursor">年龄</th> <th class="cursor">分数</th> <th class="cursor">性别</th> </tr> </thead> <tbody> </tbody> </table> </body> </html> <script> var table = document.getElementById("table"); var th = table.tHead.rows[0].cells; var body = table.tBodies[0]; var row = body.rows; console.log(row); console.log('上面,展开前是空数组,这是代码执行到此的结果'); console.log('上面,展开后有6项数据,这是页面渲染完毕后的结果'); var data = [ { name: "赵老大", age: 45, score: 60, sex: 0 }, { name: "钱老二", age: 24, score: 67, sex: 1 }, { name: "孙老三", age: 38, score: 79, sex: 1 }, { name: "李老四", age: 30, score: 80, sex: 0 }, { name: "周老五", age: 65, score: 56, sex: 1 }, { name: "吴老六", age: 26, score: 26, sex: 0 }, ]; //绑定原始数据 bind(); function bind() { var frg = document.createDocumentFragment(); for (var i = 0; i < data.length; i++) { var cur = data[i]; var tr = document.createElement("tr"); for (var attr in cur) { if (attr === "sex") { cur[attr] = cur[attr] === 0 ? "男" : "女"; } var td = document.createElement("td"); td.innerHTML = cur[attr]; tr.appendChild(td); } frg.appendChild(tr); } body.appendChild(frg); //2、 frg = null; } //实现隔行变色 changeColor(); function changeColor() { for (var i = 0; i < row.length; i++) { row[i].className = "bg" + (i % 2); } } //绑定点击事件 for (var i = 0; i < th.length; i++) { if (th[i].className === "cursor") { th[i].flag = -1; th[i].index = i; th[i].onclick = function () { sortArray.call(this, this.index); }; } } //类数组转化为数组 function makeArray(arg) { var ary = []; try { ary = Array.prototype.slice.call(arg); } catch (e) { for (var i = 0; i < arg.length; i++) { ary.push(arg[i]); } } return ary; } //点击事件中的排序 function sortArray(n) { var that = this; for (var i = 0; i < th.length; i++) { th[i].flag = i === n ? (that.flag *= -1) : -1; } var ary = makeArray(row); ary.sort(function (rowBefore, rowBehind) { var rowInnerBefore = rowBefore.cells[n].innerHTML; var rowInnerBehind = rowBehind.cells[n].innerHTML; return rowInnerBefore.localeCompare(rowInnerBehind); }); var frg = null; for (i = 0; i < ary.length; i++) { frg = ary[i]; body.appendChild(frg); } changeColor(); } </script> 十八、普通拖拽 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>拖拽</title> <style> *{ margin:0; padding:0; } div{ position: absolute; left:0; top:0; width: 100px; height: 100px; background: red; } </style> </head> <body> <div id="div"></div> </body> </html> <script> var oDiv = document.getElementById("div"); oDiv.onmousedown = down; function processThis(fn, obj) { return function (e) { fn.call(obj, e); }; } function down(event) { event = event || window.event; this.offsetLeftPass = this.offsetLeft; this.offsetTopPass = this.offsetTop; this.eventClientX = event.clientX; this.eventClientY = event.clientY; if (this.setCapture) { this.setCapture(); this.onmousemove = processThis(move, this); this.onmouseup = processThis(up, this); } else { document.onmousemove = processThis(move, this); document.onmouseup = processThis(up, this); } } function move(event) { event = event || window.event; this.style.left = this.offsetLeftPass + (event.clientX - this.eventClientX) + "px"; //this.offsetLeftPass:移动前offsetLeft值;(event.clientX-this.eventClientX):鼠标横向移动的距离,即盒子横向移动的距离 this.style.top = this.offsetTopPass + (event.clientY - this.eventClientY) + "px"; //this.offsetTopPass:移动前offsetTop值;(event.clientX-this.eventClientX):鼠标纵向移动的距离,即盒子纵向移动的距离 } function up() { if (this.releaseCapture) { this.releaseCapture(); this.onmousemove = null; this.onmouseup = null; } else { document.onmousemove = null; document.onmouseup = null; } } </script> 十九、zTree树拖拽 <!DOCTYPE html> <html> <head> <title>zTree-可拖拽的树</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <link rel="stylesheet" href="https://cdn.bootcss.com/zTree.v3/3.5.33/css/zTreeStyle/zTreeStyle.min.css"> <script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdn.bootcss.com/zTree.v3/3.5.33/js/jquery.ztree.core.min.js"></script> <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/zTree.v3/3.5.29/js/jquery.ztree.excheck.js"></script> <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/zTree.v3/3.5.29/js/jquery.ztree.exedit.js"></script> <script type="text/javascript"> var setting = { edit: { enable: true, showRemoveBtn: false, showRenameBtn: false }, data: { simpleData: { enable: true } }, callback: { beforeDrag: beforeDrag, beforeDrop: beforeDrop } }; var zNodes =[ { id:1, pId:0, name:"随意拖拽 1", open:true}, { id:11, pId:1, name:"随意拖拽 1-1"}, { id:12, pId:1, name:"随意拖拽 1-2", open:true}, { id:121, pId:12, name:"随意拖拽 1-2-1"}, { id:122, pId:12, name:"随意拖拽 1-2-2"}, { id:123, pId:12, name:"随意拖拽 1-2-3"}, { id:13, pId:1, name:"禁止拖拽 1-3", open:true, drag:false}, { id:131, pId:13, name:"禁止拖拽 1-3-1", drag:false}, { id:132, pId:13, name:"禁止拖拽 1-3-2", drag:false}, { id:133, pId:13, name:"随意拖拽 1-3-3"}, { id:2, pId:0, name:"随意拖拽 2", open:true}, { id:21, pId:2, name:"随意拖拽 2-1"}, { id:22, pId:2, name:"禁止拖拽到我身上 2-2", open:true, drop:false}, { id:221, pId:22, name:"随意拖拽 2-2-1"}, { id:222, pId:22, name:"随意拖拽 2-2-2"}, { id:223, pId:22, name:"随意拖拽 2-2-3"}, { id:23, pId:2, name:"随意拖拽 2-3"} ]; function beforeDrag(treeId, treeNodes) { for (var i=0,l=treeNodes.length; i<l; i++) { if (treeNodes[i].drag === false) { return false; } } return true; } function beforeDrop(treeId, treeNodes, targetNode, moveType) { return targetNode ? targetNode.drop !== false : true; } function setCheck() { var zTree = $.fn.zTree.getZTreeObj("treeDemo"), isCopy = $("#copy").attr("checked"), isMove = $("#move").attr("checked"), prev = $("#prev").attr("checked"), inner = $("#inner").attr("checked"), next = $("#next").attr("checked"); zTree.setting.edit.drag.isCopy = isCopy; zTree.setting.edit.drag.isMove = isMove; showCode(1, ['setting.edit.drag.isCopy = ' + isCopy, 'setting.edit.drag.isMove = ' + isMove]); zTree.setting.edit.drag.prev = prev; zTree.setting.edit.drag.inner = inner; zTree.setting.edit.drag.next = next; showCode(2, ['setting.edit.drag.prev = ' + prev, 'setting.edit.drag.inner = ' + inner, 'setting.edit.drag.next = ' + next]); } function showCode(id, str) { var code = $("#code" + id); code.empty(); for (var i=0, l=str.length; i<l; i++) { code.append("<li>"+str[i]+"</li>"); } } $(document).ready(function(){ $.fn.zTree.init($("#treeDemo"), setting, zNodes); setCheck(); $("#copy").bind("change", setCheck); $("#move").bind("change", setCheck); $("#prev").bind("change", setCheck); $("#inner").bind("change", setCheck); $("#next").bind("change", setCheck); }); </script> </head> <body> <p>参考文档1,https://treejs.cn/v3/main.php#_zTreeInfo</p> <p>参考文档2,https://www.bootcdn.cn/zTree.v3/3.5.29</p> <div class="content_wrap"> <div class="zTreeDemoBackground left"> <ul id="treeDemo" class="ztree"></ul> </div> <div class="right"> <ul class="info"> <li class="title"><h2>1、setting 配置信息说明</h2> <ul class="list"> <li>此 Demo 仅从功能上演示实现拖拽的基本方法和配置参数</li> <li class="highlight_red">1)、使用 拖拽功能,必须设置 setting.edit 中的各个属性,详细请参见 API 文档中的相关内容</li> <li class="highlight_red">2)、使用 拖拽功能的事件回调函数,必须设置 setting.callback.beforeDrag / onDrag / beforeDrop / onDrop 等属性,详细请参见 API 文档中的相关内容</li> <li><p>基本拖拽设置:<br/> <input type="checkbox" id="copy" class="checkbox first" checked /><span>允许复制</span> <input type="checkbox" id="move" class="checkbox " checked /><span>允许移动</span><br/> <ul id="code1" class="log" style="height:42px;"></ul></p> </li> <li><p>拖拽相对位置设置:<br/> <input type="checkbox" id="prev" class="checkbox first" checked /><span>prev</span> <input type="checkbox" id="inner" class="checkbox " checked /><span>inner</span> <input type="checkbox" id="next" class="checkbox " checked /><span>next</span><br/> <ul id="code2" class="log" style="height:65px;"></ul></p> </li> </ul> </li> <li class="title"><h2>2、treeNode 节点数据说明</h2> <ul class="list"> <li>对 节点数据 没有特殊要求,用户可以根据自己的需求添加自定义属性</li> </ul> </li> </ul> </div> </div> </body> </html> 二十、在线网址 1、在线图片转svg,https://www.bejson.com/convert/image_to_svg/ 2、在线图片转base64,https://www.bejson.com/ui/image2base64/ 3、在线编程工具,https://www.toolhelper.cn/ 4、在线编程工具,https://www.wetools.com/ 5、在线ts运行,https://www.json.cn/run/typescript/ 6、链接转成二维码(草料),https://cli.im/url/ 7、bootcdn,https://www.bootcdn.cn/ 二十一、electron 1、electron是什么? (1)用Web技术构建跨平台的桌面应用,electron = Chromium + Node.js + Native API。2016 年 5 月 Electron 发布了 v1.0.0 版本 (2)Chromium,为 Electron 提供了强大的UI能力,可以不考虑兼容性的情况下,利用强大的Web生态来开发界面 (3)Node.js,让 Electron 有了底层的操作能力,比如文件的读写,甚至是集成C++等等操作,并可以使用大量开源的 npm 包来完成开发需求 (4)Native API,Native API 让 Electron 有了跨平台和桌面端的原生能力,比如说它有统一的原生界面,窗口、托盘这些。 2、什么时候使用Electron? (1)公司没有专门的桌面应用开发者,而需要前端兼顾来进行开发时,用Electron就是一个不错的选择。 (2)一个应用需要同时开发Web端和桌面端的时候,那使用Electron来进行开发就对了。 (3)开发一些效率工具,比如API类的工具。