React中组件分为类组件和函数组件,在函数组件中没有state属性,所以一些使用不到state属性的类组件可以使用函数组件。
定义函数组件:
const User = () => {
return (
<div>
<p>名字:</p>
<p>年龄:</p>
</div>
)
}
ReactDOM.render(<User />, document.getElementById("app"));
在函数组件中传值:
const User = (props) => {
return (
<div>
<p>名字:{props.name}</p>
<p>年龄:{props.age}</p>
</div>
)
}
ReactDOM.render(<User name="fanghuayong" age="20"/>, document.getElementById("app"));
函数组件优点:
- 渲染比类组件快
- 可读性高
函数组件缺点:
3. 没有state属性
使用包含函数组件修改app应用:
class MyApp extends React.Component {
constructor(props) {
super(props);
this.handleRemoveAll = this.handleRemoveAll.bind(this);
// handleRemoveAll在其他地方引用,需要修正。
this.handlePickOption = this.handlePickOption.bind(this);
this.handleAddOption = this.handleAddOption.bind(this);
this.state = {
options: ["鲁班7号", "小乔", "蔡文姬"]
}
}
handleAddOption(option) {
// 验证
if(!option) {
return "选项不能为空"
}else if(this.state.options.includes(option)) {
return "不能输出重复的选项"
}else {
this.setState( prevState => {
return {
options: prevState.options.concat([option])
// 拼接数组
}
})
}
}
handleRemoveAll() {
console.log("删除所有 --来自MyApp")
this.setState(() => {
return {
options: []
}
})
}
handlePickOption() {
console.log("随机选择 --来自MyApp");
const index = Math.floor(Math.random() * this.state.options.length);
const option = this.state.options[index];
alert(option)
}
render() {
const title = "帮你决定ba";
const subTitle = "把你的命交给电脑吧";
return (
<div>
<Header title={title} subTitle={subTitle}/>
<Action hasOptions={this.state.options.length > 0} handlePickOption={this.handlePickOption}/>
<Options options={this.state.options} handleRemoveAll={this.handleRemoveAll}/>
<AddOption handleAddOption={this.handleAddOption}/>
</div>
)
}
}
// 小组件
const Header = (props) => {
return (
<div>
<h1>{props.title}</h1>
<p>{props.subTitle}</p>
</div>
)
}
const Action = (props) => {
return (
<div>
<button
onClick={props.handlePickOption}
disabled={!props.hasOptions}
>
随机输出
</button>
</div>
)
}
const Options = (props) => {
return (
<div>
<button onClick={props.handleRemoveAll}>重新开始</button>
{props.options.map( (option, index) => {
return <Option key={index} option={option}/>
})}
</div>
)
}
const Option = (props) => {
return (
<div>{props.option}</div>
)
}
class AddOption extends React.Component {
constructor(props) {
super(props);
this.formSubmit = this.formSubmit.bind(this);
this.state = {
error: undefined,
}
}
formSubmit(e) {
e.preventDefault();
let option = e.target.elements.option.value.trim();
// if(option) {
const error = this.props.handleAddOption(option)
console.log(error)
this.setState( () => {
return {
error,
}
})
// alert(option)
// }
e.target.elements.option.value = "";
}
render() {
return (
<div>
{this.state.error && <p>{this.state.error}</p>}
<form onSubmit={this.formSubmit}>
<input type="text" name="option" placeholder="请输入要新增的英雄"/>
<button>新增英雄</button>
<button>普通按钮</button>
</form>
</div>
)
}
}
ReactDOM.render(<MyApp/>, document.getElementById("app"));
默认值
如果组件中没有接受到props的实参,那么就是undefined,undefined就不会显示标签。我们可以用defaultProps来定义默认参数:
class MyApp extends React.Component {
constructor(props) {
super(props);
this.handleRemoveAll = this.handleRemoveAll.bind(this);
this.handlePickOption = this.handlePickOption.bind(this);
this.handleAddOption = this.handleAddOption.bind(this);
this.state = {
options: ["鲁班7号", "小乔", "蔡文姬"]
}
}
handleAddOption(option) {
// 验证
if(!option) {
return "选项不能为空"
}else if(this.state.options.includes(option)) {
return "不能输出重复的选项"
}else {
this.setState( prevState => {
return {
options: prevState.options.concat([option])
// 拼接数组
}
})
}
}
handleRemoveAll() {
console.log("删除所有 --来自MyApp")
this.setState(() => {
return {
options: []
}
})
}
handlePickOption() {
console.log("随机选择 --来自MyApp");
const index = Math.floor(Math.random() * this.state.options.length);
const option = this.state.options[index];
alert(option)
}
render() {
const title = "帮你决定ba";
const subTitle = "把你的命交给电脑吧";
return (
<div>
<Header subTitle={subTitle}/>
<Action hasOptions={this.state.options.length > 0} handlePickOption={this.handlePickOption}/>
<Options options={this.state.options} handleRemoveAll={this.handleRemoveAll}/>
<AddOption handleAddOption={this.handleAddOption}/>
</div>
)
}
}
// 小组件
const Header = (props) => {
return (
<div>
<h1>{props.title}</h1>
<p>{props.subTitle}</p>
</div>
)
}
Header组件没有接收到h1的props参数,所以没有了h1标签。
使用默认值:
const Header = (props) => {
return (
<div>
<h1>{props.title}</h1>
<p>{props.subTitle}</p>
</div>
)
}
Header.defaultProps = {
title: "我就是默认值"
}
class组件中也可以使用默认属性:
class MyApp extends React.Component {
constructor(props) {
super(props);
this.handleRemoveAll = this.handleRemoveAll.bind(this);
// handleRemoveAll在其他地方引用,需要修正。
this.handlePickOption = this.handlePickOption.bind(this);
this.handleAddOption = this.handleAddOption.bind(this);
this.state = {
options: props.options
}
}
handleAddOption(option) {
// 验证
if(!option) {
return "选项不能为空"
}else if(this.state.options.includes(option)) {
return "不能输出重复的选项"
}else {
this.setState( prevState => {
return {
options: prevState.options.concat([option])
// 拼接数组
}
})
}
}
handleRemoveAll() {
console.log("删除所有 --来自MyApp")
this.setState(() => {
return {
options: []
}
})
}
handlePickOption() {
console.log("随机选择 --来自MyApp");
const index = Math.floor(Math.random() * this.state.options.length);
const option = this.state.options[index];
alert(option)
}
render() {
const title = "帮你决定ba";
const subTitle = "把你的命交给电脑吧";
return (
<div>
<Header subTitle={subTitle}/>
<Action hasOptions={this.state.options.length > 0} handlePickOption={this.handlePickOption}/>
<Options options={this.state.options} handleRemoveAll={this.handleRemoveAll}/>
<AddOption handleAddOption={this.handleAddOption}/>
</div>
)
}
}
MyApp.defaultProps = {
options: ["鲁班7号", "小乔", "蔡文姬", "王昭君", "妲己", "安琪拉"]
}
工具: React dev tool
可以查看组件和数据的变化。