在React / Redux中映射状态和动作的常用方法如下所示,因此映射函数与组件代码分开放置:
import React, { Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import myAction from 'actions/request';
class MyComponent extends Component {
/* BODY */
}
function mapStateToProps(state) {
return {
myComponentProp: state.myReducer.myReducerProp
};
}
function mapDispatchToProps(dispatch) {
return {
myComponentPropAction: bindActionCreators(myAction, dispatch),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
我在Vue中找到的唯一描述状态和动作的映射方式如下
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState('myReducer', {
myComponentProp: (state) => state.myReducerProp,
}),
...{
/* aditional manipulations with this.myComponentProp */
}
},
methods: {
...mapActions('myReducer', [
'myReducerAction'
]),
...{
myEventHandler: function() {
/* checke conditions before action call */
this.myReducerAction();
},
}
}
}
由于扩展的数量,代码看起来很模糊,所以问题是:
是否有办法像在react / redux常规方法中一样将mapState
和mapActions
移动到组件外部。
感谢帮助!
答案 0 :(得分:1)
好吧,除了打字稿支持外,他们还添加了一个vue-class-component装饰器,可用于实现您的目标。可以在此处找到指向此存储库的链接,但是我建议改为通过CLI创建一个新项目,然后从v3 Vue Class Component Github Repository中添加该项目开始。
<script>
function Getter (getterType) {
return createDecorator((options, key) => {
if (!options.computed) options.computed = {}
options.computed[key] = function () {
return this.$store.getters[getterType]
}
})
}
import Vue from 'vue'
import Component from 'vue-class-component'
@Component({
props: {
propMessage: String
}
})
export default class App extends Vue {
@Getter('foo') bar
@Setter('psu') psi
// computed
get computedMsg () {
return 'computed ' + this.msg
}
// method
greet () {
alert('greeting: ' + this.msg)
}
}
</script>
如您所见,正在使用此处的函数调用我们的getter和setter方法,该函数不是最佳方法,但更接近多汁的答案。现在出现了vuex-class-binding软件包,该软件包抽象了所有这些模糊的函数:vuex class
import Vue from 'vue'
import Component from 'vue-class-component'
import {
State,
Getter,
Action,
Mutation,
namespace
} from 'vuex-class'
const someModule = namespace('path/to/module')
@Component
export class MyComp extends Vue {
@State('foo') stateFoo
@State(state => state.bar) stateBar
@Getter('foo') getterFoo
@Action('foo') actionFoo
@Mutation('foo') mutationFoo
@someModule.Getter('foo') moduleGetterFoo
// If the argument is omitted, use the property name
// for each state/getter/action/mutation type
@State foo
@Getter bar
@Action baz
@Mutation qux
created () {
this.stateFoo // -> store.state.foo
this.stateBar // -> store.state.bar
this.getterFoo // -> store.getters.foo
this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
this.moduleGetterFoo // -> store.getters['path/to/module/foo']
}
}
这是一个示例,它的确非常不错,因为它能够采用命名空间模块并调用所有的getter和setter方法,而无需任何讨厌的自定义函数,因此我们可以将所有准备好使用的函数导入const
以上。现在,您只需使用装饰器就可以访问所有模块功能。这与可悲地将您的功能分配到组件中的程度几乎是一样的,但是一旦完成所有设置,它看起来就很不错了。我认为可以在有或没有TS的情况下进行此操作,但我一直在TS中完成,因为它对仍相对较新的vue类组件提供了一流的支持。