web能够简单分为:结构、表现、行为。三部分独立开来使其模块化
w3c是对web作出规范,使代码更严谨,作出来的网页更易使用,维护。
w3c作出的规范可分为以下:
结构上:(标签规范对页面的搜索权重有很大关系,写的越规范网站在搜索排名越靠前)javascript
表现、行为上:php
发送机制css
一、get请求会将参数跟在URL后面进行参数传递,而post请求则是做为http消息的实体内容发送给web服务器;
二、get提交的数据限制是1024字节,这种显示是来自特定浏览器和服务器对它的限制。如ie的URL长度限制是2083字节,火狐理论上没有长度限制。注意这个限制是URL 的整个长度,而不是参数的长度。
三、get方式请求的数据会被浏览器缓存起来。由于其余人能够从浏览器的历史记录中读取到这些数据,好比:帐号或者密码等。在某种状况下,get方式会带来严重的安全问题,而post相对来讲能够避免这些问题。html
在服务端的区别前端
一、客户端请求使用get时,服务端使用Request.QueryString来获取,而客户端使用post请求时,服务端使用Request.Form来获取。
二、post用于建立资源,资源的内容会被编入http请示的内容中,例如,处理定货表单等。
三、当请求无反作用时(如进行搜索),使用get方法,当请求有反作用时(如添加数据),则用post方法。vue
1. 文件合并
2. 文件最小化/文件压缩
3. 使用 CDN 托管
4. 缓存的使用(多个域名来提供缓存)
5. 其余java
“官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(一般是一个函数),于是这些变量也是该表达式的一部分。webpack
通俗的讲:就是函数a的内部函数b,被函数a外部的一个变量引用的时候,就建立了一个闭包。web
闭包的特性:面试
①.封闭性:外界没法访问闭包内部的数据,若是在闭包内声明变量,外界是没法访问的,除非闭包主动向外界提供访问接口;
②.持久性:通常的函数,调用完毕以后,系统自动注销函数,而对于闭包来讲,在外部函数被调用以后,闭包结构依然保存在
系统中,闭包中的数据依然存在,从而实现对数据的持久使用。
优势:
① 减小全局变量。
② 减小传递函数的参数量
③ 封装;
缺点:
使用闭包会占有内存资源,过多的使用闭包会致使内存溢出等.
在https页面下的带有相对路径的请求都会与页面的协议保持一致。若是想在https页面下发送http的请求,若是只把连接写死成为http的绝对路径是不够的,这样会致使http的请求与总页面https的请求的session不一致。
为何呢?缘由是https的请求中服务器发回的cookie是标记为"secure"的,而http的请求时非"secure","因为在服务器端secure"的cookie不会兼容非"secure"的,因此当http的请求携带着同一jsessionid的cookie到达服务器时,服务器拒绝非"secure",进而返回的结果是一个新的非"secure"的cookie,因而两个session就不一样了。
怎么解决呢?由缘由分析可知,两个session不一样,更具体说是cookie的状态不一样。那么办法是,在接收到第一个https请求的响应后 到 发送下面的http请求以前,将cookie去"secure"状态,可是又要保证jsessionid不变。具体操做能够新建一个cookie(新建的是非"secure"状态),而后赋予同一个jessionid,而后加入response中。
推荐文章:传送门
人家讲得已经很清楚了,案例跟优缺点都整理出来了,推荐阅读
一、建立ajax对象(XMLHttpRequest/ActiveXObject(Microsoft.XMLHttp))
二、打开连接 open(请求方式,'请求路径',同步/异步)
三、发送 send()
四、当ajax对象完成第四步(onreadystatechange)数据接收完成,判断对象状态码(readystate) 4 HTTP响应彻底接收 在判断http响应状态(status)200-300之间或者304(缓存)执行回调函数 获取的数据转成字符串格式(responseText)
具体代码参考网上...
console.log('script start'); setTimeout(() => { console.log('setTimeout'); },0) Promise.resolve().then(function() { console.log('promise1'); }).then(function() { console.log('promise2'); }); console.log('script end')
考察的是代码执行顺序问题,定时器和主程序属于宏任务,Promise中then的回调属于微任务,在每一个宏任务里面都会先执行完微任务再去执行下一个宏任务。
本题执行逻辑应该是主线程中console.log('script start');碰到定时器,把这个宏任务扔事件队列里面,继续向下,碰到Promise.then异步任务,继续扔队列里面,执行console.log('script end');再去执行当前宏任务里面的微任务,即Promise.then回调函数,最后执行第二个宏任务定时器.
执行结果: script start script end promise1 promise2 setTimeout
const promise = new Promise((resolve,reject) => { console.log(1); resolve(); console.log(2); }); promise.then(()=>{ console.log(3); }); console.log(4);
Promise 构造函数是同步执行的,promise.then 中的函数是异步执行的。因此
执行结果: 1 2 4 3
var funcs = []; for(var i=0;i<10;i++) { funcs.push(function() { console.log(i); }); } funcs.forEach(function(func) { func(); });
基础题,匿名函数中的 i 值只有在函数调用执行的时候才会去寻找对应变量的,for循环结束后执行func()时,此时i变量已经变为10(最后有个i++),因此循环打印了十次10,想依次打印0-9的话可使用当即执行函数解决或者使用ES6的块级做用域let声明变量i.
js中number类型的数字都是采用64位的双精度浮点数进行存储的,其中1个符号位(0正1负),11个指数位,52个尾数位。0.1用二进制表示以下:0.000110011001100110011001100110011001100110011001100110011...
如上能够看出0.1二进制表示时尾数是超过52位的, 因此52位以后的会被舍去,这就有了浮点数存储的精度丢失问题。
setTimeout(()=>{ console.log('b') new Promise((resolve,reject)=>{ console.log('c'); resolve() }).then(res => { console.log('f') }) },0); new Promise((resolve,reject) => { console.log('d') resolve() }).then(res => { console.log('a') setTimeout(()=>{ console.log('e') },0) })
原理同第一题,答案为:dabcfe
let test1 = () => { console.log(this); }; function test2() { console.log(this); }; class t { test() { console.log(this); } } let test3 = t.prototype.test; test1.call(null); test2.call(null); test3.call(null);
先给出正确答案:
/// window ; window ; null (非严格模式), /// window ; null ; null (严格模式)
当call或apply的第一个参数为null || undefined时 this指向window ||global
call方法的参数,应该是一个对象。若是参数为空、null和undefined,则默认传入全局对象
类和模块的内部,默认就是严格模式,因此不须要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到将来全部的代码,其实都是运行在模块之中,因此 ES6 实际上把整个语言升级到了严格模式。
顺便解释一下call的用法,apply相似,参数不一样而已:
call方法 语法:call(thisobj,[argq,arg2]) 定义:调用一个对象的一个方法,以另外一个对象替换当前对象 说明: call方法能够用来代替一个对象调用一个方法,call方法能够将一个函数的对象上下文从初始化改成新的对象,也就是括号里面的本来的对象改成call()前面的对象、即用thisobj代替call前面的东西,最终用thisobj这个对象去执行call前面的方法。 若是没有提供 thisObj 参数,那么 Global 对象被用做 thisObj。
其实call才是函数调用最原始的方式,如今咱们使用的直接myFunc(args)调用函数的方式其实就是call调用的语法糖
let iArray = []; function getRandom(istart, iend){ var iChoice =iend - istart + 1; return Math.floor(Math.random() * iChoice + istart); } /*Math.random()就是获取 0-1 之间的随机数(永远获取不到 1)*/ for(let i=0; i<10; i++){ let result= getRandom(10,100); iArray.push(result); } iArray.sort(function(a,b){ return a>b; }); console.log(iArray);
let foo=1; function bar(){ foo=10; return; functionfoo(){} } bar(); console.log(foo); //1
为何是1而不是10先分析一下每步流程: 第一步:varfoo=1;全局变量foo被初始化赋值成1。 第二步:执行bar();方法。 第三步:bar()方法里,函数声明functionfoo(){}优先处理,这里JavaScript解析语法时(在运行以前)函数优先于一切。因此foo被初始化赋值为function(){}; 第四步:执行foo=10;这里制造了一个假象,认为没有用var声明指向的是外层foo=1;。其实不是。而是先在自身函数体里找有没有foo声明,找到以前声明的functionfoo(){};赋值成10,只是局部变量的值改写。 第五步:输出foo,这时找的是全局变量varfoo=1;输出1。
<style> .box { line-height: 24px; background-color: lightblue; } .box span { line-height: 48px; border: 1px solid; } </style> <div class="box"> <span>content...</span> </div>
考察的是inline box模型,它的工做就是包裹每行文字,一个没有设置height属性的div的高度就是由一个一个line boxes的高度堆积而成的,撑开div高度的是line-height不是文字内容.MDN 文档中对line-height的描述以下:
line-height CSS 属性用于设置多行元素的空间量, 好比文本。对于块级元素, 它指定元素行盒(line boxes)的最小高度。 对于非替代的inline元素, 它用于计算行盒(line box)的高度。
适用元素 all elements. It also applies to ::first-letter and ::first-line.
如上面最终显示 .box 容器 height = 48px; 1. 将<span>标签里的内容 改成<span>content ... <br> content ... </span> 后, .box 的height = 96px(48px*2)。 2. 将<span>标签里的内容 改成content ... <br><span> content ... </span> 后, .box 的height = 48 + 24 = 72px。
半像素边框固然不是简单地把1px改成0.5px,浏览器中最小的像素单位为1像素,是不能识别0.5个像素,
1.设置目标元素做为定位参照 box{position:relative} 2.给目标元素添加一个伪元素before或者after,并设置绝对定位 .box:before{content:""; position:absolute;} 3.给伪元素添加1px边框 border:1px solid #000; 4.设置伪元素的宽高为目标元素的2倍 width:200%; height:200%; 5.缩小0.5倍(缩放到原来大小) transform-origin: 0 0; transform:scale(0.5,0.5); 6.把border 边框在线框内绘制 box-sizing:border-box;
简单地说,对象是引用数据类型,那你每次导入这个组件的时候,其实引用的是同一个内存地址,componentA改变了引用这块地址的数据后,componentB中的这块地址对应的数据也会被改变。
那是由于在js中,函数的{}才有独立的做用域,对象的{},if(){}是不构成做用域的.
函数里面,每调用一次函数就会建立一个新的函数做用域,他们之间是互相独立的,这样的话,无论你同时引入同一个组件多少次,他们之间的组件属性都是独立的,互不干扰。
vue的响应式核心是Object.defineProperty实现的.
Object.defineProperty(obj, key, { set:function(){}, get:function(){} })
被Object.defineProperty绑定过的数据会被监听到,改变这个对象的时候会触发get和set事件,这也是vue的model层和view层通讯的基础,其实vue中的Observer就是基于Object.defineProperty来实现的。
Observer是数据的观察者,与model层直接通讯,当数据更改时,它会通知dep(专门管理数据监听依赖的东西),dep会收集到它所须要的依赖,当get的时候,收集订阅者(这里的订阅者实际上是观察者模式下的订阅者,简单地说,就是它须要知道具体get什么订阅者,什么是观察者模式和发布订阅者设计模式,具体网上不少相关资料解释),把他添加到依赖,好比,watch和computed都依赖一个data进行监听或者计算,那么dep会将这两个不一样的依赖收集。当set的时候会发布更新,通知watcher更新view层。一个属性可能有多个依赖,每一个响应式数据都有一个Dep来管理它的依赖。
每个依赖又是依靠一个中介的角色来通知变化从而更新视图的,所以watcher能通知变化去执行各自的代码,固然它也能区分本身所属的依赖,好比本身是属于data仍是watch仍是computed.
放两张网上的图能够更明了的说明他们之间的关系,也能够看看大佬们的文章,讲的更仔细,想学会这种设计模式仍是要撸源码,应付面试已经够了。
原图连接
v-model本质上就是一个语法糖,实现原理其实就是上面说过的数据绑定加上底层的input事件监听,经过v-bind绑定一个数据传给子组件,子组件里面的model默认用value属性接受,而后子组件监听数据发生变化,emit触发父组件的input事件,经过触发事件来进行传值,实现了父子组件数据的双向绑定。
定义了一种一对多的依赖关系,即当一个对象的状态发生改变的时候,全部依赖他的对象都会获得通知。
观察者模式是由具体目标(发布者/被观察者)调度的,而发布/订阅模式是由独立的调度中心进行调度,因此观察者模式的订阅者与发布者之间是存在依赖的,而发布/订阅模式则不会(至关于一个中介的角色,一个全局的Event,发布者不须要知道具体要通知谁,订阅者也不须要知道具体是谁通知的);能够说发布订阅模式是观察者模式进一步解耦,在实际中被大量运用的一种模式。
单元测试:按空间切割,对每一个组件进行测试
好比,我要测试日期输入框,那么我编写的测试用例应该包括如下部分:
E2E测试:按时间切割,对每一个流程进行测试
好比,我要测试搜索功能,那么我编写的测试用例应该模拟如下步骤:
vue init webpack test
1.v-on绑定多个方法:<p v-on="{click:dbClick,mousemove:MouseClick}"></p>
2.一个事件绑定多个函数:<p @click="one(),two()">点击</p>
.lazy:
v-modeil不用多说,输入框改变,这个数据就会改变,lazy这个修饰符会在光标离开input框才会更新数据:
<input type="text" v-model.lazy="value">
.trim:
输入框过滤首尾的空格:
<input type="text" v-model.trim="value">
.number:
先输入数字就会限制输入只能是数字,先字符串就至关于没有加number,注意,不是输入框不能输入字符串,是这个数据是数字:
<input type="text" v-model.number="value">
.stop:
阻止事件冒泡,至关于调用了event.stopPropagation()方法。这个应该不须要解释:
<button @click.stop="test">test</button>
.prevent:
阻止默认行为,至关于调用了event.preventDefault()方法,好比表单的提交、a标签的跳转就是默认事件:
<a @click.prevent="test">test</a>
.self:
只有元素自己触发时才触发方法,就是只有点击元素自己才会触发。好比一个div里面有个按钮,div和按钮都有事件,咱们点击按钮,div绑定的方法也会触发,若是div的click加上self,只有点击到div的时候才会触发,变相的算是阻止冒泡:
<div @click.self="test"></div>
.once:
只能用一次,不管点击几回,执行一次以后都不会再执行:
<div @click.once="test"></div>
.capture:
事件的完整机制是捕获-目标-冒泡,事件触发是目标往外冒泡,好比:
<div @click="test(1)"> <button @click="test(2)">test</button></div> 顺序是2 1,capture的做用就是让这个顺序相反: <div @click.capture="test(1)"> <button @click="test(2)">test</button></div>
先1 后2。
.passive:
其实我不怎么理解,官网解释说能够提高移动端的性能,查了查,大概解释就是每次滚动都会有一个默认事件触发,加了这个就是告诉浏览器,不须要查询,不须要触发这个默认事件preventDefault:
<!-- 滚动事件的默认行为 (即滚动行为) 将会当即触发 --> <!-- 而不会等待 `onScroll` 完成 --> <!-- 这其中包含 `event.preventDefault()` 的状况 --> <div v-on:scroll.passive="onScroll">...</div>
.native:
组件绑定当前组件的事件是不会触发的,须要用native才能触发:
<My-component @click="shout(3)"></My-component>
鼠标.left、.reight、.middle:
就是鼠标点击的时候就触发:
<button @click.right="test">test</button>
.keyCode:
监听按键的指令,具体能够查看vue的键码对应表:
<input type="text" @keyup.enter="test(1)"> <button @click.enter="test(1)">test</button>
注意,只有你点击过一次或者聚焦到这个输入框才能使用键盘触发。
.exact:
系统修饰键,只有按着这个键而后用鼠标点击才会触发,官网解释:
<!-- 即便 Alt 或 Shift 被一同按下时也会触发 --> <button @click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button @click.ctrl.exact="onCtrlClick">A</button> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button @click.exact="onClick">A</button>
可是我试了一下没有用。
.sync
对prop进行双向绑定,我的暂时用不习惯:
//父组件 <fa-comp :fatest.sync="test"></fa-comp> //子组件 this.$emit('update:fatest,sontest);
......
持续更新~