【问题标题】:Why is the Vuex action type unknown?为什么 Vuex 动作类型未知?
【发布时间】:2021-04-04 20:48:12
【问题描述】:

为什么操作类型未知,解决方法是什么?

我知道这是一个常见问题。我搜索了 SO,有大约 20 个答案,其中许多与 mapActions 相关。在阅读了所有这些答案并尝试了无数种 mapActions 语法后,我仍然无法弄清楚我的代码有什么问题。

我明白了,我们应该在组件(或模块)中调用 dispatch,然后在 Vuex 存储中提交一个突变(这是实际值被更改的地方)。

另外,不确定指出是否有帮助,但我希望在下面的状态图中看到动作和突变,但没有。

更新:

按照其他人的建议编辑代码后,结果仍然相同;未知操作类型:toggleIsCategoryWheelSpinning,{}

不确定它是否相关,但在 Wheel.vue 中调用 myStore.dispatch("toggleIsCategoryWheelSpinning,{}"); 的那一行在嵌套函数中。


这是我的代码:

 //Wheel.vue

    <template>
    <div >
        <div id="chart"></div>
    </div>
</template>

<script type="text/javascript" charset="utf-8">
import store from 'vuex'
import { mapActions} from 'vuex'

export default {
    name: "wheel",
    props: {
        wheelCategories: {
            type: Array,
            required: true,
        },
        expressions: {
            type: Array,
            required: true,
        },
    },
    data() {
        return {
        };
    },
    mounted() {
        let myscript = document.createElement("script");
        myscript.setAttribute("src", "https://d3js.org/d3.v3.min.js");
        document.head.appendChild(myscript);
        myscript.onload = this.createWheel(this.wheelCategories,this.expressions, this.$store);
    },
    methods: {
        ...mapActions(['toggleIsCategoryWheelSpinning']),   
        created(){
            this.toggleIsCategoryWheelSpinning       
        },

        createWheel: function (wheelCategories,expressions, myStore) {
            var padding = { top: 20, right: 40, bottom: 20, left: 20 },
                w = 500 - padding.left - padding.right,
                h = 500 - padding.top - padding.bottom,
                r = Math.min(w, h) / 2,
                rotation = 0,
                oldrotation = 0,
                picked = 100000,
                oldpick = [],
                color = d3.scale.category20();
            
            var svg = d3
                .select("#chart")
                .append("svg")
                .data([wheelCategories])
                .attr("width", w + padding.left + padding.right)
                .attr("height", h + padding.top + padding.bottom);
            
            var container = svg
                .append("g")
                .attr("class", "chartholder")
                .attr(
                    "transform",
                    "translate(" +
                        (w / 2 + padding.left) +
                        "," +
                        (h / 2 + padding.top) +
                        ")"
                )
                .style({ cursor: "grab" });

            var vis = container.append("g");

            var pie = d3.layout
                .pie()
                .sort(null)
                .value(function (d) {
                    return 1;
                });

            var arc = d3.svg.arc().outerRadius(r);

            var arcs = vis
                .selectAll("g.slice")
                .data(pie)
                .enter()
                .append("g")
                .attr("class", "slice");
            
            arcs.append("path")
                .attr("fill", function (d, i) {
                    return color(i);
                })
                .attr("d", function (d) {
                    return arc(d);
                });

            // add the text
            arcs.append("text").attr("transform", function (d) {
                d.innerRadius = 0;
                d.outerRadius = r;
                d.angle = (d.startAngle + d.endAngle) / 2;
                return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")translate(" + (d.outerRadius -10) +")";
            })
            .attr("text-anchor", "end")
                .text(function (d, i) {
                    return wheelCategories[i].label;                 
                });

            container.on("click", spin);  

            function spin(d) {
                container.on("click", null);
                //the following line gives the "unknown action"
                myStore.dispatch("toggleIsCategoryWheelSpinning,{}");
                console.log('dispatch finished');

                //all slices have been seen, all done
                if (oldpick.length == wheelCategories.length) {
                    document.getElementById("spinResponse"
                    ).innerHTML = `out of spins`;
                    container.on("click", null);
                    return;
                }

                var ps = 360 / wheelCategories.length,
                    pieslice = Math.round(1440 / wheelCategories.length),
                    rng = Math.floor(Math.random() * 1440 + 360);

                rotation = Math.round(rng / ps) * ps;

                picked = Math.round(
                    wheelCategories.length - (rotation % 360) / ps
                );
                picked =
                    picked >= wheelCategories.length
                        ? picked % wheelCategories.length
                        : picked;

                if (oldpick.indexOf(picked) !== -1) {
                    d3.select(this).call(spin);
                    return;
                } else {
                    oldpick.push(picked);
                }

                rotation += 90 - Math.round(ps / 2);

                let index = Math.floor(Math.random() * expressions.length); // 10  returns a random integer from 0 to 9

                vis.transition()
                    .duration(3000)
                    .attrTween("transform", rotTween)
                    .each("end", function () {
                        oldrotation = rotation;
                        container.on("click", spin);
                    });
            }

            //make arrow
            svg.append("g")
                .attr(
                    "transform",
                    "translate(" +
                        (w + padding.left + padding.right) +
                        "," +
                        (h / 2 + padding.top) +
                        ")"
                )
                .append("path")
                .attr(
                    "d",
                    "M-" +
                        r * 0.15 +
                        ",0L0," +
                        r * 0.05 +
                        "L0,-" +
                        r * 0.05 +
                        "Z"
                )
                .style({ fill: "black" });

            //draw spin circle
            container
                .append("circle")
                .attr("cx", 0)
                .attr("cy", 0)
                .attr("r", 60)
                .style({ fill: "white", cursor: "grab" });

            //spin text
            container
                .append("text")
                .attr("x", 0)
                .attr("y", 15)
                .attr("text-anchor", "middle")
                .text("SPIN ME!")
                .style({
                    "font-weight": "bold",
                    "font-size": "25px",
                    cursor: "grab",
                });

            function rotTween(to) {
                var i = d3.interpolate(oldrotation % 360, rotation);
                return function (t) {
                    return "rotate(" + i(t) + ")";
                };
            }

            function getRandomNumbers() {
                var array = new Uint16Array(1000);
                var scale = d3.scale
                    .linear()
                    .range([360, 1440])
                    .domain([0, 100000]);

                if (
                    window.hasOwnProperty("crypto") &&
                    typeof window.crypto.getRandomValues === "function"
                ) {
                    window.crypto.getRandomValues(array);
                    console.log("works");
                } else {
                    //no support for crypto, get crappy random numbers
                    for (var i = 0; i < 1000; i++) {
                        array[i] = Math.floor(Math.random() * 100000) + 1;
                    }
                }

                return array;
            }
        }
    }
    
};

//end code for wheel
</script>

<style type="text/css" scoped>
text {
    font-size: 15px;
    pointer-events: grab;
}
#chart {
    /* cursor: grab; */
    margin: 0 auto;
    border: 10px;
}
#question {
    text-align: center;
}
#question h1 {
    font-size: 50px;
    font-weight: bold;
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    /* position: absolute; */
    padding: 0;
    margin: 0;
    top: 50%;
    -webkit-transform: translate(0, -50%);
    transform: translate(0, -50%);
}

#spinResponse {
    font-size: 30px;
    text-align: center;
    width: 500px;
    padding-bottom: 30px;
    background-color: rgb(129, 19, 19);
    font-weight: bold;
}

</style>

vuex 商店

// store/index.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const foodCategories = [
   //...
];

const expressions = [
   //...
];

const isCategoryWheelSpinning = false;

export default new Vuex.Store({
  state: {
    foodCategories,
    expressions,
    isCategoryWheelSpinning,
  },
  getters: {
  },    
  actions: {
    toggleIsCategoryWheelSpinning(context,payload){
        context.commit("toggleIsCategoryWheelSpinning",payload);
    }
  },
  mutations: {
   toggleIsCategoryWheelSpinning(state, payload) {
      state.isCategoryWheelSpinning = !isCategoryWheelSpinning;
    },
  },
});

和 main.js

// src/main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store';

Vue.config.productionTip = false

new Vue({
  store,
  render: h => h(App),
}).$mount('#app')

【问题讨论】:

  • 使用两个参数调用一个动作:name,它是{module/}{action} 形式的字符串(使用模块时带有模块名称)和payload,它可以是一个对象(或数组,它仍然是一个对象)或任何原语(stringbooleannumber 等)。因此,如果您想使用空对象作为有效负载来调用它,请将其称为dispatch("toggleIsCategoryWheelSpinning", {})。您已将有效负载放在 name 参数中,它会生成一个不映射到已知操作的字符串。
  • @tao ,您的评论导致(是)答案。谢谢。
  • 欢迎。这就是我写它的原因:)。我没有将其发布为答案,因为我相信如果您花更多时间查看文档,您可能会自己发现这一点。从我看到的地方来看,这个错误非常简单,所以在我看来,你的问题不太可能对未来的用户有所帮助。因此,根据 SO 规则(据我所知),不应该回答。我意识到我在这里很主观,但是嘿,我可以选择在哪里设置标准来考虑值得回答的问题。如果不是,我只是通过指出正确的方向来提供帮助,如果我看到它的话。节日快乐!

标签: vue.js vuex action dispatch


【解决方案1】:

您的操作名称不匹配。您的代码应该相同。 尝试使用 :...mapActions(["toggleIsCategoryWheelSpinning"] 导入动作

【讨论】:

  • 我按照您和@Sadraque Santos 的建议编辑了我的代码。另外,我添加了 Wheel.vue 的所有内容。不确定它是否相关,但在 Wheel.vue 中调用 dispatch 的行在嵌套函数内。
  • 您需要将函数调用为this.toggleIsCategoryWheelSpinning(),并且在变异函数内部,变量应用作state.isCategoryWheelSpinning = !state.isCategoryWheelSpinning
【解决方案2】:

在您的商店actions 中,没有名为action_toggleIsCategoryWheelSpinning 的操作,但有一个名为toggleIsCategoryWheelSpinning 的操作,因此您应该在mapActions 中导入该操作:

methods: {
  mapActions(['toggleIsCategoryWheelSpinning'])
}

【讨论】:

    【解决方案3】:

    @Tao 的评论(见下文)导致(是)答案;特别是粗体字。

    以下代码编辑修复了该问题。

    在 Wheel.vue 中,编辑方法部分

    ...mapActions(['toggleIsCategoryWheelSpinning']),   
    created(){
        this.toggleIsCategoryWheelSpinning       
    },
    

    调用dispatch时,从第一行改为第二行。

    myStore.dispatch("toggleIsCategoryWheelSpinning,{}");    
    myStore.dispatch("toggleIsCategoryWheelSpinning",{});
    

    一个动作用两个参数调用:name,它是一个字符串 {module/}{action} 的形式(使用时带有模块名称 模块)和有效载荷,它可以是一个对象(或数组,它仍然是 一个对象)或任何原语(字符串、布尔值、数字等)。 所以打电话 如果你愿意,它作为 dispatch("toggleIsCategoryWheelSpinning", {}) 使用空对象作为有效负载调用它。 您已经放置了有效负载 在 name 参数中,它会产生一个字符串,它不会 映射到已知动作。 – tao 30 分钟前

    【讨论】:

    • 映射动作没有任何问题(因此您可以将其称为this.someName({}).then(r =&gt; /* do something with the returned promise result */) 而不是this.$store.dispatch('someName', {}).then(r =&gt; ...)),但您并不需要它。这就是一个 action 的映射:它在 Vue 实例上创建一个 async 方法,与 store 中的 action 同名,返回 store 中 action 返回的 promise。
    猜你喜欢
    • 2022-01-02
    • 2019-10-28
    • 2021-06-26
    • 2020-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多