2018-07-21
## 经典bug:1.模板引擎的渲染## 难点:### 0.vue总结#### 指令:```jsVue.directive('指令名称',{ //自定义指令的生命周期函数 bind(){}, //参数1el 参数2binding inserted(){}, update(){},})//当bind和update函数内部的业务逻辑一模一样的时候,可以简写Vue.directive('指令名称', (el,binding)=>{})```#### 组件:```js//全局指令Vue.directive('mycolor',{ inserted(el,binding){ el.style.color = binding.value }})//全局过滤器Vue.filter('fmtName', function (v, arg) { // v 就是需要过滤的原始数据 也就是管道符|左边的内容 var data = arg + v // 返回处理好的数据 return data})//组件Vue.component('组件',{ data(){ return{ time: new Date(), color: 'red' } }, template: `
{{time | fmtTime}}
`, //局部过滤器 filters: { fmtTime(time){ console.log(time); var y = time.getFullYear(); var m = time.getMonth() + 1; var d = time.getDate(); return y + '/' + m + '/' + d } },})Vue.component('two', { data() { return { time: new Date(), color: 'red' } }, template: `
{{time}}
`, //局部指令 directives: { myfocus: { inserted(el, binding) { console.log(el); console.log(binding); el.focus() } } } })var vm = new Vue({ el:'#app', data: { }, //定义当前vue实例用到的任何函数 methods: { }, //生命周期函数 created:{ },// mounted(){ }, updated(){ }, //计算属性 computed:{ }, watch:{ handler(){ }, deep: true },})```组件是用来封装重复的视图一:定义组件(1) 1.创建组件的模板对象```jsvar login=Vue.extend({ // template 是用来写视图代码的地方 template: '
登录
'})``` 2.使用Vue.component()注册组件```jsVue.component('login',login)```二:定义组价(2)```jsVue.component('register',{template: '
注册
',})```三:定义组件(3)定义组件的第三种方法: template里面的结构使用选择器选择页面中的元素注意: template使用的选择器选择的模板元素必须写在Vue托管区域外,模板便签`````jsVue.component('account',{template: '#account',})```注意:1.template里面的选择器的模板元素必须写在Vue托管区域外2.模板标签叫做(也有别的写法,不推荐)3.组件模板必须有一个唯一的根元素4.组件内部的data属性必须在当前组件的模板中进行使用5.所有组件的模板都是定义在托管区域外的,都是平级的,不存在嵌套6.组件名称,组件的属性名称,组件的事件名称如果使用了驼峰命名法,都必须使用纯小写,并用连接符-链接#### 路由:前端路由: 通过浏览器的特性(window.location.hash)实现无刷新的页面跳转路由传参中的this.$route(分别表示routes数组里的对应的路由对象,每次打印的都不一样,是用来获取参数的) this.$router(每次打印的都一样,指的是用new VueRouter创建出来的路由对象,主要用于页面间的跳转)#### 组件生命周期:```js 数据初始化(created) 初始化阶段 页面初始化(mounted) 运行阶段 updated 销毁阶段 destoryed 生命周期函数,只需要搞清楚生命周期函数的执行时期和执行的特点,在实际开发中到低可以写什么代码 beforeCreate 执行时机: 当vue实例一被初始化时,vue对象呗创建时触发. 特点: 此时vue实例上什么都没有! 没用 created 执行时机: 当vue实例被创建完成时,所有属性和方法都已经挂在完毕是执行. 特点: 此时vue实例data中的属性和methods中的方法(filteds,directive)都已经绑定到实例上了 实际运用: 1.数据的初始化. 2.发送网络请求 beforeMount 执行时机: vue的dom已经渲染到页面了,但是使用的各种指令还没被正确解析,如果获取真实dom,获取的还会带有各种指令 特点: dom还还带着各种指令 实际运用: 没用 mounted 执行时机: vue的dom已经渲染到页面了, 同时各种指令已经正确解析了 特点: 真实dom已经完全渲染完毕 实际运用: 只要涉及到获取真实dom,就会用 beforeUpdate 执行时机: 当data中数据发送改变的时候 特点: data中的数据已经发送了变化,但是页面还没有重新渲染过来 实际运用: 很少用到 updated 执行时机: 当data中数据发送改变的时候 特点: data中的数据已经发送了变化,页面重新渲染完成 实际运用: 设计到数据变化时会用到 beforeDestory 执行时机: 当vue实例被销毁时,执行 特点: 虽然已经接收到销毁的信息,但是data和methods还可以继续使用 实际运用: 清除不在使用的变量, 比如: 清除定时器的操作 destoryed 执行时机: 当vue实例被销毁时,执行 特点: 凉了 实际运用: 不用```-------------------------### 1.JSON.parse() 和JSON.stringftyJSON.parse() `[{},{}]`JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串 `"[{},{}]"`-------------### 2.ES5 中引入的部分数组方法1> forEach2> map3> filter4> some5> every6> indexOf7> lastIndexOf---------------------------------### 3.函数的四种调用模式:1. 函数模式 - 函数的定义方式 - 表达式 - 声明式 - Function - 单独独立调用的就是函数 - this表达全局对象 - 任何自调用都是函数模式2. 方法模式 - 区分 方法本身就是函数,但是方法不是单独独立的调用,而是通过一个对象调用 - this表示引导方法的对象3. 构造器函数 constructor - 区分 使用 new 关键字引导 - 执行步骤 var p = new Person(); new 是一个运算符, 专门用来申请创建对象,创建出来的队象传递给构造函数的 this利用构造函数对其初始化 function Person () { this.name = 'jim', this.age = 19. this.gender = 'male' } - 返回值 如果不写return语句, 那么构造函数默认返回 this 如果在构造函数中写上 return 语句, 并紧跟基本类型(return num , return 1223), 则忽略this - 如果调用构造函数的时候, 构造函数没有参数, 圆括号是可以省略的4. 上下文调用 就是 环境调用模式 => 在不同环境下的不同调用模式 简单说就是统一一种格式, 可以实现 函数模式与方法模式 - 语法(区分) - call 形式 函数名.call() - apply 形式 函数名.apply() - 用法 call() 和 apply() 的区别和作用? apply()函数有两个参数:第一个参数是上下文,第二个参数是参数组成的数组。如果上下文是null,则使用全局对象代替。 如:function.apply(this,[1,2,3]); call()的第一个参数是上下文,后续是实例传入的参数序列。 如:function.call(this,1,2,3); // bind call apply - 都可以改变this指向 - 只能函数使用 ``` function fn (a, b) { console.log('儿童节快乐!', a + b) console.log(this) } // console.dir(fn) var arr = [45, 56] var obj = {name: 666} // 1. call 是一个方法call(this指向, 传递参数) call借用函数同时改变this之后帮其调用 /* fn.call(arr, 66, 100) // 2. apply等同与call 区别就是传递参数 fn.apply(arr, [66, 100]) */ // 3. bind 但是它不会帮我们调用 var ff = fn.bind(obj, 46545, 56161465) // console.log(ff) ff() ``` ``` // 4. this的使用 var btn = document.querySelector('.btn') btn.onclick = function() { console.log('中国桃之乡襄阳') console.log(this) // 4.1 使用that var that = this /* setTimeout(function() { // console.log(that) // 我想让这句话打印button怎么办 }, 1000) */ // 4.2 使用bind改变this指向 /* setTimeout(function() { // console.log(that) // 我想让这句话打印button怎么办 console.log(this) }.bind(this), 1000) */ // 4.3 使用箭头函数 优点 就是没有this指向 setTimeout(() =>{ // console.log(that) // 我想让这句话打印button怎么办 console.log(this) }, 1000) // 箭头函数 是es6中的新语法 // var fn = function (a, b) {} ==》var fn = (a, b) => {} } ```------------------------------------### 4.事件队列:定时函数事件函数ajax回调函数前段开发中, 三种情况有事件队列1. 主线程已经空闲2. 任务满足触发条件 - 定时函数(延时时间已经到达) - 事件函数(特定事件被触发) - ajax的回调函数(服务器端有数据响应)常见的面试题```jsconsole.log(1);setTimeout(function(){ console.log(2);},10);console.log(3);//结果为1,3,2//先执行主线程中的代码,打印1,3再执行事件队列中的函数,打印2```-----------------------------------------### 5.数组,对象操作(基础api)数组的方法```1.push(); 方法:在数组的最后面添加内容,返回值是添加后数组的长度2.pop() 方法:把数组的最后一个删除,返回值是删除的那一项3.unshift() 方法:在数组的最前面添加内容,返回值是添加后数组的长度4.shift() 方法:删除数组中的第一项,返回值是删除的那一项5.concat() 方法:拼接数组6.join() 方法:把数组中的每一项用特定的字符串连接起来7.slice(a,b) 方法: 从索引a开始截取(包括a),一直截取到b(不包括b),如果里面只有一个参数,,那么就直接截取到末尾,不会改变原来的数组 > var arr = [1,2,3,4,5]; > var a = arr.slice(-8,3); =>等同于:arr.slice(0,3) //如果第一个参数是负数,就用数组的长度跟这个负数相加,如果相加后的数字小于等于0,就表示从索引0开始截取,如果大于0,就表示从相加之后的那个数字索引开始截取 > console.log(a); //[1,2,3] 从索引0开始截取 > var b = slice(-4,3); =>等同于:arr.slice(1,3) > console.log(b); //[2,3] 从索引1开始截取 >var c = arr.slice(1,-2); =>等同于:arr.slice(1,3) //如果第二个参数是负数的话,就用数组的长度跟第二个参数相加,表示截取到相加之后的那个数字索引 >console.log(c); //[2,3] var d = arr.slice(-4,-2); =>等同于:arr.slice(1,3) 如果两个参数都是负数的话,就结合上面两种情况 >console.log(d); //[2,3]8.splice(a,b,c); 方法:从索引a开始截取b个元素,并用c替换截取的元素,并改变原来的数组,如果只有一个参数,表示从这个索引开始截取到末尾splice(a,b) 方法里面如果第一个参数为负数的话,使用方法跟slice() 方法一样,如果第二个参数为负数的话,表示截取的是一个空数组9.sort(function (a,b){return a-b}); 数组排序方法10.reverse(); 方法:数组翻转方法11.forEach(function (ele,index){console.log(ele,index)}); 方法:遍历数组,传入一个回调函数,里面有三个参数,第一个是元素值,第二个是索引,第三个是数组12.every(function (ele){return ele > 20}); 传入一个回调函数,返回值是boolean类型值 例子:var arr = [1,2,3,4,5]; var a = arr.every(function (ele){ return ele > 3}); console.log(a); //false 数组里只要有一个数字小于3就返回false13.map(function (ele){return ele + 10}); 或 map(Math.sprt); 让数组中的每一个元素按照函数的方法去执行,返回一个新的数组14.filter(functoon (ele){return ele < 50}); 起到过滤作用, 让数组中的每一个元素按照函数的方法去执行,把符合条件的元素放到一个新的数组中返回15.eval(arr.join('+')); 如果数组中的每一项都是数字的话,用这个方法可以求数组中的数字之和 例子:var arr = [1,2,3,4,5]; var a = eval(arr.join('+')); console.log(a); //15```字符串的方法```字符串最大的特点就是不可变1.charAt();方法: 找到索引对应的字符串2.charCodeAt();方法 :返回索引对应的字符串的ASCII码3.string.fromCharCode();方法 :获取ASCII码对应的字符串4.concat();方法:拼接字符串5.slice(a,b);方法: 从索引a开始截取(包括a),一直截取到索引b(不包括b),如果里面只有一个参数,就直接截取到末尾slice(a,b); 如果里面的参数是负数的话,使用方法跟数组中的slice()方法一样6.substring(a,b)方法:从索引a开始截取(包括a),一直截取到索引b(不包括b),如果里面只有一个 参数那么就直接截取到末尾substring(a,b); 如果第一个参数为负数的话,会自动转化为0,从索引0开始截取substring(a,b); 如果第二个参数为负数的话,会自动转化为0,并且会把第一个参数和第二个参数的位置互换例子:var str = 'hello world';var a = str.substring(3,-7); => 等同于 str.substring(0,3);console.log(a); //hel substring(a,b); 如果两个参数都是负数的话,截取到的是空字符串7.substr(a,c); 方法: 从索引a开始截取c个元素 substr(a,b); 如果第一个参数为负数的话,跟数组中slice()使用方法一样 substr(a,b); 如果第二个参数为负数,或者两个参数都是负数的话,截取到的是空字符串8.indexOf();方法:从前往后查找字符串对应的索引9.lastIndexOf();方法:从后往前查找字符串对应的索引10.replace();方法 :替换字符串> var str = "Welcome to Microsoft!";> str.replace(/Microsoft/, 'wahaha')11.trim();方法:把字符串两边的空格去掉用正则表达式可以把字符串中所有的空格都去掉例子:var reg = /\s+/;var str = ' hello world ';var a = str.replace(reg,'');console.log(a); //helloworld12.toLowerCase();方法:转小写13.toUpperCase(); 方法:转大写14.toLocaleCompare();方法:比较15.search();方法:返回字符串对应的索引16.match();方法:返回找到的字符串,没有就返回null17.split();方法:用指定的字符串隔开,并以数组的方式返回```--------------------------------### 6.js的三大特性:1. 继承 解决代码冗余2. 封装 将抽象出来的属性和对属性的操作封装在一起,属性被保护在内部,程序的其他部分只能用特定的操作来对属性进行操作.3. 多态 指一个引用(类型)在不同情况下的多种状态。js天生拥有多态-------------------------------------------------------------------------------------### 7.形参和实参:调用的是实参, 声明的是实参```success: fucntion(res) // 形参obj.success(res) //实参```-------------------------------------------------------------------------------------### 8.跨域怎么解决 --- (jsonp和cors) 原理:其本质是利用了 script: src 天然的可跨域的特性, 由服务器端返回一个预先定义好的JavaScript函数的调用, 并且将服务器数据已改函数的形式传递过来,需要后端配合. ---只能以get传递**常见解决ajax****跨域的方式:jsonp****,cors****等**。我们着重学习jsonp.**1.**静态script标签的src属性进行跨域请求(了解)缺点:不支持动态的传递参数**2.**动态创建script标签,通过标签的src属性发送请求(重点掌握)```jsvar script = document.createElement('script');script.src = 'http://xxx.com/data.php?flag='+flag;var head = document.getElementByTagName('head')[0];head.appendChild(script);```优点:可以动态的传递参数。缺点:动态创建script标签发出去的请求是异步请求。**jsonp****的本质**:(1) 主要是利用了script标签的天然的跨域特性来发送请求(2) 它的实现方式: 在发送请求的时候传递一个函数名到后台, 后台的返回数据的时候回返回这个函数的调用形式,并且在()中拼接参数(3) ajax和jsonp的本质不同, ajax的核心是通过XMLHttpRequest来发送请求, 而jsonp是通过script标签来实现请求的发送CORS在后台加一个允许跨域的头-------------------------------------------------------------------------------------### 9.cookie session 和 localstoragesessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。web storage和cookie的区别Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。```var keyArr = [];keyArr.push(keyword);// 将关键字数组存储在本地localStorage.setItem('keyArr', JSON.stringify(keyArr));```cookie和session的区别数据持久化存储在服务器,为session技术。```为了实现业务逻辑的连续性,将部分信息持久化存储在服务器端,可以保证数据的安全性及各个脚本之间的共享。SESSION数据是基于COOKIE的。当浏览器不同时,COOKIE数据不同,对应的SESSION文件也不同,无法读取到SESSION数据。从HTTP协议,为什么SESSION是基于COOKIE的?浏览器请求a.php时:PHP脚本中,基于不同浏览器、使用特定的算法,生成浏览器对应的唯一身份信息。并判断该浏览器对应的SESSION文件是否存在。不存在则创建以session开头,后缀以与浏览器对应的字符串身份信息。响应时,PHP脚本会将当前SESSION会话的会话名称(文件名一部分),以COOKIE数据的形式返回给浏览器(在setcookie协议项中,COOKIE数据名为PHPSESSID)。浏览器再次请求本网站的任意页面时,自动携带名为PHPSESSID的COOKIE数据,PHP按照会话名称,查找对应session文件,将数据读取到$_SESSION数组中。```数据持久化存储在浏览器,为cookie技术。```什么是cookie?当你在浏览网站的时候,WEB 服务器会先送一小小资料放在你的计算机上,Cookie 会帮你在网站上所打的文字或是一些选择,都纪录下来。当下次你再光临同一个网站,WEB 服务器会先看看有没有它上次留下的 Cookie 资料,有的话,就会依据 Cookie里的内容来判断使用者,送出特定的网页内容给你。允许服务器脚本(PHP脚本)在浏览器端存储数据,并以此跟踪及识别用户的技术。数据设置后,浏览器再次请求服务器指定页面时,将相关的数据(身份信息)发送给服务器脚本,供脚本使用。 cookie本质为简单数据(string 类型),基本操作逻辑为增删改查设置cookiesetcookie(名,值,有效期,有效路径, 有效的域名);```## [1. session]()与COOKIE之间的区别与联系### [1) 区别]()l **从存储位置**: COOKIE存储在浏览器,SESSION存储的服务器端。l **数据安全****性:** session存储在服务器端,不易获取,更加安全。(COOKIE存储安全性要求不高的信息)l **通过HTTP协议传输的数据量:**每次请求,COOKIE传输量较大。传递该网站相关的全部的COOKIE数据。l **支持的数据类型:**COOKIE支持字符串,SESSION几乎所有的数据类型。 ### [2) 联系]()l 都是用来解决HTTP协议的无状态、无记忆的不足之处,以实现业务的连续性,如登录及购物车模块的实现。l 二者都是会话技术的范畴 。l SESSION需要依赖COOKIE(浏览器的身份信息,存储浏览器对应会话的名称)进行数据的传递。禁用COOKIE后,session无法正常使用)。 ------------------------------------### 10.Promise这么一看就明白了,Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。这么说用Promise new出来的对象肯定就有then、catch方法喽,没错。那就new一个玩玩吧。```var p = new Promise(function(resolve, reject){ //做一些异步操作 setTimeout(function(){ console.log('执行完成'); resolve('随便什么数据'); }, 2000);});```Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来讲,resolve是将Promise的状态置为fullfiled,reject是将Promise的状态置为rejected。不过在我们开始阶段可以先这么理解,后面再细究概念。在上面的代码中,我们执行了一个异步操作,也就是setTimeout,2秒后,输出“执行完成”,并且调用resolve方法。这时候你应该有两个疑问:1.包装这么一个函数有毛线用?2.resolve('随便什么数据');这是干毛的?我们继续来讲。在我们包装好的函数最后,会return出Promise对象,也就是说,执行这个函数我们得到了一个Promise对象。还记得Promise对象上有then、catch方法吧?这就是强大之处了,看下面的代码:```runAsync().then(function(data){ console.log(data); //后面可以用传过来的数据做些其他操作 //......});```在runAsync()的返回上直接调用then方法,then接收一个参数,是函数,并且会拿到我们在runAsync中调用resolve时传的的参数。运行这段代码,会在2秒后输出“执行完成”,紧接着输出“随便什么数据”。这时候你应该有所领悟了,原来then里面的函数就跟我们平时的回调函数一个意思,能够在runAsync这个异步任务执行完成之后被执行。这就是Promise的作用了,简单来讲,就是能把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。```runAsync1().then(function(data){ console.log(data); return runAsync2();}).then(function(data){ console.log(data); return runAsync3();}).then(function(data){ console.log(data);});```这样能够按顺序,每隔两秒输出每个异步回调中的内容,在runAsync2中传给resolve的数据,能在接下来的then方法中拿到。运行结果如下:![img](https://images2015.cnblogs.com/blog/520134/201603/520134-20160311004311507-221152206.png) 在then方法中,你也可以直接return数据而不是Promise对象,在后面的then中就可以接收到数据了,比如我们把上面的代码修改成这样:```runAsync1().then(function(data){ console.log(data); return runAsync2();}).then(function(data){ console.log(data); return '直接返回数据'; //这里直接返回数据}).then(function(data){ console.log(data);});```那么输出就变成了这样:![img](https://images2015.cnblogs.com/blog/520134/201603/520134-20160311004444163-67067993.png)-------------------------------------------------------------------------------------### 11.forEach和jq中的each数组的循环 forEach方法```jsvar arr = [1,2,3,4];//遍历数组arr.forEach(function(value,index){ console.log();});``````jsvar arr = ['娃哈哈','爽歪歪','冰红茶','雪碧'];arr.forEach((value, index)=>{ console.log(index + '===' + value);})```jq中的each方法```js$('.imgUl>li').each(function (i,v) { $('
' + (i+1) + '
').appendTo($('.btnOl'))})```-------------------------------------------------------------------------------------### 12.垂直居中```js// 方法一:已知元素的高宽#div1{ background-color:#6699FF; width:200px; height:200px; position: absolute; //父元素需要相对定位 top: 50%; left: 50%; margin-top:-100px ; //二分之一的height,width margin-left: -100px; } //方法二:未知元素的高宽 #div1{ width: 200px; height: 200px; background-color: #6699FF; margin:auto; position: absolute; //父元素需要相对定位 left: 0; top: 0; right: 0; bottom: 0; }那么问题来了,如何垂直居中一个
?(用更简便的方法。)#container //
need-to-insert-img
的容器设置如下{ display:table-cell; text-align:center; vertical-align:middle;}```-------------------------------------------------------------------------------------### 13.rem的用法``````--------------------------------------------------------### 14.this的指向问题this对象的理解 this总是指向函数的直接调用者(而非间接调用者);----------函数定义的时候this是没有指向的,只有在调用的时候才有指向,----------如果函数包含多个对象,尽管这个函数是被最外层的调用的,也是指向上一层的函数如果有new关键字,this指向new出来的那个对象; 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window。构造函数里的thisnew做了什么(1)创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型。 (2)属性和方法被加入到 this 引用的对象中。 (3)新创建的对象由 this 所引用,并且最后隐式的返回 this 。箭头函数里的this指向箭头函数里的this指向与箭头函数外的this指向相同```jsdocument.getElementByID('btn').onclick = function(){ var this = This; setTimeout(function(){ This.style.backgroundColor = 'red'; })}```--------------------------------------------------### 15.清楚浮动的方法清除浮动有哪些方式?比较好的方式是哪一种? (Q1) (1)父级div定义height。 (2)结尾处加空div标签clear:both。 (3)父级div定义伪类:after和zoom。 (4)父级div定义overflow:hidden。(5)父级div定义overflow:auto。 (6)父级div也浮动,需要定义宽度。 (7)父级div定义display:table。 (8)结尾处加br标签clear:both。(Q2) 比较好的是第3种方式,好多网站都这么用。页面导入样式时,使用link和@import有什么区别? (1)link属于XHTML标签,除了加载CSS外,还能用于定义RSS, 定义rel连接属性等作用;而@import是CSS提供的,只能用于加载CSS; (2)页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载; (3)import是CSS2.1 提出的,只在IE5以上才能被识别,而link是XHTML标签,无兼容问题。----------------------------------------### 17.你有哪些性能优化的方法? (1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。 (2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数 (3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能。 (4) 当需要设置的样式很多时设置className而不是直接操作style。 (5) 少用全局变量、缓存DOM节点查找的结果。减少IO读取操作。(6) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)。 (7) 图片预加载,将样式表放在顶部,将脚本放在底部 加上时间戳。----------------------------------------### 18.请求报文和响应报文#### 请求行:如请求方式, 请求的页面, 遵循的协议GET的方式:```GET http://www.test.com/day07/student/edit.php?stu_id=1 HTTP/1.1```POST的方式:```POST http://www.test.com/day07/student/update.php?stu_id=1 HTTP/1.1```#### 请求头:如通知服务器, 浏览器支持的数据类型请求中,所有当前要用到的协议项的集合,即浏览器在发送真正请求数据之前,事先告诉服务器的一些信息(一般是浏览器自身的信息),并且每个协议项都要独占一行。#### 请求体: 请求数据,主要是通过表单提交的数据。 消息体(entity-body),请求体。只有POST方式提交的数据才会在请求数据中出现。一般使用application/x-www-form-urlencoded方式对表单数据进行编码,文件上传时必须使用multipart/form-data方式。#### 请求数据: 提交的核心数据: post数据#### 状态行(响应行):请求资源成功,失败,或者其他状态HTTP/1.1 200 ok#### 响应头:通知浏览器一些信息, 如返回数据的类型, 使用什么字符集显示数据#### 响应体:请求的HTML,PHP输出语句返回的数据.-------------------------------------------### 19.闭包的理解一、变量的作用域要理解闭包,首先必须理解Javascript特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。二、如何从外部读取局部变量?出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。Js代码```jsfunction f1(){ n=999; function f2(){ alert(n); // 999 }}```在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1 就是不可见的。这就是Javascript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!```jsfunction f1(){ n=999; function f2(){alert(n); } return f2; }var result=f1();result(); // 999```四、闭包的用途闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。五、使用闭包的注意点1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。```jsvar name = "The Window";var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; }};alert(object.getNameFunc()()); //The Windowvar name = "The Window";var object = { name : "My Object", getNameFunc : function(){ obj = this; return function(){ return obj.name; }; }};alert(object.getNameFunc()()); // My Object```-----------------------------------------### 20.绝对路径与相对路径--------------------------------------------------------### 21.DOM树---------------------------### 22.url获取值```1.url中的值: /***/:id 使用params获取``````2.url中的值: /***?id=3&name=zs 使用query获取```---------------------------### 23.路由 后端路由:一个前端的URL地址对应后台的一个资源(后端路由一定会涉及到数据请求) 前端路由: 通过浏览器的特性(window.location.hash/window.history)实现无刷新的跳转页面### 24.es6模块规范化(导入导出) import```js//全部导出 一个js文件中只能出现一次export default 出现export default 就不能出现exportfunciton tool() { console.log('工具函数')}export default {tool:tool} //utils就是导出的对象import utils from './utils.js'utils.tool()``````js//按需导出 可以出现多次export funciton tool() { console.log('工具函数')}//对应的导出方式是export function tool(){}//花括号中的变量必须和导出时的变量名称同名//按需导入import {tool} from './utils.js'```
need-to-insert-img