我对 React 和 Javascript 都很陌生,我已经通过构建一个简单的可折叠菜单开始学习它。它按预期工作,除了我不知道如何一次只突出显示一个项目。我怀疑 onClick 方法和状态必须由比 sectionItem 更高级别的类拥有,但我真的很困惑如何使它起作用。我的第一直觉是每次单击某项时都遍历菜单中的所有项目,并确保所有其他项目都切换为 active=false。
这是正确的思考方式吗?有人可以解释在这种情况下状态在 React 中是如何工作的,以及我应该如何在这里实现它?
完整代码可在此处获得:Menu on codepen.io
这是我想要突出显示的项目的代码。我还不能实现一次只突出显示一个项目。
var SectionItem = React.createClass({
handleClick: function(){
if(!this.state.active) {
this.setState({
currentItem: this,
active: true,
class: "sectionitem active"});
}
},
getInitialState: function(){
return {
active: false,
class: "sectionitem"
}
},
render: function() {
return (
<div className={this.state.class} onClick={this.handleClick}>{this.props.title}</div>
);
}
});
最佳答案
伟大的开始!让我们先解决一下代码中的一些问题。
无需在最顶层组件中创建整个嵌套结构。这是非常做作的:
for (i=0; i < this.props.menuitems.length; i++) {
if(this.props.menuitems[i].section !== lastSection) {
var section = this.props.menuitems[i].section;
var items = [];
for (j=0; j < this.props.menuitems.length; j++) {
if(this.props.menuitems[j].section == section) {
var itemName = this.props.menuitems[j].name;
items.push(<SectionItem title={itemName} key={itemName} />);
};
}
sections.push(<Section title={section} items={items} key={section} />);
lastSection = section;
}
}
恰恰相反。您应该尝试让每个组件负责呈现自己的信息。如果我们首先处理您的数据,我们可以改进这一点。问题是您的部分没有嵌套。如果,而不是这个...
var MENU_ITEMS = [
{section: "About", name: "Hey", key: "Hey", selected: true},
{section: "About", name: "No", key: "No", selected: false},
{section: "About", name: "Way", key: "Way", selected: false},
{section: "People", name: "Cakewalk", key: "Cakewalk", selected: false},
{section: "People", name: "George", key: "George", selected: false},
{section: "People", name: "Adam", key: "Adam", selected: false},
{section: "Projects", name: "Pirate raid", key: "Pirate raid", selected: false},
{section: "Projects", name: "Goosehunt", key: "Goosehunt", selected: false},
];
我们有这个:
var sections = [
{
name: "About",
items: [
{name: "Hey", key: "Hey", selected: true},
{name: "No", key: "No", selected: false},
{name: "Way", key: "Way", selected: false}
]
},{
name: "People",
items: [
{name: "Cakewalk", key: "Cakewalk", selected: false},
{name: "George", key: "George", selected: false},
{name: "Adam", key: "Adam", selected: false}
]
},{
name: "Projects",
items: [
{name: "Pirate raid", key: "Pirate raid", selected: false},
{name: "Goosehunt", key: "Goosehunt", selected: false}
]
}
];
然后我们可以大大简化Accordion。我们只需为每个 section 呈现一个 Section:
var Accordion = React.createClass({
render: function() {
return (
<div className="main">
{this.props.sections.map(function(section){
return <Section key={section.name} section={section}/>
})}
</div>
);
}
});
同样,Section 和 SectionItem 变得非常简单。
var Section = React.createClass({
handleClick: function(){
this.setState({
open: !this.state.open,
class: this.state.open ? "section" : "section open"
});
},
getInitialState: function(){
return {
open: false,
class: "section"
}
},
render: function() {
return (
<div className={this.state.class}>
<div className="sectionhead" onClick={this.handleClick}>{this.props.section.name}</div>
<div className="articlewrap">
<div className="article">
{this.props.section.items.map(function(item){
return <SectionItem key={item.name} item={item}/>
})}
</div>
</div>
</div>
);
}
});
var SectionItem = React.createClass({
handleClick: function(){
this.setState({
currentItem: this,
active: !this.state.active,
class: this.state.active ? "sectionitem" : "sectionitem active"
});
},
getInitialState: function(){
return {
active: false,
class: "sectionitem"
}
},
render: function() {
return (
<div className={this.state.class} onClick={this.handleClick}>{this.props.item.name}</div>
);
}
});
现在,回到您原来的问题。在更复杂的应用程序中,您可以从更强大的功能中受益,例如 Flux .然而,就目前而言,遵循 Thinking in React 中公开的技术应该可以解决你的问题。
的确,一种好方法是将“打开的内容”的状态带到 Accordion 组件中。您只需要让您的 parent 知道某些东西被点击了。我们可以通过作为 prop 传递的回调来做到这一点。
因此,Accordion 可以有一个 openSection 状态,以及一个接收被点击部分名称的 onChildClick。它需要将 onChildClick 传递给每个 Section。
var Accordion = React.createClass({
getInitialState: function() {
return {
openSection: null
};
},
onChildClick: function(sectionName) {
this.setState({
openSection: sectionName
});
},
render: function() {
return (
<div className="main">
{this.props.sections.map(function(section){
return <Section key={section.name}
onChildClick={this.onChildClick}
open={this.state.openSection===section.name}
section={section}/>
}.bind(this))}
</div>
);
}
});
Section 只需在单击时调用此函数,并传入它自己的名称。
var Section = React.createClass({
handleClick: function(){
this.props.onChildClick(this.props.section.name);
},
render: function() {
var className = this.props.open ? "section open" : "section"
return (
<div className={className}>
<div className="sectionhead" onClick={this.handleClick}>{this.props.section.name}</div>
<div className="articlewrap">
<div className="article">
{this.props.section.items.map(function(item){
return <SectionItem key={item.name} item={item}/>
})}
</div>
</div>
</div>
);
}
});
您可以将此解决方案外推到 SectionItem 问题。
生成的代码笔在这里:http://codepen.io/gadr90/pen/wamQXG?editors=001
祝你学习 React 好运!您走在正确的道路上。
关于javascript - 使用 React 一次突出显示一个对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31280902/
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
总的来说,我对ruby还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t