我在React.js中制作了这个小游戏:
演示:https://door-game.netlify.com/ App.js文件:https://github.com/Blazej6/Door-game/blob/master/src/App.js
我想在中心按钮中渲染一个与所选框架相匹配的图片。 3 Vue渲染vue,3反应 - 反应等。
如何制定逻辑呢?
做了一些实验性的approches,比如在应用程序和圈子组件中放置一个颜色类锚,但它似乎根本没有读取当前状态,至少不是从当前角度,也试图实际使用反应路由器并在一个圈中组成圈子组件链接,但无论出于何种原因,这真的搞砸了CSS
真的没有人能胜任这个任务吗?
答案 0 :(得分:1)
对于像这样的简单应用程序,还没有必要集成redux / mobx。我推荐的是在React中非常常见的东西,那就是lift your state up。
我们可以通过三个步骤来实现这一目标:
愚弄Circleone
,Circletwo
,Circlethree
个组件。他们只需要知道当前角度是什么,以呈现
ClawCircle
要渲染的图像(或其他空白)
App
需要保留所有这些信息的状态(因此我们已经解除了#{1;}状态从CircleX
升级到其父级,{ {1}})。
不要让App
保持在州内,而是假设通过道具currentAngle
向我们提供信息。当点击一个圆圈时,我们只会告诉我们创建圆圈的人,因为他们会向我们传递一个名为currentAngle
的道具。
由于我们现在不需要跟踪我们的状态,因此我们可以使组件无状态并将其转换为功能组件。
例如,onClick
可能看起来更像是这样:
CircleOne
接下来,让我们更改const CircleOne = ({ currentAngle, onClick }) => (
<div
className="App-logo small-logo"
alt="logo"
style={{ transform: `rotateZ(${currentAngle}deg)` }}
onClick={onClick}
>
<div className="little-circle one react">
{/* ... rest of your divs */}
</div>
);
,我们会给它一个可选的ClawCircle
道具,可能是imageClass
,claw-react
等,或者它可能只是一个空字符串(相应地更新css以渲染图像!)。因此claw-vue
方法可能会改变为:
render
顺便说一下,绑定调用可以在构造函数中完成而不是渲染方法,这样我们就不必在每次重新渲染组件时重新绑定。
render() {
const circleStyle = { transform: `rotateZ(${this.props.currentAngle}deg)` };
return (
<div
className={`App-logo claw-circle ${this.props.imageClass}`}
alt="logo"
style={circleStyle}
onClick={this.rotateCircle.bind(this)}
/>
);
}
这是一个更复杂的步骤,因为我们现在必须将繁重的工作委托给constructor(props) {
super(props);
// constructor code
this.rotateCircle = this.rotateCircle.bind(this);
}
// later: onClick={this.rotateCircle}
而不是个人App
。
所以Circle
需要知道每个圆圈的角度,并处理每个圆圈点击时发生的情况。此外,当角度改变时,我们想检查它们中的所有三个是否相等。如果它们相等,我们需要告诉App
要渲染的图像。
总而言之,它可能看起来像这样:
编辑:我应该尝试运行此代码,然后在此处动态编写。这是完整版(已测试!)只需确保您的CSS中有ClawCircle
claw-react
和claw-vue
规则
claw-angular
答案 1 :(得分:0)
好吧,组件封装在这里真的不喜欢这个有趣的王者,无论如何我得到的应用程序使用纯js,所有欢呼全局变量!
如果有人需要,可以使用以下代码:https://codepen.io/Raitar/pen/OOWRzb
当然是JS代码:
var angle=0;
var angle2=0;
var angle3=0;
count = 0;
count2 = 0;
count3 = 0;
document.getElementById("small-logo").addEventListener("click", rotateCircle)
document.getElementById("big-logo").addEventListener("click", rotateCircle2)
document.getElementById("biggest-logo").addEventListener("click", rotateCircle3)
function rotateCircle(){
angle+=120;
this.style.webkitTransform="rotate("+angle+"deg)";
count += 1;
if (count > 2) {
count = 0;
}
}
function rotateCircle2(){
angle2+=120;
this.style.webkitTransform="rotate("+angle2+"deg)";
count2 += 1;
if (count2 > 2) {
count2 = 0;
}
}
function rotateCircle3(){
angle3+=120;
this.style.webkitTransform="rotate("+angle3+"deg)";
count3 += 1;
if (count3 > 2) {
count3 = 0;
}
}
angular = "background-image:
url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/angular.png);"
react = "background-image:
url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/react.png);"
vue = "background-image: url(https://raw.githubusercontent.com/Blazej6/Door-
game/master/src/img/vue.png);"
document.getElementById("claw-circle").addEventListener("click",
changeCenter)
var x = document.getElementById("claw-circle")
function changeCenter() {
if (count == 0 && count2 == 0 && count3 == 0) {
x.style.cssText = angular;
} else if(count == 1 && count2 == 1 && count3 == 1) {
x.style.cssText = react;
} else if(count == 2 && count2 == 2 && count3 == 2) {
x.style.cssText = vue;
}
}