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