我是React的新手,并且想编写一个有趣的项目来掌握这种语言。我想编写一个吹泡泡的应用程序,就像这样,我写了以下JSFiddle:
我正在渲染以以下方式存储的气泡对象数组:
history =
[ { //first element is empty placeholder
diameter: 0,
x: 0,
y: 0
},
{
diameter: 40,
x: 158,
y: 122
},
{
diameter: 86,
x: 274,
y: 214
},
{
diameter: 26,
x: 158,
y: 244
},
]
此精确数组将产生以下结果:
现在,在模拟了这一点之后,我有了疯狂的想法来增加一些重力并弹跳。我希望气泡像这样JSFiddle那样反弹:
但是,使气泡运行的唯一方法是直接将信息存储在状态中,如下面的代码所示。 (vy是球的垂直速度。)
class Box extends React.Component {
constructor(props) {
super(props);
this.state = {
diameter: 0,
x: 0,
y: 0,
vy: 0,
clicked: false,
};
}
我使用以下代码更新box的状态,以模拟气泡的弹跳:
fall(i){
this.setState({
y: this.state.y + i,
vy: this.state.vy + .01,
});
}
fallWrap(){
this.fall(this.state.vy);
this.u = setTimeout(this.fallWrap.bind(this), 1);
if(this.state.y >= 400 - (this.state.diameter/2)){
this.setState({
y: 400 - (this.state.diameter/2),
vy: -.9 * this.state.vy,
}, function(){
if(Math.abs(this.state.vy) < .2){
clearTimeout(this.u);
}
});
}
}
我想做的是像第一个JSfiddle一样存储多个气泡数组,并像第二个JS fiddle一样在框中弹出所有气泡。这意味着同时更新历史记录数组中多个对象的值vy。我希望我已经充分描述了我的需求。我的中心问题是如何使用setstate更新数组中存储的每个对象内的单个值(vy)?例如,如果我有
history =
[ {
diameter: 0,
x: 0,
y: 0,
vy: 0
},
{
diameter: 40,
x: 158,
y: 122,
vy: .5 //update this
},
{
diameter: 86,
x: 274,
y: 214,
vy: .4 //update this
},
{
diameter: 26,
x: 158,
y: 244
vy: .23 //update this
},
]
然后我如何以更新每个vy的方式实现setState?我知道在React中,状态数组应该是不可变的,所以我想知道是否存在建立此方法的方法。地图功能似乎很有希望,但是我不知道如何在这里应用它。
编辑:谢谢大家,我最终使用Haken解决方案解决了我的问题。这是指向JSFiddle
的链接答案 0 :(得分:2)
您可以将更新程序函数传递给setState。这是一个可能如何工作的示例。
从updater函数返回的对象将被合并到以前的状态。
const updateBubble = ({y, vy, ...props}) => ({y: y + vy, vy: vy + 0.1, ...props})
this.setState(state => ({bubbles: state.bubbles.map(updateBubble)}))
更改updateBubble函数以添加弹跳等。
答案 1 :(得分:1)
您确实可以使用map进行此操作。这就是我要做的。
一个班轮
var site = angular.module('site', ["ngRoute"]);
var initInjector = angular.injector(['ng']);
var $http = initInjector.get('$http');
site.config(function($routeProvider,$locationProvider){
$http.get("requests/views.php")
.then(function (response) {
var views = response.data.views;
$.each(views, function(i){
console.log(views[i].link)
$routeProvider.when('/' + views[i].link, {
templateUrl: views[i].template
// controller: 'pagesController'
})
})
})
$routeProvider.when('/', {
templateUrl: "template/home.php"
})
})
更明确
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
$conn = new mysqli("localhost", "root", "", "database");
$result = $conn->query("SELECT * FROM pages");
$views = "";
while($view = $result->fetch_array(MYSQLI_ASSOC)) {
if($views != ""){$views .= ",";}
$views .= '{"id":"' .$view["id"]. '",';
$views .= '"title":"' .$view["title"]. '",';
$views .= '"type":"' .$view["type"]. '",';
$views .= '"link":"' .$view["link"]. '",';
$views .= '"template":"' .$view["template"]. '",';
$views .= '"params":"' .$view["params"]. '"}';
}
$views = '{"views":['.$views.']}';
$conn->close();
echo($views);
答案 2 :(得分:0)
我建议您应该改变方法。您应该只按显示的第一个状态管理状态,然后在另一个组件中管理您当前拥有的组件的次数。
您可以使用类似这样的内容:
import React from 'react'
import Box from './box'
export default class Boxes extends React.Component {
constructor(props) {
super(props);
this.state = {
started:[false,false,false,false] /*these flags will be changed on your "onClick" event*/
}
}
render() {
const {started} = this.state
return(
<div>
{started[0] && <Box />}
{started[1] && <Box />}
{started[2] && <Box />}
{started[3] && <Box />}
</div>
)
}
}