[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XO56tAfI-1589971833570)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1589010837908.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-65kEqSAI-1589971833643)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1589022076208.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1x5vBuLB-1589971833647)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588955408055.png)]
Vue-router懒加载就是按需加载组件,只有当路由被访问时才会加载对应的组件,而不是在加载首页的时候就加载,项目越大,对首屏加载的速度提升得越明显。
在做项目时,我们会用到很多库,采用cdn加载可以加快加载速度。
服务端渲染还能对seo优化起到作用,有利于搜索引擎抓取更多有用的信息(如果页面纯前端渲染,搜索引擎抓取到的就只是空页面)
单页面的优点:
1,用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小
2,前后端分离
3,页面效果会比较炫酷(比如切换页面内容时的专场动画)
单页面缺点:
1,不利于seo
2,导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理)
3,初次加载时耗时多
4,页面复杂度提高很多
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fayFxEn5-1589971833651)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588213585241.png)]
1.前进:
history.forward();
history.go(1);
2.后退:
history.back();
history.go(-1);
3.获取记录个数:
history.length:
treeshaking
多页打包
在网页中写了一段js代码,使用ajax向淘宝发起登陆请求,因为很多数人都访问过淘宝,所以电脑中存有淘宝的cookie,不需要输入账号密码直接就自动登录了,然后小黑在ajax回调函数中解析了淘宝返回的数据,得到了很多人的隐私信息。
同源政策:不是同协议 同域名 同端口 的网页无法相互访问。
用form表单提交到不同源的网页是被允许的,因为 form 提交到另一个域名之后,原页面的脚本无法获取新页面中的内容,所以浏览器认为这是安全的。
而 AJAX 是可以读取响应内容的,因此浏览器不能允许你这样做。如果你细心的话你会发现,其实请求已经发送出去了,你只是拿不到响应而已。
所以浏览器这个策略的本质是,一个域名的 JS ,在未经允许的情况下,不得读取另一个域名的内容。但浏览器并不阻止你向另一个域名发送请求。
同源策略限制内容有:
但是有三个标签是允许跨域加载资源:
对script的资源引用没有同源限制,通过动态插入一个script标签,当资源加载到页面后会立即执行的原理实现跨域
允许用户传递一个callback或者开始就定义一个回调方法,参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
只支持GET请求而不支持POST等其它类型的HTTP请求,它只支持跨域HTTP请求
缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I1uK21IR-1589971833653)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588932515140.png)]
搭建一个中转nginx服务器,用于转发请求。
使用nginx反向代理实现跨域,是最简单的跨域方式。只需要修改nginx的配置即可解决跨域问题,支持所有浏览器,支持session,不需要修改任何代码,并且不会影响服务器性能。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DLmqxnWv-1589971833654)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588953094846.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1WwsgukF-1589971833656)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588953112719.png)]
该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin;浏览器判断该相应头中是否包含Origin的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。
CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,需要两方配合
跨域请求不仅解决了ajax也解决了cookie,要在ajax请求里加上
jquery:xhrFields: {withCredentials: true}, crossDomain: true
js: xhr.withCredentials = true
跨域请求是否提供凭据信息(cookie、HTTP认证及客户端SSL证明等)
也可以简单的理解为,当前请求为跨域类型时是否在请求中协带cookie。
当配置了xhr.withCredentials = true时,必须在后端增加 response 头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。
且res.setHeader(“Access-Control-Allow-withCredentials”,“true”)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YRk9dWgW-1589971833657)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588932661968.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HptXS5Uj-1589971833658)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588932688537.png)]
只要同时满足以下两大条件,就属于简单请求
条件1:使用下列方法之一:
条件2:Content-Type 的值仅限于下列三者之一:
不符合以上条件的请求就肯定是复杂请求了。 复杂请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。
比如请求方法是PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP方法和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest
请求,否则就报错。
"预检"请求的HTTP头信息:
"预检"请求用的请求方法是OPTIONS
,表示这个请求是用来询问的。头信息里面,关键字段是Origin
,表示请求来自哪个源。
除了Origin
字段,"预检"请求的头信息包括两个特殊字段。
(1)Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT
。
(2)Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header
。
上面的HTTP回应中,关键的是Access-Control-Allow-Origin
字段,表示http://api.bob.com
可以请求数据。该字段也可以设为星号,表示同意任意跨源求。
Access-Control-Allow-Origin: *
如果浏览器否定了"预检"请求,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。这时,浏览器就会认定,服务器不同意预检请求,因此触发一个错误,被XMLHttpRequest
对象的onerror
回调函数捕获。
控制台会打印出如下的报错信息。
XMLHttpRequest cannot load http://api.alice.com.Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin.
服务器回应的其他CORS相关字段如下。
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin
头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin
头信息字段。
下面是"预检"请求之后,浏览器的正常CORS请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HbL66aCv-1589971833660)(C:\Users\wanglei\AppData\Roaming\Typora\typora-user-images\1588951781081.png)]
1、offsetLeft
假设 obj 为某个 HTML 控件。
obj.offsetTop 指 obj 距离上方或上层控件的位置,整型,单位像素。
obj.offsetLeft 指 obj 距离左方或上层控件的位置,整型,单位像素。
obj.offsetWidth 指 obj 控件自身的宽度,整型,单位像素。
obj.offsetHeight 指 obj 控件自身的高度,整型,单位像素。
一、offsetTop 返回的是数字,而 style.top 返回的是字符串,除了数字外还带有单位:px。
二、offsetTop 只读,而 style.top 可读写。
三、如果没有给 HTML 元素指定过 top 样式,则 style.top 返回的是空字符串。
offsetLeft 与 style.left、offsetWidth 与 style.width、offsetHeight 与 style.height 也是同样道理。
2、clientHeight 就是透过浏览器看内容的这个区域高度。
scrollHeight 则是网页内容实际高度。数字
clientWidth、offsetWidth 和 scrollWidth 的解释与上面相同,只是把高度换成宽度即可。
clientWidth = width + padding
clientHeight = height + padding
offsetWidth = width + padding + border
offsetHeight = width + padding + border
3、scrollTop:已滚动过去的高度 “卷起高度” onscoll函数
4、clientTop:clientTop可以返回div的上边框的大小,其值为一个整数,没有单位。
在不同尺寸的手机设备上,页面“相对性的达到合理的展示(自适应)”或者“保持统一效果的等比缩放(看起来差不多)”;
1)viewport(scale=1/dpr)
2)rem
3)flex
4)vm/vh
当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
JQuery和Vue的主要区别是JQuery主要是通过选择器来选取DOM,对其进行赋值,取值,事件绑定等操作,数据和页面是混合在一起的;Vue则是通过Vue对象将数据和视图完全分割开来,对数据进行操作,不再需要引用相应的DOM对象,实现了MVVM。
创建前/后: 在beforeCreate阶段,vue实例的挂载元素el和数据对象data都为undefined,还未初始化。在created阶段,vue实例的数据对象data有了,el还没有。
载入前/后:在beforeMount阶段,vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。在mounted阶段,vue实例挂载完成,data.message成功渲染。
更新前/后:当data变化时,会触发beforeUpdate和updated方法。
销毁前/后:在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,但是dom结构依然存在
(1)、什么是vue生命周期
答: Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期。
(2)、vue生命周期的作用是什么
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
(3)、vue生命周期总共有几个阶段
答:可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后
(4)、第一次页面加载会触发哪几个钩子
答:第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
(5)、DOM 渲染在 哪个周期中就已经完成
答:DOM 渲染在 mounted 中就已经完成了。
(6)、简单描述每个周期具体适合哪些场景
答:生命周期钩子的一些使用方法:
beforecreate : 可以在这加个loading事件,在加载实例时触发
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用
mounted : 挂载元素,获取到DOM节点
updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框
nextTick : 更新数据后立即操作dom
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YmRucxtD-1589971833663)(G:\html实例\笔记\lifecycle.png)]
在 MVC 模式中我们使用观察者模式,来实现当 Model 层数据发生变化的时候,通知 View 层的更新。
Model 代表数据模型,用纯JavaScript对象表示,数据和业务逻辑都是在Model层中定义。
View 代表UI 视图,负责对数据的展示,将数据模型转化成UI 展现出来。
ViewModel 负责监听Model中数据的改变并控制视图的更新,处理用户交互操作,是一个同步View 和 Model的对象。ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model。
Model和View并无直接关联,而是通过ViewModel来进行联系的,Model和ViewModel之间有着双向数据绑定的联系。因此当Model中的数据改变时会触发View层的刷新,View中由于用户交互操作而改变的数据也会在Model中同步。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
采用数据劫持结合发布者-订阅者模式,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调。
将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者。
1.监听器Observer,用来劫持并监听model所有属性,如果有变动就通知订阅者。
2.订阅者Watcher,可以收到属性的变化通知 并执行相应的回调函数。
3.解析器Compile,可以扫描和解析每个节点的相关指令,并替换模板数据,初始化视图 以及 将模板指令对应的节点绑定对应的更新函数,初始化相应的订阅器。
computed其实只是纯数据操作,需要返回数据结果。但是watch就可以监测某个数据发生了变更进行一系列的回调操作,不仅仅局限于返回数据,你也可以不返回。
计算属性具有缓存。计算属性是基于它们的依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。这就意味着只要 lastName和firstName都没有发生改变,多次访问 fullName计算属性会立即返回之前的计算结果,而不必再次执行函数。
而侦听器watch是侦听一个特定的值,当该值变化时执行特定的函数。例如分页组件中,我们可以监听当前页码,当页码变化时执行对应的获取数据的函数。
vue.directive(‘xxx’,{bind:function(el){…}},{update:function(){…}})
用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。
key的作用主要是为了高效的更新虚拟DOM
**hash模式:**在浏览器中符号“#”,#/hello称之为hash,用window.location.hash读取;
hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
**history模式:**history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
mode: 'history',
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
二、404 错误
1、hash模式下,仅hash符号之前的内容会被包含在请求中,如 http://www.abc.com, 因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回404错误;
2、history模式下,前端的url必须和实际向后端发起请求的url 一致,如http://www.abc.com/book/id 。如果后端缺少对/book/id 的路由处理,将返回404错误。
父传子用 props传递(异步,有可能数据还没获取到就渲染了,所以监听)
父亲:
data(){
return{
msg:'i am father'
}
}
儿子:
props:['message'],
{{message}}
子传父用$emit传递