vuex
vuex是vue的状态管理模式。采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理模式包含state,驱动应用的数据源; view 以声明的方式将state映射到视图; actions,响应在view上的用户输入导致的状态变化。
核心是store,vuex的存储状态时响应式的。所有从store实例中获取状态最简单的方式就是在计算属性中返回某个状态
state用来数据共享数据存储
mutation用来改变数据状态,只能包含同步的代码, 不能写异步代码
getters用来对共享数据进行处理
action解决异步改变共享数据
store
mapState辅助函数
对象展开运算符
computed: {
localComputed () { /* ... */ },
//使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
getter
有时候我们需要从store中的state派生出新的状态
getter的返回值会根据它的依赖被缓存起来,只有当它的依赖值发生了变化才会被重新计算
getter接受state作为第一个参数,getter可以作为第二个参数
mapGetters辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
Mutation(映射在method)
改变state的唯一方法就是提交mutation,每个mutation都有一个字符串的事件类型和一个回调函数
你可以向store.commit传入额外的参数,即 mutation 的 载荷(payload)
Mutation需遵守 Vue 的响应规则
既然Vuex的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:
最好提前在你的store中初始化好所有所需属性。
当需要在对象上添加新属性时,你应该
使用Vue.set(obj, 'newProp', 123),或者
以新对象替换老对象。例如,利用对象展开运算符我们可以这样写:
state.obj = { ...state.obj, newProp: 123 }
Action
Action函数接受一个与 store 实例具有相同方法和属性的 context 对象,但是context 对象不是 store 实例本身了,
actions: {
increment ({ commit }) {
commit('increment')
}
}
Action通过 store.dispatch 方法触发
store.dispatch可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch 仍旧返回 Promise
Module
将store分割成模块,每个模块拥有自己的 state、mutation、action、getter。
对于模块内部的mutation和 getter,接收的第一个参数是模块的局部状态对象。
对于模块内部的action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState
从输入URL到页面展示,这中间发生了什么?
这个过程可以大致描述为如下:
1、URI 解析
2、DNS 解析(DNS 服务器)
3、TCP 三次握手(建立客户端和服务器端的连接通道)
4、发送 HTTP 请求
5、服务器处理和响应
6、TCP 四次挥手(关闭客户端和服务器端的连接)
7、浏览器解析和渲染
8、页面加载完成
https://juejin.im/post/5f0415fff265da22bb7b232d
Map对象
https://juejin.im/post/5f03408d5188252e397ed503
不同
键名类型
JavaScript 「Object」只接收两种类型的键名String 和 Symbol,你可以使用其他类型的键名,但是最终JavaScript 都会隐式转换为字符串
原型Prototype
「Object」不同于「Map」,它不仅仅是表面所看到的。「Map」只包含你所定义的键值对,但是「Object」对象具有其原型中的一些内置属性
迭代器
「Map」 是可迭代的,可以直接进行迭代,例如forEach循环或者for...of...循环
但是对于「Object」是不能直接迭代的,当你尝试迭代将导致报错
元素顺序和长度
「Map」可以直接通过size获取,「Object」需要运用方法来实现。
「Map」始终保持按插入顺序返回键名。但「Object」却不是。从ES6 开始,String和Symbol键是按顺序保存起来的,但是通过隐式转换保存成String的键就是乱序的
Object/Map 应用场景
如上就是「Map」和「Object」的基本区别,在解决问题考虑两者的时候就需要考虑两者的区别。
[if !supportLists]o [endif]当插入顺序是你解决问题时需要考虑的,并且当前需要使用除String和Symbol以外的键名时,那么「Map」就是个最佳解决方案
[if !supportLists]o [endif]如果需要遍历键值对(并且需要考虑顺序),那我觉得还是需要优先考虑「Map」。
[if !supportLists]o [endif]「Map」是一个纯哈希结构,而「Object」不是(它拥有自己的内部逻辑)。Map在频繁增删键值对的场景下表现更好,性能更高。因此当你需要频繁操作数据的时候也可以优先考虑Map
[if !supportLists]o [endif]再举一个实际的例子,比如有一个自定义字段的用户操作功能,用户可以通过表单自定义字段,那么这时候最好是使用Map,因为很有可能会破坏原有的对象
「Object」对象通常可以很好的保存结构化数据,但是也有相应的局限性:
[if !supportLists]1. [endif]键名接受类型只能用String或者Symbol
[if !supportLists]2. [endif]自定义的键名容易与原型继承的属性键名冲突(例如toString,constructor等)
[if !supportLists]3. [endif]对象/正则无法用作键名 而这些问题通过「Map」都可以解决,并且提供了诸如迭代器和易于进行大小查找之类的好处
不要将「Map」作为普通「Object」的替代品,而应该是普通对象的补充
块状作用域
JS的作用域有:全局作用域、函数作用域,es6新增了块级作用域。
块级作用域由{}包括。If和for语句里面的{}也属于块状作用域
ES6没有块级作用域的情况会出现的问题:
[if !supportLists]1、[endif]在if和for循环中声明的变量会泄露成全局变量
[if !supportLists]2、[endif]内部变量存在变量提升会覆盖外部变量
https://www.cnblogs.com/moumoon/p/10985250.html
普通函数与箭头函数的区别
普通函数中的this总是指向调用它的那个对象;箭头函数没有自己的this,它的this永远指向其定义环境,任何方法都改变不了其this执行
箭头函数不能当作构造函数,不能使用new命令。
箭头函数不能使用yield命令,因此箭头函数不能用作genertor函数。
箭头函数没有原型属性。
箭头函数不能使用argumen对象,可以使用...rest函数代替
变量提升:由于js的内存机制,function的级别最高,而用箭头函数定义函数的时候,需要var(let、const)关键字,而用var所定义的变量不能得到变量提升。箭头函数一定要定义于调用之前。
防抖节流
防抖
触发事件后n秒后才执行函数,如果在n秒内触发了函数,将重新计算执行时间
防抖分为立即执行版和非立即执行版。
非立即执行版的意思是触发事件后函数不会立即执行,而是在n 秒后执行,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
立即执行版的意思是触发事件后函数会立即执行,然后n 秒内不触发事件才能继续执行函数的效果。
节流
就是之连续触发事件但是在n秒中只执行一次
对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版
https://juejin.im/post/5b651dc15188251aa30c8669
场景
https://www.codercto.com/a/25782.html
对this、call、apply和bind的理解
[if !supportLists]1、[endif]在浏览器里,在全局范围内this指向window对象;
[if !supportLists]2、[endif]在函数中,this永远指向最后调用它的那个对象;
[if !supportLists]3、[endif]构造函数中,this指向new出来的那个新的对象;
[if !supportLists]4、[endif]Call、apply、bind中的this被强绑定在指定的那个对象上;
[if !supportLists]5、[endif]箭头函数中的this比较特殊,箭头函数this为父作用域的this,不是调用时的this,箭头函数的this指向是静态的,声明的时候就确定下来了。
原型、原型链
我们创建的每一个函数都有一个prototype属性,这个属性就是一个指针,指向一个对象。这个对象包含由特定类型的所有实例共享的属性和方法,简单来说,该函数实例化的所有对象的_proto_的属性指向这个对象,它是该函数所有实例化对象的原型。
Constructor 属性
当函数创建的时候,prototype属性指向一个原型对象时,在默认情况下,这个原型对象将会获得一个constructor属性,这个属性是一个指针,指向prototype所在的函数对象。
isPrototypeOf() 方法用于测试一个对象是否存在于另一个对象的原型链上。
原型链主要实现方法是让构造函数的prototype对象等于另一个类型的实例,此时的prototype对象因为是实例,因此将包含一个指向另一个原型的指针,响应的另一个原型也包含着一个指向另一个构造函数的指针。例如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条,这就是原型链的基本概念。
获取原型的方法:
P.proto p.constructor.prototype Object.getPrototypeOf(p)
闭包
闭包是指有权访问另一个函数作用域内变量的函数
创建闭包最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。
用途:
[if !supportLists]1、[endif]闭包的用途是使我们在函数外部可以访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以用来创建私有变量。
[if !supportLists]2、[endif]函数的另一个用途可以让已经运行结束的函数上下文中的变量对象继续留着内存中,因为闭包函数保留了这个变量对象的引用,不会被回收
事件委托
利用了浏览器事件冒泡的机制。因为事件在冒泡过程中会上传到父节点,并且父节点可以通过事件对象获取到目标节点,因为可以把子节点的监听函数定义在父节点上,由父节点的监听函数统一处理多个子元素的事件,这种方式称为事件代理。
事件传播
三个阶段:
[if !supportLists]1、[endif]捕获阶段-事件从window开始,然后从下到每个元素,直到到达目标元素事件或者enent。Target
[if !supportLists]2、[endif]目标阶段-事件已到达目标元素
[if !supportLists]3、[endif]冒泡阶段-事件从目标元素冒泡,然后上升到每个元素,直到window。
事件捕获
当事件发生在dom元素上时,该事件饼不完全发生在那个元素上。捕获阶段,事件从window开始,一直到触发事件的元素。Window-document-html-body-目标元素。
事件冒泡
事件冒泡刚好与事件捕获相反,当前元素---->body ----> html---->document ---->window。当事件发生在DOM元素上时,该事件并不完全发生在那个元素上。在冒泡阶段,事件冒泡,或者事件发生在它的父代,祖父母,祖父母的父代,直到到达window为止。
var、let和const区别?
[if !supportLists]1、[endif]Var声明的变量会挂载在window上,会存在变量提升;
[if !supportLists]2、[endif]Let和const声明形成块作用域;
[if !supportLists]3、[endif]同一个作用域下的let和const不能声明不同名变量,而var可以;
网友评论