vue的一些心得总结
1:状态管理和使用场景(vuex):
vuex所解决的问题与bus类似,它作为Vue的一个插件使用,可以更好的管理和维护整个项目的组件状态。
在实际的业务逻辑中,经常有跨组件共享数据的需要,因此Vuex的设计就是用来更好的管理统一管理组件状
态的。它定义了一系列规范来使用和操作数据,使组件应用更加高效。
1.1: Vuex的基本使用? 1.1.1: 首先通过NPM进行安装: npm install --save vuex 1.1.2: 在main.jsl文件里,通过Vuer.use()使用Vuex import Vuex from 'vuex' import createrLogger from 'vuex/dist/logger' const debug = process.env.NODE_ENV !== 'production' Vue.use(Vuex) 1.1.3: 进行路由配置 const store = new Vuex.Store({ // vuex的配置 state: { count: 0, list: [1, 5, 8, 10, 30, 50] }, mutations: { increment (state) { state.count++; }, decrease (state, n = 1) { // n= n || 1 state.count -= n; }, ceshiTypeFunc (state, params) { state.count += params.count; } }, actions: { increase (context) { context.commit('increase'); }, asyncIncreasement(xontext) { return new Promise((resolve, reject) => { this.$nextTick(() => { contect.commit('increase'); resolve(); }) }) } } getters: { filterList: state => { return state.list.filter(item => item< 10); }, listCount: (state, getters, rootState) => { // rootState.count 来访问根节点的状态。 return getters.filterList .length; } }, plungins: debug ? [crateLogger()] : []; }); 仓库store包含了应用的数据(状态)和操作过程。Vuex里面的数据都是响应式的,在任何组件使用同一store的数据 时候,只要store的数据变化的时候,对应的组件也会立即更新。 在任何组件中,可以直接通过$store.state.count读取。(模板),直接写在template中会显得会很乱, 可以使用一个 计算属性来进行显示: export default { computed: { count() { return this.$store.state.count; }, list() { return this.$store.state.list.filter(item => item < 10); }, listTwo() { return this.$store.getters.filterList; }, listCount() { return this.$store.getters.listCount; } } } 1.1.4: 状态值更改? 在组件中,来自store的数据只能进行读取,不能手动更改, 改变store中的数据的时候唯一途径是使用显示的提交 mutations(mutations是Vuex的第二个选项, 用来直接修改state里的数据). 在组件中使用this.$store.commit方法来进行执行mutations中的方法的(例如点击事件) methods: { handIncrease () { this.$store.commit('increase'); }, handDecrease () { this.$store.commit('decrease'); }, handCeshiFunc () { this.$store.commit({ type: 'ceshiTypeFunc ', count: 10 }); }, handActionIncrease() { this.$store.dispatch('increase'); }, handAsyncIncreasement() { this.$store.dispatch('asyncIncreasement ').then(() => { console.log(this.$store.state.count); }) } } 这样看起来就像Javascript的观察者模式,组件只负责提交一个事件名, Vuex对应的mutations来完成业务逻辑。 mutation还可以接受第二个参数, 可以是数字、字符串或者对象等。 注意,mutation里尽量不要使用异步操作数据, 如果异步操作数据,组件在commit后,数据不会立即更新,而且不知 道什么时候改变。 1.1.5: 高级用法? Vuex还有其他3个选项可以使用: getters、actions、modules. getters: 如果只是想得到小于10的数据, 最容易想到的是通过计算属性进行过滤,这样写是没有问题的,但是如果是 其他组件也要使用过滤后的数据的时候,就得吧computed的代码完全复制一份了,而且当需要修改过滤方法 的时候,每个用到的组件都需要进行修改,这明显不好, 所可以使用getters. 注意: getters也可以依赖其他的getters,把getters作为第二个参数。 actions: actions与mutation很像,不同的是action里面提交的是mutations,并且可以异步操作业务逻辑。 action在组建内通过$store.dispatch触发。 modules: module将store分割到不同的模块,当你的项目足够大的时候,store里的state、getters、mutations、 actions会分厂多,放再main.js里面显得不是很友好,使用modules可以将它们写到不同的文件里面,每个 modules都拥有自己的state、getters、mutations、actions,而且可以多层嵌套。 const modulesA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const modulesB = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const store = new Vuex.Store({ modules: { a: modulesA, b: modulesB } }) 1.1.6: 比较? mutations、actions看起来很相似,可能会觉得不知道哪个, 但是Vuex很像是一种与开发者的约定,所以涉及 改变数据的,就使用mutations,存在业务逻辑的就用actions.至于将业务逻辑放在你action里还是Vue组件里完 成的根据实际的业务逻辑拿捏。 1.2: 辅助函数? Vuex除了提供我们Store对象之外,还对外提供了一系列的辅助函数,方便我们在代码中使用Vuex,提供了操作store 的各种属性的一系列的语法糖。 1.2.1: mapState mapState工具函数会将store中的state映射到局部计算中,为了更好的理解它的实现。
前:(对象)
import { mapState } from 'vuex'
export default {
computed: mapState({ count: state => state.count, // 传入字符串‘count’ 等同于`state => state.count` countAlia: 'count', // 想要访问局部状态,就必须借助于一个普通函数,函数中使用`this`获取局部状态。 countPlusLocalState (state) { return state.count + this.localCount; } })
}
经过mapStore函数调用之后的结果:
import {mapState} from 'vuex'
export default {
computed: { count() { return this.$store.state.count; }, countAlia () { return this.$store.state['count']; }, countPlusLocalState () { return this.$store.state.count + this.localCount } }
前:(数组)
import { mapState } from 'vuex'
export default {
computed: mapState([ 'count' ])
}
经过mapStore函数调用之后的结果:
import {mapState} from 'vuex'
export default {
computed: { count() { return this.$store.state['count']; } }
当计算属性名称和状态子树名称对应相等的时候,我们可以向,mapState工具函数中传入一个字符串数组。
computed: mapState({
// 映射this.count 到 this.$store.state.count 'count'
});
通过例子可以明显看出来mapState函数可以接受一个对象,也可以接受一个数组。 1.2.2: mapGetters mapGetters工具函数将store中的getters映射到局部计算属性属性中,它的功能和mapsState非常类似
前(数组)
import { mapGetters } from 'vuex'
export default {
computed: { ...mapGetters([ 'doneTodoCount', 'anotherGetter', // ... ]) }
}
经过mapGetters 函数调用之后的结果:
import { mapGetters } from 'vuex'
export default {
computed:{ doneTodoCount () { return this.$store.getters['doneTodoCount ']; }, anotherGetter() { this.$store.getters['anotherGetter ']; } }
}
前(对象)
computed: mapGetters({
doneCount: 'doneTodosCount'
})
经过mapGetters 函数调用之后的结果:
computed: {
doneCount() {
return this.$store.getters['doneTodosCount ']
}
}
1.2.3: mapActions mapActions工具函数将store中的dispatch方法映射到组件的methods中,和mapState、mapGetters类似,只不过 它映射的是地方不是计算属性,而是组件的methods对象上面:
前
import {mapActions} from 'vuex'
export default {
methods: { ...mapActions([ 'increase' // 映射this.increase() 到 this.$store.dispatch('increase'); ]), ...mapActtions([ add: 'increase' // 映射 this.add() 到 this.$store.dispatch('increase'); ]) }
}
经过mapActions 函数调用之后的结果:
import { mapActions } from 'vuex'
export default {
methods:{ increase(...arg) { return this.$store.dispatch.apply(this.$store, ['increase'].concat(args)) }, add(...arg) { return this.$store.dispatch.apply(this.$store, ['increase'].concat(args)); } }
}
1.2.4: mapMutations: mapMutations 工具函数会将store中的commit方法映射到组件的methods中,和mapActions的功能几乎一样
前
import { mapMutatiosn } from 'vuex'
export default {
methods: { ...mapMutatiosn ([ 'increase' // 映射this.increase() 到 this.$store.commit('increase'); ]), ...mapMutatiosn ([ add: 'increase' // 映射 this.add() 到 this.$store.commit('increase'); ]) }
}
经过mapMutatiosn 函数调用之后的结果:
import { mapMutatiosn } from 'vuex'
export default {
methods:{ increase(...arg) { return this.$store.commit.apply(this.$store, ['increase'].concat(args)) }, add(...arg) { return this.$store.commit.apply(this.$store, ['increase'].concat(args)); } }
}
1.3: 插件 Vuex的store接受一个plung 选项,一个Vuex的插件就是一个简单的方法,接受store作为唯一的参数。 插件的作用通常阿是用来监听每次mustations的变化的,来做一些事情。 在store的构造函数的最后,我们通过如下代码调用插件。
import devtoolPlungin from './plungins/devtool'
plungins.concat(devtoolPlungin).forEach(plungin => plungin(this))
2: 中央事件总线的使用(vue-bus)
在本地目录下创建目录vue-bus,在目录vue-bus下插件vue-bus.js文件,此时就给Vue添加了一个属性$bus,并且代理了$emit, $on,$off三个方法, 代理如下
// vue-bus.js
const install = function(Vue) {
const Bus = new Vue({ methods: { emit(event, ...args) { this.$emit(event, ...args); }, on(event, ...args) { this.$on(event, ...arg); }, off(event, callback) { this.$off(event, callback); } } }); Vue.prototype.$bus = Bus;
}
export default install;
使用:
// 在main.js 文件中使用
import VueBus from './vue-bus'; Vue,use(VueBus);
// 在view中仙剑一个组件Counter.vue
接收前
<template> <div> {{number}} </div> <button @click="handAddRandom">随机增加<button> </template> <script> export default { props: { number: { type:Number } }, methods: { handleAddRandom() { // 随机回去0-100之间的数值 const num = Math.floor(Match.random() * 100 + 1); this.$bus.emit('add', num); } } } </script>
接收后
<template> <div> <Counter :number="number"></Counter> </div>
·</template>
import Counter from './conter.vue' <script> export default { componrents: { Counter }, data: { return : { number: 0 } }, methods: { handlerAddRandom(num) { this.number = num; } } created() { this.$bus.on('add', this.handlerAddRandom ) }, beforeDestory() { this.$bus.off('add', this.handlerAddRandom) } } </script>