vue每个组件都是独立的,每个组件都有一个属于它的生命周期,从一个组件创建、数据初始化、挂载、更新、销毁,这就是一个组件所谓的生命周期。
beforeCreate() 在实例创建之间执行,数据未加载状态
created() 在实例创建、数据加载后,能初始化数据,dom渲染之前执行
beforeMount() 虚拟dom已创建完成,在数据渲染前最后一次更改数据
mounted() 页面、数据渲染完成,真实dom挂载完成
beforeUpadate() 重新渲染之前触发
updated() 数据已经更改完成,dom 也重新 render 完成,更改数据会陷入死循环
beforeDestory() 和 destoryed() 前者是销毁前执行(实例仍然完全可用),后者则是销毁后执行
因为:VUE中MVVM思想、虚拟DOM等机制
所以:需要钩子函数/生命周期,从而方便开发、提升性能等
常用路由模式有2个,分别为hash和history 直接修改路由构造函数加个mode键即可
准备说有3个,hash/history用于客户端,abstract用户服务端
vue路由是基于SPA单页面应用思想去开发的
利用BOM API 来使用
hash模式 通过 BOM location对象的hash属性来改变路由
history模式 通过BOM history对象的pushState属性来改变路由
SPA优点:1.切换速度快、减少HTTP请求、便于加特效
2.前后端分离便于后期扩展
3.转场动画,也就是一个页面切换另一个页面 transition
缺点:1. 不利于seo优化
2. 初次加载耗时(注:这时候可能问vue首屏加载慢如何解决 见优化部分答案)SPA缺点:不利于SEO优化(就是百度可以搜到你)
MPA多页面的好处
概念:有多个页面,跳转方式是页面之间的跳转
优点:首屏加载快;seo优化好
缺点:跳转较慢;相对复杂,没有实现前后端分离
如何选择
根据项目需求,老板没有明确说直接用vue脚手架创建框架就行,
但是老板说需要seo优化则通过:Vue.js 服务器端渲染(nuxt.js)
写法不一样,声明式导航是写在组件的template中,通过router-link来触发,
编程式导航写在js函数中,通过this.$router.push(xxx)来触发路径
就是用来存放所有组件数据的仓库,也就是组件状态管理工具
state:存储数据;
mutations:更新数据的方法;
actions:调用mutations方法,更新state数据;
getters:对state中的数据进行预处理;
vuex 的作用

实现所有组件相互通信,数据共享
组件之间需要相互通信时,例如购物车购买数量、登录信息等
什么是计算属性和侦听器

计算属性:普通方法的升级版,有缓存
怎么用:在data同级定义computed对象来声明计算属性、调用不加小括号
侦听器:用来监控模型数据变化
怎么用:在data同级定义watch对象声明侦听器、方法名就是data中的键、不能调用
如何选:
1 事件 和 封装减少视图代码冗余便于后期维护 先用普通方法
2 上述多次执行耗时 计算属性优化
3 当需要监控模型数据改变 使用侦听器。例如:搜索、全选全不选等等
什么是混入

是什么:vue中提供的解决组件代码冗余的技术,可以提起相同的普通方法、模型数据等
怎么用:Vue.mixin 或 mixins键来定义
实战用:后期项目的跳转、返回上一页、提示信息等等
什么是vue组件

是什么:用来代替传统HTML的一种解决方案、里面还是HTML、JS、CSS
好处:倡导模块化、便于后期相互调用、从而减少代码冗余、方便维护
怎么用: Vue.component(组件名,{template, methods, data, ....})
组件通信工作流

父传子: 子组件通过 props 属性,绑定父组件数据,实现双方通信
子传父: 将父组件的事件在子组件中通过 $emit 触发
兄弟 :1 创建bus总线 全局仓库
2 传递数据 bus.$emit
3 接受数据 bus.$on
vue中的事件修饰符

事件修饰符:.stop、.prevent、.once等
键盘修饰符:.enter、.ctrl .enter等
什么是路由懒加载

路由懒加载是通过异步的方式来加载对应的路由组件,提高页面相应速度
vue的路由使用步骤?

1.下载vue-router路由模块;
2.创建路由对象;
3.配置路由规则;
4.将路由对象注册为vue实例对象的成员属性;
http协议状态码301和302的区别

301 redirect: 301 代表永久性转移(Permanently Moved)
302 redirect: 302 代表暂时性转移(Temporarily Moved )
302重定向只是暂时的重定向,浏览器会抓取新的内容而保留旧的地址,因为服务器返回302,所以,搜索浏览器认为新的网址是暂时的。
301重定向是永久的重定向,浏览器在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址
谈谈你对虚拟DOM的理解?

就是用JS 的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点,因为浏览器工作机制,通过虚拟DOM提升性能。
回流重绘

回流:重新布局
重绘:改变元素属性样式
谈谈你对diff算法的理解?

diff算法是虚拟DOM技术的产物,核心思想是通过新旧虚拟DOM做对比,(即diff),将变化的地方更新在真实的DOM上,也需要diff高效执行对比的过程,从而降低时间复杂度为O(n).
步骤一:用JS对象模拟DOM树
步骤二:比较新旧虚拟DOM树的差异
步骤三:把差异应用到真正的DOM树上
v-for中有key值和没有key值的区别

它们区别主要在于虚拟DOM的复用,绑定key可以更好的复用,避免重复渲染
fetch、axios区别

相同点:都是基于promise封装的HTTP库
不同点:1 fetch官方 axios第三方
2 axios更强例如拦截器、而fetch需要自己封装等
请谈谈对http的理解

HTTP:超文本传输协议,主要由request请求 和response响应 组成,规定了计算机之间如何相互通信
项目开发中常遇到的
请求方式常用的有get、post、put、delete
HTTP状态码:...
请求头:expire、gzip、content-type等
HTTP状态码

100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 请求成功
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 永久性重定向。
302 Found 临时性重定向。
303 SeeOther 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 浏览器缓存
400 BadRequest 参数有误。
401 Unauthorized 密码错误。
403Forbidden 没有权限。
404 NotFound 文件不存在。
500 InternalServer Error 服务器错误。
503 ServiceUnavailable 服务器端暂时无法处理请求(可能是过载或维护)。
vue实现数据双向绑定的原理

采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调
Created与Mounted的区别

Created:在dom渲染之前调用,通常初始化某些属性值,然后再渲染成视图。
Mounted:在dom渲染之后调用,初始化页面完成后,再对dom节点进行一些需要的操作。
vue中mounted和updated这两个生命周期怎么运行的

mounted 页面首次渲染完毕时触发
updated 模型数据更新时候触发
vue首屏加载过慢如何解决

1、路由懒加载(也就是要的时候的时候进行加载。
2、UI组件按需加载
3、webpack启用gzip压缩
什么是JSX

JSX即JavaScript XML,是JS的一种扩展语言。
解释单向数据流和双向数据绑定

单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。要使UI发生变更就必须创建各种 action 来维护对应的 state;
双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度。
Vue 如何去除url中的

vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history。
需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面(重定向)。
和
router的区别

$router 为 VueRouter 实例,想要导航到不同 URL,则使用 $router.push 方法$route 为当前 router 跳转对象里面可以获取 name 、 path 、 query 、 params 等
NextTick 是做什么的

$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功
Vue 组件 data 为什么必须是函数

因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
计算属性computed 和事件 methods 有什么区别

我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的
不同点:
computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值对于 method ,只要发生重新渲染,method 调用总会执行该函数
watch和computed区别
computed结果会缓存,依赖于外界响应式依赖发生变化而变化
watch是直接监听某个属性,只要这个属性发生了变化,就会触发相应的函数回调,并且能获取到变更值以及变更之前的值
清除keep-alive缓存

deactivated () { //清除keep-alive的缓存
this.$destroy(true)
}
对比 jQuery ,Vue 有什么不同

jQuery 专注视图层,通过操作 DOM 去实现页面的一些逻辑渲染; Vue 专注于数据层,通过数据的双向绑定,最终表现在 DOM 层面,减少了 DOM 操作Vue 使用了组件化思想,使得项目子集职责清晰,提高了开发效率,方便重复利用,便于协同开发
vue-router 路由实现

路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能
Vue 组件 data 为什么必须是函数

因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
Vue 中怎么自定义指令

全局注册
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
局部注册
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
Vue 中怎么自定义过滤器

可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值
Vue.filter('reverse', function (value) {
return value.split('').reverse().join('')
})
过滤器也同样接受全局注册和局部注册
对 keep-alive 的了解

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
可以使用API提供的props,实现组件的动态缓存
钩子函数
1.activated:页面第一次进入的时候,钩子触发的顺序是created->mounted->activated
2.deactivated :页面退出的时候会触发deactivated,当再次前进或者后退的时候只触发activated
属性:include包含的组件会被缓存,exclude排除的组件不会被缓存
Vue 的核心是什么

数据驱动 组件系统
vue 等单页面应用的优缺点

优点:1.良好的交互体验 2.良好的前后端工作分离模式 3.减轻服务器压力
缺点:1.SEO难度较高 2.前进、后退管理 3.初次加载耗时多
vue-router有哪几种导航守卫

1>全局守卫
a:router.beforeEach 全局前置守卫,进入路由之前
b:router.beforResolve 全局解析守卫,在beforeRouterEnter调用之后调用
c:router.afterEach 全局后置钩子,进入路由之后
2>路由独享守卫
如果不想全局配置守卫的话,可以为某些路由单独配置守卫
3>路由组件内的守卫
beforeRouteEnter 进入路由前, 在路由独享守卫后调用 不能 获取组件实例 this,组件实例还没被创建beforeRouteUpdate (2.2)路由复用同一个组件时,在当前路由改变,但是该组件被复用时调用 可以访问组件实例this
beforeRouteLeave 离开当前路由时, 导航离开该组件的对应路由时调用,可以访问组件实例 this
vue-router 使用params与query传参有什么区别

vue-router 可以通过 params 与 query 进行传参
// 传递
this.$router.push({path: './xxx', params: {xx:xxx}})
this.$router.push({path: './xxx', query: {xx:xxx}})
// 接收
this.$route.params
this.$route.query
params 是路由的一部分,必须要有。query 是拼接在 url 后面的参数,没有也没关系
params 不设置的时候,刷新页面或者返回参数会丢,query 则不会有这个问题
你在什么场景下使用了vuex?

当应用遇到多个组件共享状态的时候,即:多个视图依赖于同一个状态,不同视图的行为需要变更同一个状态
如:
用户的个人信息管理模块
电商项目购物车模块
props和data的优先级,区别

props>data
props就相当于你的参数,data就相当于局部变量,组件其实就是一个函数
xxxxxxxxxx vuex是:就是用来存放所有组件数据的仓库,也就是组件状态管理工具state:存储数据;mutations:更新数据的方法;actions:调用mutations方法,更新state数据;getters:对state中的数据进行预处理;
实现所有组件相互通信,数据共享
组件之间需要相互通信时,例如购物车购买数量、登录信息等
计算属性:普通方法的升级版,有缓存
怎么用:在data同级定义computed对象来声明计算属性、调用不加小括号
侦听器:用来监控模型数据变化
怎么用:在data同级定义watch对象声明侦听器、方法名就是data中的键、不能调用
如何选:
1 事件 和 封装减少视图代码冗余便于后期维护 先用普通方法
2 上述多次执行耗时 计算属性优化
3 当需要监控模型数据改变 使用侦听器。例如:搜索、全选全不选等等
是什么:vue中提供的解决组件代码冗余的技术,可以提起相同的普通方法、模型数据等
怎么用:Vue.mixin 或 mixins键来定义
实战用:后期项目的跳转、返回上一页、提示信息等等
是什么:用来代替传统HTML的一种解决方案、里面还是HTML、JS、CSS
好处:倡导模块化、便于后期相互调用、从而减少代码冗余、方便维护
怎么用: Vue.component(组件名,{template, methods, data, ....})
父传子: 子组件通过 props 属性,绑定父组件数据,实现双方通信
子传父: 将父组件的事件在子组件中通过 $emit 触发
兄弟 :1 创建bus总线 全局仓库
2 传递数据 bus.$emit
3 接受数据 bus.$on
事件修饰符:.stop、.prevent、.once等
键盘修饰符:.enter、.ctrl .enter等
路由懒加载是通过异步的方式来加载对应的路由组件,提高页面相应速度
1.下载vue-router路由模块;
2.创建路由对象;
3.配置路由规则;
4.将路由对象注册为vue实例对象的成员属性;
301 redirect: 301 代表永久性转移(Permanently Moved)
302 redirect: 302 代表暂时性转移(Temporarily Moved )
302重定向只是暂时的重定向,浏览器会抓取新的内容而保留旧的地址,因为服务器返回302,所以,搜索浏览器认为新的网址是暂时的。
301重定向是永久的重定向,浏览器在抓取新的内容的同时也将旧的网址替换为了重定向之后的网址
就是用JS 的Object对象模拟DOM中的节点,然后再通过特定的render方法将其渲染成真实的DOM节点,因为浏览器工作机制,通过虚拟DOM提升性能。
回流:重新布局
重绘:改变元素属性样式
diff算法是虚拟DOM技术的产物,核心思想是通过新旧虚拟DOM做对比,(即diff),将变化的地方更新在真实的DOM上,也需要diff高效执行对比的过程,从而降低时间复杂度为O(n).
步骤一:用JS对象模拟DOM树
步骤二:比较新旧虚拟DOM树的差异
步骤三:把差异应用到真正的DOM树上
它们区别主要在于虚拟DOM的复用,绑定key可以更好的复用,避免重复渲染
相同点:都是基于promise封装的HTTP库
不同点:1 fetch官方 axios第三方
2 axios更强例如拦截器、而fetch需要自己封装等
HTTP:超文本传输协议,主要由request请求 和response响应 组成,规定了计算机之间如何相互通信
项目开发中常遇到的
请求方式常用的有get、post、put、delete
HTTP状态码:...
请求头:expire、gzip、content-type等
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 请求成功
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 永久性重定向。
302 Found 临时性重定向。
303 SeeOther 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 浏览器缓存
400 BadRequest 参数有误。
401 Unauthorized 密码错误。
403Forbidden 没有权限。
404 NotFound 文件不存在。
500 InternalServer Error 服务器错误。
503 ServiceUnavailable 服务器端暂时无法处理请求(可能是过载或维护)。
采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调
Created:在dom渲染之前调用,通常初始化某些属性值,然后再渲染成视图。
Mounted:在dom渲染之后调用,初始化页面完成后,再对dom节点进行一些需要的操作。
mounted 页面首次渲染完毕时触发
updated 模型数据更新时候触发
1、路由懒加载(也就是要的时候的时候进行加载。
2、UI组件按需加载
3、webpack启用gzip压缩
JSX即JavaScript XML,是JS的一种扩展语言。
单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。要使UI发生变更就必须创建各种 action 来维护对应的 state;
双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度。
vue-router 默认使用 hash 模式,所以在路由加载的时候,项目中的 url 会自带 #。如果不想使用 #, 可以使用 vue-router 的另一种模式 history。
需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面(重定向)。
$router 为 VueRouter 实例,想要导航到不同 URL,则使用 $router.push 方法$route 为当前 router 跳转对象里面可以获取 name 、 path 、 query 、 params 等
$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功
因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
我们可以将同一函数定义为一个 method 或者一个计算属性。对于最终的结果,两种方式是相同的
不同点:
computed: 计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值对于 method ,只要发生重新渲染,method 调用总会执行该函数
computed结果会缓存,依赖于外界响应式依赖发生变化而变化
watch是直接监听某个属性,只要这个属性发生了变化,就会触发相应的函数回调,并且能获取到变更值以及变更之前的值
deactivated () { //清除keep-alive的缓存
this.$destroy(true)
}
jQuery 专注视图层,通过操作 DOM 去实现页面的一些逻辑渲染; Vue 专注于数据层,通过数据的双向绑定,最终表现在 DOM 层面,减少了 DOM 操作Vue 使用了组件化思想,使得项目子集职责清晰,提高了开发效率,方便重复利用,便于协同开发
路由就是用来跟后端服务器进行交互的一种方式,通过不同的路径,来请求不同的资源,请求不同的页面是路由的其中一种功能
因为js本身的特性带来的,如果 data 是一个对象,那么由于对象本身属于引用类型,当我们修改其中的一个属性时,会影响到所有Vue实例的数据。如果将 data 作为一个函数返回一个对象,那么每一个实例的 data 属性都是独立的,不会相互影响了
全局注册
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
局部注册
directives: {
focus: {
// 指令的定义
inserted: function (el) {
el.focus()
}
}
}
可以用全局方法 Vue.filter() 注册一个自定义过滤器,它接收两个参数:过滤器 ID 和过滤器函数。过滤器函数以值为参数,返回转换后的值
Vue.filter('reverse', function (value) {
return value.split('').reverse().join('')
})
过滤器也同样接受全局注册和局部注册
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
可以使用API提供的props,实现组件的动态缓存
钩子函数:activated deactivated
属性:include包含的组件会被缓存,exclude排除的组件不会被缓存
数据驱动 组件系统
优点:1.良好的交互体验 2.良好的前后端工作分离模式 3.减轻服务器压力
缺点:1.SEO难度较高 2.前进、后退管理 3.初次加载耗时多
1>全局守卫
a:router.beforeEach 全局前置守卫,进入路由之前
b:router.beforResolve 全局解析守卫,在beforeRouterEnter调用之后调用
c:router.afterEach 全局后置钩子,进入路由之后
2>路由独享守卫
如果不想全局配置守卫的话,可以为某些路由单独配置守卫
3>路由组件内的守卫
beforeRouteEnter 进入路由前, 在路由独享守卫后调用 不能 获取组件实例 this,组件实例还没被创建beforeRouteUpdate (2.2)路由复用同一个组件时,在当前路由改变,但是该组件被复用时调用 可以访问组件实例this
beforeRouteLeave 离开当前路由时, 导航离开该组件的对应路由时调用,可以访问组件实例 this
vue-router 可以通过 params 与 query 进行传参
// 传递
this.$router.push({path: './xxx', params: {xx:xxx}})
this.$router.push({path: './xxx', query: {xx:xxx}})
// 接收
this.$route.params
this.$route.query
params 是路由的一部分,必须要有。query 是拼接在 url 后面的参数,没有也没关系
params 不设置的时候,刷新页面或者返回参数会丢,query 则不会有这个问题
当应用遇到多个组件共享状态的时候,即:多个视图依赖于同一个状态,不同视图的行为需要变更同一个状态
如:
用户的个人信息管理模块
电商项目购物车模块
props>data
props就相当于你的参数,data就相当于局部变量,组件其实就是一个函数
1.DNS解析寻址,将输入的url解析为ip地址
2.TCP三次握手:根据ip地址与服务器进行连接通信
3.发送HTTP请求,请求相关资源
4.服务器接收请求并返回HTTP报文,携带指定资源
5.浏览器解析资源,渲染页面
6.TCP四次挥手,关闭连接
a、首先 js 是单线程运行的,在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。
b、在执行同步代码的时候,如果遇到了异步事件,会将异步代码放到事件循环中,继续执行执行栈中的其他任务;
c、当同步事件执行完毕后,再将异步事件对应的回调加入到与当前执行栈中不同的另一个任务队列中等待执行
d、任务队列可以分为宏任务对列和微任务对列,当当前执行栈中的事件执行完毕后,js引擎首先会判断微任务对列中是否有任务可以执行,如果有就将微任务队首的事件压入栈中执行
e、当微任务对列中的任务都执行完成后再去判断宏任务对列中的任务
深拷贝递归地复制新对象中的所有值或属性,而拷贝只复制引用。
在深拷贝中,新对象中的更改不会影响原始对象,而在浅拷贝中,新对象中的更改,原始对象中也会跟着改。
在深拷贝中,原始对象不与新对象共享相同的属性,而在浅拷贝中,它们具有相同的属性。
方法:深拷贝:1.递归,2.JSON.stringify(JSON.parse()),3. JQ的extend方法
浅拷贝:1. Object.assign() 2. 使用 for in 循环,遍历每一个属性,将他们赋值给新的对象 3. 直接用=赋值 4 …扩展运算符
全局作用域:在任何地方都能被访问,window对象下的内置属性都是全局作用域
函数作用域:固定代码片段中
作用域链:作用域都有上下级关系,上下级关系确定函数在哪个作用域下创建,变量取值都会在当前作用域中查找,如果没有查到就会像上级作用域查找,直到查到全局作用域,这个查找的过程叫做作用域链
在React当中,有个onChange属性,可以给input绑定事件,当input框里的值发生变化时会触发调用方法,这个方法会合并data到this.state,并重新渲染组件。
如果一个函数 接受一个或多个组件作为参数并且返回一个组件 就可称之为 高阶组件。
什么时候使用:页面复用,组件渲染性能追踪,权限控制。
React组件的生命周期可以分为挂载、渲染和卸载这几个阶段,当渲染后的组件需要更新的时候,我们会重新去渲染组件,直到卸载。
因此,我们可以把React生命周期分为两类:
1 当组件在挂载或卸载时
2 当组件接收新的数据时,即组件更新时
componentWillMount 在渲染前调用
componentDidMount 在第一次渲染后调用
componentWillReceiveProps 在组件接受一个新的prop时调用,这个方法在第一次渲染的时候不会被调用。
shouldComponentUpdate 返回一个布尔值,在组件接受到新的props或是state时被调用。在初始化时或是使用forceUpdate时不被调用。可以在你确认不需要更新组件时使用。
componentWillUpdate 在组件接受到新的props或是state但还没有render时被调用。在初始化时不会被调用。
componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用
componentWillUnmount 在组件从DOM中移除的时候立即被调用
1 减少不必要的props引起的重绘
2 减少不必要state引起的重绘
3 长列表优化
1.View在redux中会派发action方法;
2.action通过store的dispatch方法会派发给store;
3.store接收action,连同之前的state,一起传递给reducer;
4.reducer返回新的数据给store;
5.store去改变自己的state。
它主要在于虚拟DOM的复用,绑定key可以更好的复用,避免重复渲染
connect是一个高阶函数,首先传入mapStateToProps、mapDispatchToProps,然后返回一个生产Component的函数(wrapWithConnect),然后再将真正的Component作为参数传入wrapWithConnect,这样就生产出一个经过包裹的Connect组件。
1 两种常用的路由:HashRouter和BrowserRouter
2 路由组件:包裹整个应用:一个React应用只使用一次
3 HashRouter:使用URL的哈希值实现,就是在地址栏的后面有#(localhost:3000/#/sdjdjdj)
4 推荐使用BrowserRouter:使用H5的historyAPI实现(localhost:3000/djjdd)
5 Link:组件:用于指定导航链接(a标签) 在浏览器解析时,会将link组件解析成a标签
6 Router组件:指定路由展示相关的组件信息
通过params
1.路由表中
2.Link处
HTML方式
XXXX
JS方式
this.props.history.push( '/sort/'+'2' )
3.sort页面
通过 this.props.match.params.id 就可以接受到传递过来的参数(id)
通过query
前提:必须由其他页面跳过来,参数才会被传递过来
注:不需要配置路由表。路由表中的内容照常:
1.Link处
HTML方式
JS方式
this.props.history.push({ path : '/sort' ,query : { name: ' sunny'} })
2.sort页面
this.props.location.query.name
原型:js给每个函数分配的公共空间,减少内存占用
原型链:多个原型的集合,当调用对象的属性或方法时,先自身找,找不到去原型链上找,一直找到Object构造函数得原型链
1.编译环境不一样,less是基于JavaScript的在客户端处理 所以安装的时候用npm,sass是基于ruby所以在服务器处理。
2.变量符不一样,Less是@,而Scss是$,而且变量的作用域也不一样。
Sass的功能比Less强大
1》link是html的标签,不仅可以加载css还可以定义Rss , rel连接属性;@import是css的语法规则,只能引入样式;
2》加载页面时,link是同时加载的,@impor是页面加载完后才加载
3》link没有兼容性的问题,而@import只在较高版本的浏览器才可以识别
4》link可以通过js插入操作dom,@import 不可以!
1;每个构造函数都有一个原型对象
2;每个原型对象都有一个指向构造函数的指针
3;每个实例函数都有一个指向原型对象的指针。
4;查找方式是一层一层查找,直至顶层。Object.prototype
就是我们先设置图片的data-set属性(当然也可以是其他任意的,只要不会发送http请求就行了,作用就是为了存取值)值为其图片路径,由于不是src,所以不会发送http请求。 然后我们计算出页面scrollTop的高度和浏览器的高度之和, 如果图片举例页面顶端的坐标Y(相对于整个页面,而不是浏览器窗口)小于前两者之和,就说明图片就要显示出来了(合适的时机,当然也可以是其他情况),这时候我们再将 data-set 属性替换为 src 属性即可。
或
好处:减少HTTP请求
1、监控滚动条滚动
2、获取总可视内容高度(可见视口高度+滚动条滚动高度)
3、获取所有图片
4、遍历步骤3
5、在步骤4中判断,图片.offsetTop <= 步骤2 成立-修改src属性为data-src、失败-不管
6、节流防抖优化
相同点:
· 都支持服务器端渲染
· 都有Virtual DOM,组件化开发,通过props参数进行父子组件数据的传递,都实现webComponent规范
· 数据驱动视图
· 都有支持native的方案,React的React native,Vue的weex
不同点:
· React严格上只针对MVC的view层,Vue则是MVVM模式
· virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
· 组件写法不一样, React推荐的做法是 JSX + inline style, 也就是把HTML和CSS全都写进JavaScript了,即'all in js'; Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,jd写在同一个文件;
· 数据绑定: vue实现了数据的双向绑定,react数据流动是单向的
· state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理
相同点:px和em都是长度单位;
异同点:px的值是固定的,指定是多少就是多少,计算比较容易。em得值不是固定的,并且em会继承父级元素的字体大小。
浏览器的默认字体高都是16px。所以未经调整的浏览器都符合: 1em=16px。那么12px=0.75em, 10px=0.625em。
1)意外的全局变量引起的内存泄露
function leak(){ leak="xxx";//leak成为一个全局变量,不会被回收 }
2)闭包引起的内存泄露
3)没有清理的DOM元素引用
4)被遗忘的定时器或者回调
5)子元素存在引起的内存泄露
http缓存
websql
cookie
localstorage
sessionstorage
flash缓存
渲染的流程如下:
1.解析HTML文件,创建DOM树。
自上而下,遇到任何样式(link、style)与脚本(script)都会阻塞(外部样式不阻塞后续外部脚本的加载)。
2.解析CSS。优先级:浏览器默认设置<用户设置<外部样式<内联样式
CSS3实现圆角(border-radius),阴影(box-shadow),
对文字加特效(text-shadow、),线性渐变(gradient),旋转(transform)
transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜
增加了更多的CSS选择器 多背景 rgba
在CSS3中唯一引入的伪元素是::selection.
媒体查询,多栏布局
border-image
(1)新的语义标签和属性
(2)表单新特性
(3)视频和音频
(4)Canvas绘图
(5)SVG绘图
(6)地理定位
(7)拖放API
1.借用构造函数继承,使用call或apply方法,将父对象的构造函数绑定在子对象上
2.原型继承,将子对象的prototype指向父对象的一个实例
3.组合继承
原型链继承的缺点:
字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。
借用构造函数(类式继承):
借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。
组合式继承:
组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。
前端:1.浏览器插件2.前端代理3.SONP
后端:1.声明header头2.后端代理
运维:web服务器配置
等等
使用闭包主要是为了设置私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念
闭包有三个特性:
1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
浏览器兼容性问题,是指因为不同的浏览器对同一段代码有不同的解析,造成页面显示效果不统一的情况。
1 尽量减少HTTP请求次数
2 压缩合并js
3 css精灵
4 减少DOM元素数量
5 使用CDN(网站上静态资源即css、js全都使用cdn分发,图片亦然,因为cdn拥有众多服务器,用户请求可以请求距离他近的服务器,加快速度)
6 把CSS放到顶部,把JS放到底部
7 使用gzip压缩内容(服务端)
BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的margin会发生折叠。
1.JavaScript是一门单线程语言。
2.Event Loop(事件循环)是JavaScript的执行机制。
它属于一个预编译模块方案(模块打包工具),我们现在的前端代码开始分模块进行构建,则会用到import "./a.js"; 、require ("a.js"); 等方法。但是浏览器是不认识这样的方法。这时,webpack 就出现了,它采用预编译的方式,在代码加载到页面前,把这些模块引用的方式转换成浏览器可以识别的js代码。
1.创建环境env文件
2.修改package.json
3.vue.config.js中引用环境变量
1、使用import导入组件,可以获取到组件
2、使用import导入组件,直接将组件赋值给componet
3、使用require 导入组件,可以获取到组件
4、使用require 导入组件,直接将组件赋值给componet
1.文件夹名字不能大写。
2.两层v-for不能用index的名字来作为索引
3.合法域名校验出错,不在以下合法域名列表中
盒模型的组成,由里向外content,padding,border,margin。
盒模型有两种标准,一个是标准模型,一个是怪异盒模型。
A普通函数调用 this => window
B对象函数调用 this => 对象本身
C事件处理函数调用 this => 事件源
D定时器调用 this => window
E箭头函数中调用 this => 父function中的this 父没有function则window
F bind/apply/call this=> 用来改变this指向
区别:都用来改变this的指向,bind后函数不会执行,而只是返回一个改变了上下文的另一个函数,而call和apply是直接执行函数。若无参数,apply与call基本没什么区别
1.不一样的变量声明:const和let
2.模板字符串
3.箭头函数(Arrow Functions)
4. 函数的参数默认值
5.Spread / Rest 操作符
6.二进制和八进制字面量
7.对象和数组解构
8.对象超类
9.for...of 和 for...in
10.ES6中的类
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大,简单地说,Promise好比容器,里面存放着一些未来才会执行完毕(异步)的事件的结果,而这些结果一旦生成是无法改变的
区别:1 Promise的出现解决了传统callback函数导致的“地域回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句。
2 async await与Promise一样,是非阻塞的。
3 async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。
商业级数据图表,它是一个纯JavaScript的图标库,兼容绝大部分的浏览器,底层依赖轻量级的canvas类库ZRender,提供直观,生动,可交互,可高度个性化定制的数据可视化图表。创新的拖拽重计算、数据视图、值域漫游等特性大大增强了用户体验,赋予了用户对数据进行挖掘、整合的能力。
Echarts支持的图表:折线图(区域图)、柱状图(条状图)、散点图(气泡图)、K线图、饼图(环形图)
雷达图(填充雷达图)、和弦图、力导向布局图、地图、仪表盘、漏斗图、事件河流图等12类图表
浅拷贝 shadow copy (传地址)
仅仅只拷贝对象自身,内部元素引用的其他对象只拷贝一个引用。
深拷贝 deep copy (传值)
外围和内部元素都拷贝了对象本身。而不是引用。因此深拷贝产生的副本可以随意修改,而不用担心会影响原始值。
1,额外标签法,
CommonJS是服务器端模块的规范,Node.js采用了这个规范。CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作
事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。
事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能。
ajax(异步javascript xml) 是什么:能够刷新局部网页数据而不是重新加载整个网页。
(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象.
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
(3)设置响应HTTP请求状态变化的函数.
(4)发送HTTP请求.
(5)获取异步调用返回的数据.
(6)使用JavaScript和DOM实现局部刷新.
因为网络请求需要中间有很多的服务器路由器的转发。中间的节点都可能篡改信息,而如果使用HTTPS,密钥在你和终点站才有。https之所以比http安全,是因为他利用ssl/tls协议传输。它包含证书,卸载,流量转发,负载均衡,页面适配,浏览器适配,refer传递等。保障了传输过程的安全性
节流:一段时间内,只执行一次函数
防抖:事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时
性能角度: cookie影响性能 h5不影响性能 h5最重要
生命周期: cookie自定义 localStorage永久、sessionStorage窗口
存储空间: cookie 4k h5 5M
主要网站设置了cookie 后期所有请求都会携带cookie 影响性能
1.concat() 功能:用于连接两个或多个数组,该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
2.join() 功能:根据指定分隔符将数组中的所有元素放入一个字符串,并返回这个字符串。
3.pop() 功能:方法用于删除并返回数组的最后一个元素。
4.shift() 功能:方法用于删除并返回数组的第一个元素。
5.unshift() 功能:向数组的开头添加一个或更多元素,并返回新的长度。
6.push() 功能:向数组的末尾添加一个或更多元素,并返回新的长度。
7.slice() 功能:可从已有的数组中返回选定的元素。该方法接收两个参数slice(start,end),strat为必选,表示从第几位开始;end为可选,表示到第几位结束(不包含end位),省略表示到最后一位;start和end都可以为负数,负数时表示从最后一位开始算起,如-1表示最后一位。
8.splice() 功能:向数组中添加,或从数组删除,或替换数组中的元素,然后返回被删除/替换的元素。
参数:splice(start,num,data1,data2,...); 所有参数全部可选。
9.toString() 功能:转换成字符串,类似于没有参数的join()。该方法会在数据发生隐式类型转换时被自动调用,如果手动调用,就是直接转为字符串。
10.indexOf() 功能:根据指定的数据,从左向右,查询在数组中出现的位置,如果不存在指定的数据,返回-1。该方法是查询方法,不会对数组产生改变。
11.forEach() 功能:ES5新增方法,用来遍历数组,该方法没有返回值。forEach接收的回调函数会根据数组的每一项执行,该回调函数默认有三个参数,分别为:遍历到的数组的数据,对应的索引,数组自身。
12.map() 功能:1.同forEach功能;2.map的回调函数会将执行结果返回,最后map将所有回调函数的返回值组成新数组返回。
13.filter() 功能:1.同forEach功能;2.filter的回调函数需要返回布尔值,当为true时,将本次数组的数据返回给filter,最后filter将所有回调函数的返回值组成新数组返回(此功能可理解为“过滤”)。
一、利用ES6中的 Set 方法去重
二、使用双重for循环,再利用数组的splice方法去重(ES5常用)
三、利用数组的indexOf方法去重
四、利用数组的sort方法去重(相邻元素对比法)
五、利用ES6中的Map方法去重
六、利用数组的filter方法去重
使用上的不同+
import xxx from './'
export xxx
import {xxx} from './'
1.get传参方式是通过地址栏URL传递,是可以直接看到get传递的参数,post传参方式参数URL不可见,get把请求的数据在URL后通过?连接,通过&进行参数分割。psot将参数存放在HTTP的包体内
2.get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,URL最大长度是2048个字符。post没有长度限制
3.get后退不会有影响,post后退会重新进行提交
4.get请求可以被缓存,post不可以被缓存
5.get请求只URL编码,post支持多种编码方式
6.get请求的记录会留在历史记录中,post请求不会留在历史记录
7.get只支持ASCII字符,post没有字符类型限制
渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验。
优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。
这个配置是公司后端/运维配置的,但是我个人对编程还是比较喜欢研究的 然后呢我就自己谷歌了一把发现就是去腾讯、阿里云申请证书,然后修改nginx配置就行。我当时用的是免费版,收费版没试过。
首先通过wx.login和wx.reqeuset获取openid 然后根据API去获取用户的昵称和头像
静态资源优化:
图片懒加载
七牛云对象存储
cdn加速
expires 之前给大家发的nginx课件里面有
gzip 之前给大家发的nginx课件里面有
后端接口优化:
接口开发规范restful api
接口安全(https)
接口性能(多台数据库、缓存服务器redis存内存等)
静态资源 咱们可以分离项目 放到CDN服务器上
太大了可以讲一个小程序变成2个小程序 这样就是4M
然后通过声明式导航、编程式导航,点击直接跳转到另一个小程序即可。
.parent{
width: 500px;
height: 500px;
border: 1px solid red;
}
.child{
width: 100px;
height: 100px;
border: 1px slid #111;
}
方法一:利用定位(常用方法,推荐)
.parent{
position:relative;
}
.child{
position:absolute;
top:50%;
left:50%;
margin-top:-50px;
margin-left:-50px;
}
方法一的原理就是定位中心点是盒子的左上顶点,所以定位之后我们需要回退盒子一半的距离。
方法二:利用margin:auto;
.parent{
position:relative;
}
.child{
position:absolute;
margin:auto;
top:0;
left:0;
right:0;
bottom:0;
}
方法三:利用display:table-cell;
.parent{
display:table-cell;
vertical-align:middle;
text-align:center;
}
.child{
display:inline-block;
}
方法四:利用display:flex;设置垂直水平都居中;
.parent{
display:flex;
justify-content:center;
align-items:center;
}
方法五:计算父盒子与子盒子的空间距离(这跟方法一是一个道理);
计算方法:父盒子高度或者宽度的一半减去子盒子高度或者宽的的一半。
.child{
margin-top:200px;
margin-left:200px;
}
方法六:利用transform
.parent{
position:relative;
}
.child{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%);
}
方法七:利用calc计算
.parent{
position:relative;
}
.child{
position:absolute;
top:calc(200px);//(父元素高-子元素高)÷ 2=200px
let:calc(200px);//(父元素宽-子元素宽)÷ 2=200px
}
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法 可以很好地解决回调地狱的问题(避免了层层嵌套的回调函数) , 语法非常简洁
Promise
对象有以下两个特点。
特点1: 对象的状态不受外界影响。
解释: Promise
对象代表一个异步操作,有三种状态:pending
(进行中)、fulfilled
(已成功)和 rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无 法改变这个状态。
特点2: 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
解释:Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要 这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定 型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。
.div_text{
width: 300px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.div_moreline{
width: 300px;
display:-webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
max-height: 90px;
}
.triangle{
width: 0;
height: 0;
border: 50px solid transparent;
border-top-color: black ;
}
####vue-cli3.0兼容2.0版本
npm install -g @vue/cli-init
//1.操作数组的索引
//2.操作数组的length
//以上两种情况都不会更新视图
//原因就是因为Vue2.0底层响应式原理使用了ES5中的Object.defineProperty()这个方法,这个方法有个缺点,缺点就是无法劫持数组,数组的变化是没有办法进行响应
//操作一些数组的方法 比如push pop shift unshift reverse等方法会触发视图的更新,因为vue的底层特别对这几个方法做了hack处理,只要我们调用这些方法也会视图的更新
//Vue3.0的版本,使用的proxy这个方法,这个方法可以劫持数组,就不会出现操作索引和length不更新视图的情况了
//1.不要操作数组的length和索引,如果说硬要操作,可以使用Vue.$set(target,key,value)方法
//2.如果说操作了这些属性,不知道问题在哪里,解决不了视图不更新的情况,我们可以调用强制更新$forceUpdate()
用于区分diff算法的时候,元素的唯一性
//key的值,正常情况下一般都要给一个唯一的值,如果没有一个惟一的情况下,那么可以暂时的使用index来代替
//写项目的时候,后台返回的数据肯定有id,那么这个id就是唯一的标识所以我们一般使用id来作为key的值
trim lazy number
//v-if 都是用于控制元素/组件的显示和隐藏 值都是布尔值,如果布尔值为true那么元素就会显示,如果为false,那么元素或者组件就会隐藏 v-if元素不显示的时候,dom结构也会一并移除
//v-if可以和v-else v-else-if结合使用,如果v-if布尔值为true,那么不会展示v-else的内容,如果布尔值为false,那么就会展示v-else,而不会展示v-if,两者的关系,就是老死不相往来,互斥
//v-show 都是用于控制元素/组件的显示和隐藏 值都是布尔值,如果布尔值为true那么元素就会显示,如果为false,那么元素或者组件就会隐藏 v-show隐藏元素之后,不会移除dom结构
//使用场景:首次渲染开销较大的时候,可以使用v-if 频繁切换的时候使用v-show
//prevent 阻止默认事件
//ocne 只调用一次
//native 触发组件根元素的原生事件
//bind
//inserted
//update
//1.计算的结果会缓存
//2.根据外界响应式依赖发生变化而变化
普通监听
深度监听
字符串写法
v-for优先级别高
全局组件的创建
利用Vue.component来创建全局组件
vue.component( "vheader",{
template:
`
我是全局组件`
})
可以直接使用 ,不需要挂载
局部组件创建
(1)创建一个局部组件,举例,命名为App。
(2)利用组件的components,将App挂载上去。
(3)在页面使用 即可.
2.插槽作用域:将组件内部的数据传递给分发的内容进行渲染,再通过solt接收分发内容
举例:
03.插槽slot.html
- {{item}}
//1.如果说混入了data属性,那么会对data进行递归合并,冲突的时候,以组件的属性优先
//2.同名的钩子函数会被合并为一个数组,都会进行调用,会以混入对象的钩子函数优先调用
//3.组件选项 比如methods directives components filters...都会被合并为一个对象,冲突的时候,以组件的键值对为主
在下次dom,更新循环结束后执行延迟回调,在修改数据之后立即使用,获取更新后的dom元素
可以,在这里可以获取data,并且事件监听也添加上了,数据已经被劫持,观察者就绪,在这个钩子函数中可以修改data
created mounted
销毁定时器,解绑全部指令及事件监听,清除全局事件等
作用:缓存组件
钩子函数:activated deactivated
属性:include包含的组件会被缓存,exclude排除的组件不会被缓存
父组件beforeCreated ==》父组件created ==》父组件beforeMount ==》
子组件beforeCreated ==》子组件created ==》子组件beforeMount ==》子组件mounted ==》
父组件mounted
不会
因为$data都还没初始化,就算获得了后台数据,也不能修改data
通过js模拟真实dom的嵌套,创建新的页面的结构,就是虚拟dom,在内存中,页面是看不见的,只有添加到页面上才能看见
使用虚拟dom,可以在内存中更新结构,而不是操作真实dom一个一个更新,最大的好处提高页面渲染的性能,结合diff算法 让页面进行高效更新
Vue 的响应式原理是核心是通过 ES5 的保护对象的 Object.defindeProperty 中的访问器属性中的 get 和 set 方法,data 中声明的属性都被添加了访问器属性,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。
# 回流
1. 位置的改变 translate 定位的left top
2. 元素位置的显示和隐藏也会引起回流
3. 宽高的变化
# 重绘
1. 颜色的变化
2. 字体风格的变化
3. 背景的变化
一个项目只有一个html页面 所有的页面跳转依据于路由进行
用户体验好,切换速度快,不需要刷新整个页面
使用服务端渲染 nuxt
1. hash有#号,#号后面的url不会向后端发起请求
2. hash路由使用onhashchange监听 history使用onpopstate监听
3. history使用的是H5的api pushState replaceState
4. 当hash值相同时,不会触发hashchange,history当输入相同的路径的时候,会将浏览器中的地址当成是请求地址向后台发送请求,会造成页面404
5. abstract模式是在没有浏览器api的情况下自动启用,abstract模式在切换页面的时候,路径是不会发生变化的
6. 关键字 onhashchange pushstate replacestate popstate
7.
再path路径下,通过props:true解耦,使用,通过props:['动态参数']
其实可以直接映射在data中,只是使用的时候要加()不方便将state映射给data中的某一个属性
会造成vuex更新之后视图不更新只有computed才会根据依赖发生改变而改变
mutation
有很多种方式可以修改state,比如getters,比如直接修改,比如action中可以直接修改。但是这些修改不符合vuex的设计原则;所以规定修改state,必需通过mutation进行更改
因为如果data是一个对象则会造成数据共享,在多次使用该组件的时候,改变其中一个值会影响全部该组件的值。而如果是通过函数的形式返回出一个对象的话,在每次使用该组件时返回出的对象的地址指向是不一样的,这样子能让各个组件的数据独立。
action中发送异步请求,结果通过commit提交mutation
跨网站指令码(英语:Cross-site scripting,通常简称为:XSS)是一种网站应用程式的安全漏洞攻击,是代码注入的一种。它允许恶意使用者将程式码注入到网页上,其他使用者在观看网页时就会受到影响。这类攻击通常包含了 HTML 以及使用者端脚本语言。
XSS 分为三种:反射型,存储型和 DOM-based
XSS 通过修改 HTML 节点或者执行 JS 代码来攻击网站。
例如通过 URL 获取某些参数
<div>{{name}}div>
上述 URL 输入可能会将 HTML 改为 alert(1)
,这样页面中就凭空多了一段可执行脚本。这种攻击类型是反射型攻击,也可以说是 DOM-based 攻击。
也有另一种场景,比如写了一篇包含攻击代码 alert(1)
的文章,那么可能浏览文章的用户都会被攻击到。这种攻击类型是存储型攻击,也可以说是 DOM-based 攻击,并且这种攻击打击面更广。
最普遍的做法是转义输入输出的内容,对于引号,尖括号,斜杠进行转义
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(/\//g, '/')
return str
}
通过转义可以将攻击代码 alert(1)
变成
// -> <script>alert(1)</script>
escape('')
对于显示富文本来说,不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。这种情况通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
var xss = require('xss')
var html = xss('XSS Demo
')
// -> XSS Demo
<script>alert("xss");</script>
console.log(html)
以上示例使用了 js-xss
来实现。可以看到在输出中保留了 h1
标签且过滤了 script
标签
内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。
我们可以通过 CSP 来尽量减少 XSS 攻击。CSP 本质上也是建立白名单,规定了浏览器只能够执行特定来源的代码。
通常可以通过 HTTP Header 中的 Content-Security-Policy
来开启 CSP
只允许加载本站资源
Content-Security-Policy: default-src ‘self’
只允许加载 HTTPS 协议图片
Content-Security-Policy: img-src https://*
允许加载任何来源框架
Content-Security-Policy: child-src 'none'
更多属性可以查看 这里
跨站请求伪造(英语:Cross-site request forgery),也被称为 one-click attack 或者 session riding,通常缩写为 CSRF 或者 XSRF, 是一种挟制用户在当前已登录的 Web 应用程序上执行非本意的操作的攻击方法。[1] 跟跨網站指令碼(XSS)相比,XSS 利用的是用户对指定网站的信任,CSRF 利用的是网站对用户网页浏览器的信任。
简单点说,CSRF 就是利用用户的登录态发起恶意请求。
CSRF这种攻击方式在2000年已经被国外的安全人员提出,但在国内,直到06年才开始被关注,08年,国内外的多个大型社区和交互网站分别爆出CSRF漏洞,如:NYTimes.com(纽约时报)、Metafilter(一个大型的BLOG网站),YouTube和百度HI…而现在,互联网上的许多站点仍对此毫无防备,以至于安全业界称CSRF为“沉睡的巨人”。
假设网站中有一个通过 Get 请求提交用户评论的接口,那么攻击者就可以在钓鱼网站中加入一个图片,图片的地址就是评论接口
<img src="http://www.domain.com/xxx?comment='attack'" />
如果接口是 Post 提交的,就相对麻烦点,需要用表单来提交接口
<form action="http://www.domain.com/xxx" id="CSRF" method="post">
<input name="comment" value="attack" type="hidden" />
form>
防范 CSRF 可以遵循以下几种规则:
可以对 Cookie 设置 SameSite
属性。该属性设置 Cookie 不随着跨域请求发送,该属性可以很大程度减少 CSRF 的攻击,但是该属性目前并不是所有浏览器都兼容。
对于需要防范 CSRF 的请求,我们可以通过验证 Referer 来判断该请求是否为第三方网站发起的。
服务器下发一个随机 Token(算法不能复杂),每次发起请求时将 Token 携带上,服务器验证 Token 是否有效。
密码安全虽然大多是后端的事情,但是作为一名优秀的前端程序员也需要熟悉这方面的知识。
对于密码存储来说,必然是不能明文存储在数据库中的,否则一旦数据库泄露,会对用户造成很大的损失。并且不建议只对密码单纯通过加密算法加密,因为存在彩虹表的关系。
通常需要对密码加盐,然后进行几次不同加密算法的加密。
// 加盐也就是给原密码添加字符串,增加原密码长度
sha256(sha1(md5(salt + password + salt)))
但是加盐并不能阻止别人盗取账号,只能确保即使数据库泄露,也不会暴露用户的真实密码。一旦攻击者得到了用户的账号,可以通过暴力破解的方式破解密码。对于这种情况,通常使用验证码增加延时或者限制尝试次数的方式。并且一旦用户输入了错误的密码,也不能直接提示用户输错密码,而应该提示账号或密码错误。
render函数是什么 :
简单的说,在vue中我们使用模板HTML语法组建页面的,使用render函数我们可以用js语言来构建DOM
因为vue是虚拟DOM,所以在拿到template模板时也要转译成VNode的函数,而用render函数构建DOM,vue 就免去了转译的过程。
使用render函数描述虚拟DOM时,vue提供一个函数,这个函数是就构建虚拟DOM所需要的工具。
MVC和MVVM的区别其实并不大。都是一种设计思想。
主要就是MVC中Controller演变成MVVM中的viewModel。
MVVM主要解决了MVC中大量的DOM操作使页面渲染性能降低,加载速度变慢,影响用户体验。
当和Model频繁发生变化,开发者需要主动更新到View。
MVVM设计模式的优点
双向绑定技术,当Model变化时,View-Model会自动更新,View也会自动变化。很好的做到数据的一致性
由于控制器的功能大都移动到View上处理,大大的对控制器进行了瘦身
View的功能进一步强化,具有控制的部分功能,
若想无限增强它的功能,甚至控制器的全部功能几乎都可以迁移到各个View上
(不过这样不可取,那样View干不了属于它职责范围内的事情)。
View可以像控制器一样具有自己都View-Model
可以对View或ViewController的数据处理部分抽象出来一个函数处理model。
这样它们专职页面布局和页面跳转,它们必然更一步的简化。
MVVM设计模式的缺点
数据绑定也使得bug很难被调试。比如你看到页面异常了,有可能是你的View的代码有bug,也可能是你的model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。
数据双向绑定不利于代码重用。客户端开发最常用的是View,但是数据双向绑定技术,让你在一个View都绑定了一个model,不同的模块model都不同。那就不能简单重用view了
一个大的模块中model也会很大,虽然使用方便了也很容易保证数据的一致性,但是长期持有,不释放内存就造成话费更多的内存。
const声明的是常量,必须赋值
1)一旦声明必须赋值,不能使用null占位。
2)声明后不能再修改
3)如果声明的是复合类型数据,可以修改其属性
let和var声明的是变量,声明之后可以更改,声明时可以不赋值
var允许重复声明变量,后一个变量会覆盖前一个变量。
let和const在同一作用域不允许重复声明变量,会报错。
var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报ReferenceError错。
var:只有全局作用域和函数作用域概念,没有块级作用域的概念。但是会把{}内也假称为块作用域。
let const:只有块级作用域的概念 ,由 { } 包括起来,if语句和for语句里面的{ }也属于块级作用域。
ES5中作用域有:全局作用域、函数作用域。没有块作用域的概念。
ES6(简称ES6)中新增了块级作用域。块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
ES6明确规定:如果区块中存在let命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
所以在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
参考组件使用v-model流程
input元素
// $event.target.value
就是把input的值赋值给 a
对于非input元素
如果在自定义组件中,v-model
默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:
父组件:
子组件:
{{value}}
props:{ value: String },
methods: {
test1(){
this.$emit('input', '小红')
},
},
,