
Vuex是vue官方的一款状态管理工具,什么是状态呢?我们在前端开发中有一个概念:数据驱动,页面中任意的显示不同,都应该有一条数据来控制,而这条数据又叫做state,状态。
在vue中。组件间进行数据传递、通信很频繁,而父子组件和非父子组件的通信功能也比较完善,但是,唯一困难的就是多组件间的数据共享,这个问题由vuex来处理
vue提供的一个全局的状态管理工具,主要处理项目中多组件间状态共享
因为在组件中可以通过this storestate来使用state中管理的数据
但是我们发现,这样使用的话,当state的数据更改的时候,vue组件并不会重新渲染
也就是说,如果想要在组件中响应式的使用的时候,我们需要通过计算属性(computed)来使用
这样的写法很无趣,而且如果使用的状态较多会产生冗余的感觉,所以vuex提供了mapState辅助函数,帮助我们在组件中获取并使用vuex的store中保存的状态
所以我们可以这样写:
但是如果组件中已经有了num这个数据了,而state中的数据名字也叫num就会照成冲突,这个时候我们可以在组件使用state的时候,给状态起个别名:
但是,有的时候我们在组件中还有自己的业务逻辑需要用到计算属性:
有的时候,我们需要根据state中的某一个状态派生出一个新的状态,例如,我们state中有一个num,在某些组件中需要用到是num的二倍的一个状态,我们就可以通过getters来创建
创建了之后,在组件中通过this$storegettersdoubleNum来获取里面的数据
当然vuex也提供了mapGetters辅助函数来帮助我们在组件中使用getters里的状态,且,使用的方法和mapState一模一样
我们不能直接在组件中更改state:this$storestatenum=2,而是需要使用mutations来更改,mutations也是一个纯对象,里面包含很多更改state 的方法,这些方法的形参接收到state,在函数体里更改,这时,组件用到的数据也会更改,实现响应式。
但是我们也不能直接调用mutations 的方法,需要使用this$storecommit来调用,第一个参数为调用的方法名,第二げ参数为传递参数
vuex提供了mapMutations方法来帮助我们在组件中调用mutations 的方法,使用方法和mapState、mapGetters一样
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步 *** 作。
也就是说,如果有这样的需求:在一个异步处理之后,更改状态,我们在组件中应该先调用actions,来进行异步动作,然后由actions调用mutation来更改数据
如上,actions的方法中可以进行异步的动作,且形参会接收store,从中取出commit方法用以调用mutations的方法
在组件中通过this$storedispatch方法调用actions的方法
当然也可以使用mapMutations来辅助使用
组件使用数据且通过异步动作更改数据的一系列事情:
1生成store,设置state
2在根实例中注入store
3组件通过计算属性或者mapState来使用状态
4用户产生 *** 作,调用actions的方法,然后进行异步动作
5异步动作之后,通过commit调用mutations的方法
6mutations方法被调用后,更改state
7state中的数据更新之后,计算属性重新执行来更改在页面中使用的状态
8组件状态被更改创建新的虚拟dom
9组件的模板更新之后重新渲染在dom中
vuex的使用:
目前市场上有两种使用vuex的情况,
第一种:将需要共享、需要管理的状态放入vuex中管理,也就是说在必要时使用
第二种:将所有的数据都交由vuex管理,由vuex来承担更多的责任,组件变得更轻量级,视图层更轻
在实现回到顶部功能的时候,我们写了一个backTop组件,接下来需要通过监听windowscroll事件来控制这个组件显示隐藏
写了一个v-back-top指令,就是将回到顶部功能做成一个指令,哪个组件或者dom需要使用到回到顶部,就加上这个指令就可以,设置不同的参数来控制在不同的情况下触发
组件库就是通用组件的集合
pc:element-ui iview
mobile: mint-ui
当我们在使用一些插件的时候,经常需要在dom更新完成后进行必要 *** 作,但是在vue中提供的api只有updated钩子函数,而在这个函数里,任意数据的变化导致的dom更新完成都会触发,所以很可能会造成无关数据的影响,而使用监听的话只能监听到数据的变化,此时dom还没有更新,我们只能强行使用setTimeout来处理
这里推荐大家使用nextTick全局方法:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
v-for='n in 10' n会打印1-10
通用:beforeCreate/created/beforeMount/mounted/beforeUpdate/updated/beforeDestroy/destroyed
路由守卫:beforeRouteEnter/beforeRouteUpdate (22 新增)/beforeRouteLeave
v-if是真正的条件渲染,会确保在切换中条件块内的事件监听、子组件都会适当的被销毁和重建
v-show总是将节点渲染在dom中,只是基于css:display来控制节点的显示和隐藏
v-if有更高的切换开始,v-show有更高的初始渲染开销
v-if是惰性的,初始条件为假,就不会渲染
axios请求的时候不会带上cookie,不会影响带宽,可以通过withCredentials:true来设置
对axios 的请求头进行设置:
axiosdefaultsheaders = {'Content-Type':''}
vue20不在更新维护vue-resource,官方推荐使用axios
6为了让组件可以组合,我们需要一种方式来混合父组件的内容与子组件自己的模板。这个过程被称为内容分发 (即 Angular 用户熟知的“transclusion”)。Vuejs 实现了一个内容分发 API,参照了当前 Web Components 规范草案,使用特殊的 <slot> 元素作为原始内容的插槽。
全局:Vuecomponent(name,Vueextend({}))
局部:{ components:{name:Vueextend({})} }
假设我们有一个数据为num,还希望拥有一个数据为doublenum,而且希望doublenum的值永远都是num的二倍
方法:
prop是单向绑定的,父组件属性变化,传递给子组件,但是,子组件数据变化,不能直接传递给父组件,也就是数据的流行是从父组件流向子组件的,为了防止子组件修改父组件的数据(会让应用的数据流变的更难开发、更新、维护)
使用了vuex工具的时候,store中数据在组件中使用的过程也是单向数据流,state->vue component->actions->mutations->state->vue component
当数据改变之后,vue会创建新的虚拟dom来和原来的虚拟dom做对比,在创建新的虚拟的dom的时候,会根据key来查找在原来的虚拟dom中有没有某个部分,如果原来的有,这次的也需要,就会实现复用,而且在做diff对比的时候,如果有key会加快对比的查找速度,提高性能
尽量循环的时候不要将key设置为数组的索引,因为当删除某一个元素的时候,就会导致删除位置下面的所有元素的key值都与上一次虚拟dom的key值不同,导致复用失败,这个时候我们最好使用关键的唯一的,例如id这样的数据作为key
如果数据变化只是值的变化而不是条数和位置的变化,可以使用索引作为key
Vueuse会查找插件对象里的install方法去执行,并且给install方法里传入Vue对象
很多情况下,一个应用会有PC和移动端两个版本,而这两个版本因为差别大,内容多,所以不能用响应式开发但是单独开发,而域名只有一个,用户进入域后直接返回对应设备的应用,做法主要有两种:
每个 Vue 应用都是通过用 Vue 函数创建一个新的 Vue 实例开始的。
Vue 实例使用的根 DOM 元素。
当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
获取定义在data外的数据和方法。
当前实例的直接子组件。
获取被插槽分发的内容。
获取具名插槽。
获取注册过refs的所有DOM元素和组件实例。
Vue是否运行于服务端。
主动销毁该实例。
挂载DOM。
观察 Vue 实例上的一个表达式或者一个函数计算结果的变化。回调函数得到的参数为新值和旧值。
迫使 Vue 实例重新渲染。注意它仅仅影响实例本身和插入插槽内容的子组件,而不是所有子组件。
使回调函数在 DOM 更新完成后被调用。
Vue 在更新 DOM 时是异步执行的。只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM *** 作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
为了在数据变化之后等待 Vue 完成更新 DOM,可以在数据变化之后立即使用 VuenextTick(callback)。这样回调函数将在 DOM 更新完成后被调用。
实例被创建之前执行。在生命周期过程中只执行一次。
实例创建完成之后执行。在生命周期过程中只执行一次。
挂载组件之前(如果有挂载组件的 *** 作)。在生命周期过程中只执行一次。
组件挂载之后。在生命周期过程中只执行一次。
组件更新前。
组件更新完成。
组件销毁前。
组件被销毁。
computed是计算属性(通过其他变量计算得来的另一个属性),在相关响应式依赖发生变化时它们才会重新求值。
watch是侦听器,来响应数据的变化,当需要在数据变化时执行异步或开销较大的 *** 作时,这个方式最有用。
computed和watch都不要去改变自己监听的属性,而是要去生成一个新的值,否则会触发无限循环。
v-if=false生效时会使节点不存在在DOM流中,会动态增删节点,比较耗能;
v-show只是在节点上加上display:none。
v-if可配合v-else-if、v-else使用。
v-for的优先级高于v-if,所以在两者同时使用时,v-if会作用于每一个v-for循环上。
继承的组件的prop需要通过propsData传入,data可以直接改变。
需求:有一些内容,是在调用组件时根据场景去写的。
父组件使用子组件时:
<slot></slot>的内容将被123代替。
父组件使用子组件时:
注意:一个不带 name 的 <slot> 出口会带有隐含的名字“default”。
需求:插槽内容能够访问子组件中才有的数据。
子组件:
父组件中使用:
一、vue20的双向绑定是怎么实现的
2、observer,compile,watcher
(1)observe是一个数据监听器,核心方法是ObjectdefineProperty
(3)compile是一个指令解析器,对需要监听的节点和属性进行扫描和解析。
3、此模式的优点:不需要显式调用,可以直接通知变化,更新视图;劫持了属性setter,不需要额外的diff *** 作
4、ObjectdefineProperty缺点
(1)不能监听数组
(2)不能监听整个对象,只能监听属性
(3)不能监听属性的增删,只能监听变化
5、30版本使用Proxy
(1)可以监听数组
(2)可直接监听整个对象,不用层层递归属性
(3)get和set时候直接有参数,不需要单独存储变量
(4)new Proxy()会返回一个新对象,不会污染源对象。
二、数据不更新的问题
1、更新的原理:在数据读取时收集依赖,在赋值时通知依赖更新。
2、object有defineProperty方法,通过getter,setter只监听了属性的读取和赋值,但是新增属性和删除属性没有检测,所以专门提供了$set和$delete来实现
3、array,没有defineProperty方法,没有setter,通过get和新建数组方法拦截器修改原生方法push,pop,shift,unshift,splice,sort,reserve来实现监听,而通过修改数组下标 *** 作数组的不会被检测,所以专门提供了$set和$delete来实现
4、$set(target, key, value)和$delete(target, propertyName/index)方法原理
(1)判断target是否是undefined,null,或者原始类型,或者vue实例,或者vue实例的跟数据对象
(2)target为数组,则还是通过调用splice *** 作索引更新数据
(3)target为对象,且为响应式,则调用defineReactive *** 作数据
(4)更新完数据后通知依赖更新
三、computed和watch和methods
1、computed
(1)设计初衷:为了使模板中的逻辑运算更简单
(2)适用于数据被重复使用或者计算复杂费时的场景;依赖其他数据的场景
(3)读取缓存,依赖不变,则不需重新计算。(根据dirty标志判断)
2、watch是对数据的监听回调
3、computed和watch的区别
相同点:都会观察页面的数据变化
不同点:(1)computed是读取缓存,watch每次都要重新执行;
(2)watch更适合数据变化时的异步 *** 作和开销较大的 *** 作。
4、computed和methods的区别
computed依赖缓存,可以定义getter和setter,但是methods不行
四、vue-router的模式区别
1、abstract:非浏览器环境下使用
2、hash:
(1)默认。监听hashchange实现。
(2)有点,兼容性好,ie8支持
(3)缺点:看起来奇怪
3、history:
(1)h5新增的。允许开发者直接修改前端路由而不重新触发请求页面
(2)实现原理:监听popstate事件。能监听到用户点击浏览器的前进后退事件或者手动调用go,back,forward事件;不能监听到pushState和replaceState事件。
(3)为了避免浏览器刷新出现的404页面,需要在服务端配置兼容。
(4)如果浏览器不支持,会降级到hash模式
通过vueuse插件机制和vuemixin将store在beforeCreate和destroyed生命周期进行混入。
五、vuex解决了什么问题
1、vuex解决了vue项目中的数据状态管理问题
2、是组件通信的一种方式。
3、原理:创建了单一的状态树,包含state,mutation,action,getter,module。
4、view(dispatch)action(commit)mutation(mutate)state(render)view
5、通过vue的data和computed,让state变成响应式,
6、通过vueuse插件机制和vuemixin将store在beforeCreate生命周期进行混入。
六、nextTick是怎么是实现的
1、作用:将回调延迟到下次DOM更新循环之后执行
2、原因:VUE在更新DOM时是异步的,vue检测到数据变化后,不会立即更新DOM,而是会开启一个事件队列,并缓冲同一时间循环中的所有数据变更,在下一次tick中,执行更新DOM。
3、js的运行机制:js是单线程的,基于事件循环,有宏任务和微任务。
4、内部原理:
(1)能力检测:Promisethen(微), MutationObserve(微),setImmediate(微),setTimeout(宏)
(2)将回调函数推入回调队列,锁上易步锁,执行回调。
七、keep-alive内置组件和LRU算法(队列)
1、自身不会渲染成DOM,没有常规的 标签,是个函数组件,被他包裹的组件,切换时会被缓存在内存中,而不是销毁。
(1)可以有条件的缓存:include(匹配到的缓存),exclude(匹配到的不缓存),max(最多可以缓存多少组件实例)
2、原理:内部维护了thiscache(缓存的组件对象)和thiskeys(thiscache中的key),运用LRU策略。
(1)命中了缓存的组件要调整组件key的顺序。
(2)缓存的组件数量如果超过thismax时,要删除第一个缓存组件。
(3)LRU(Least recently used,最近最少使用):根据数据的 历史 访问记录来进行淘汰数据。“如果数据最近被访问过,那么将来被访问的几率也更高。”
3、生命周期钩子:activated和deactivated,被keep-alive包括的组件激活和停用时调用。先停用组件的deactivated,再激活组件的activated
1vuex的优缺点
2vuex的使用
先上目录结构:
项目中想要管理的数据和状态都在这
连接actions和mutations的桥梁( *** 作数据的指令)
处理数据, *** 作状态,获取数据都在这,同步去处理数据对应的调用方法 commit
要改变数据时直接用this$storecommit(SET_LOGIN_MSG, loginMsg)即可
对于一些接口数据,可能需要在组件内异步得去处理一些事情,这时候就需要写在这里,对应的调用方法是dispatch,需要注意的是:它提交的是mutation,不做数据和状态的更改,这些 *** 作在mutations中处理
这里的参数 context 是对象{commit, state},后一个参数是你需要传的数据
对应的在组件内调用方法
由于是异步得所有可以用promise封装使用,解决callhack
以上方法就可以完成vuex的整个状态管理了,完全没有任何问题。但有时候会有一些需求,比如变量name需要在firstName和lastName其中任何一个发生变化时同时发生变化,如果在组件内我们使用computed就能做到,在vuex需要我们的getters登场
Module
到这就完了吗?并没有。如果是大型项目,你会发现需要使用vuex的数据太多了,然而把所有的数据处理全部放在 mutationsjs文件中显得很杂乱,并不利于查找与管理,此时我们就需要Module,分模块管理。怎么做呢?
mod1和mod2就是 被分成的两个子模块。因为每个子模块数据和状态不会太多,因此我们把state,mutations,actions,getter写在一个文件中如下
mod1js
mod2js也是如此
那么如何调用呢?
更新数据的方法会有所变化吗?依然按照原来的方法使用就行了
总结:
将store进行拆分,有利于我们更好的管理项目中的状态,以及使我们的项目维护更加加单高效。各个模块之间的开发互相不影响。
3vuex的注意点
a在以往我们更新数据时为了防止数据随时变化所以会在更新组件时及时更新数据,甚至每隔一段时间更新数据,有了vuex就无需这么做了,我们只要在我们更改数据时更新一下数据即可。如用户的基本信息,我们只在用户对用户信息进行修改或增加时更新即可,这样在任何组件中使用用户信息时数据都是最新的。
b使用vuex我们在组件内更改数据是无效的。例如:this$storestatename=‘小明‘,这么做会报错。
打开终端,输入vue ui,会自动打开vue-cli 图像化界面
选择项目,添加ECharts 插件
我使用的是Echarts(不是vue-echarts)
主要是导入方式和50以下版本有差异,需要使用下面的方式
demo
说实话,阅读文档并不是我们大多数人喜欢的事情,但是当使用像Vue这样不断发展的现代前端框架时,每一个新版本都会有所变化,我们很有可爱已经错过了一些后来推出的新且好用的功能。
今天,刷碗智带大家来看看那些有趣但不那么流行的功能。记住,所有这些都是官方Vue文档的一部分。
在大型项目中,我们可能需要将组件分成小块,只有在需要时才从服务器上加载。为了更容易做到这一点,Vue允许我们将组件定义为一个工厂函数,异步地解析组件定义。Vue只会在组件需要渲染的时候触发工厂函数,并把结果缓存起来以备后面的重新渲染。23版的新内容是,异步组件工厂还可以返回以下格式的对象。
使用这种方法,我们有额外的选项,包括加载和错误状态、组件获取的延迟和超时。
渲染普通的 HTML 元素在 Vue 中是非常快速的,但有的时候你可能有一个组件,这个组件包含了大量静态内容。在这种情况下,我们可以在根元素上添加 v-once attribute 以确保这些内容只计算一次然后缓存起来,就像这样:
组件是可以在它们自己的模板中调用自身的。不过它们只能通过 name 选项来做这件事:
当你使用 Vuecomponent 全局注册一个组件时,这个全局的 ID 会自动设置为该组件的 name 选项。
稍有不慎,递归组件就可能导致无限循环:
类似上述的组件将会导致 “max stack size exceeded” 错误,所以请确保递归调用是条件性的 (例如使用一个最终会得到 false 的 v-if )。
当 inline-template 这个特殊的 attribute 出现在一个子组件上时,这个组件将会使用其里面的内容作为模板,而不是将其作为被分发的内容。这使得模板的撰写工作更加灵活。
内联模板需要定义在 Vue 所属的 DOM 元素内。
指令的参数可以是动态的。例如,在 v-mydirective:[argument]="value" 中, argument 参数可以根据组件实例数据进行更新!这使得自定义指令可以在应用中被灵活使用。
例如你想要创建一个自定义指令,用来通过固定布局将元素固定在页面上。我们可以像这样创建一个通过指令值来更新竖直位置像素值的自定义指令:
对于 passive 、 capture 和 once 这些事件修饰符,Vue 提供了相应的前缀可以用于 on:
修饰符前缀 passive& capture! once~ captureonce 或oncecapture~!
例如:
对于所有其它的修饰符,私有前缀都不是必须的,因为你可以在事件处理函数中使用事件方法:
修饰符处理函数中的等价 *** 作 stopeventstopPropagation() preventeventpreventDefault() selfif (eventtarget !== eventcurrentTarget) return 按键:enter, 13if (eventkeyCode !== 13) return (对于别的按键修饰符来说,可将 13 改为另一个按键码) 修饰键:ctrl, alt, shift, metaif (!eventctrlKey) return (将 ctrlKey 分别修改为 altKey、shiftKey 或者 metaKey)
在Vue中,有几种方法可以让两个组件进行通信,所有这些方法都有优点和缺点。 22 版本中引入的一种新方法是使用 Provide/Inject 的依赖注入。
这对选项一起使用,允许一个祖先组件作为其所有后代的依赖注入器,无论组件层次有多深,只要它们在同一个父链上。如果你熟悉React,这与React的上下文功能非常相似。
今天就到这了,就这?
~完,我是刷碗智,疫情只能在家 LoL 了。
以上就是关于vue第八节全部的内容,包括:vue第八节、Vue知识点整理、vue原理相关总结等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)