React基础篇(2) -- state&props&refs
内容简介
- state
- props
- refs
- 行内样式及动态类名
state
基本介绍
React 把组件看成是一个状态机(State Machines)。通过与用户的交互,实现不同状态,然后渲染 UI,让用户界面和数据保持一致。
React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
初始化状态:
constructor() {
super()
this.state = {
stateName1 : stateValue1,
stateName2 : stateValue2
}
}
读取显示:
this.state.stateName1
更新状态-->更新界面 :
this.setState({stateName1 : newValue})
举例如下:
class Myconponent1 extends React.Component{
constructor(props){
super(props)
// 1、初始化状态
this.state = {
isLike:false
}
//将新增的方法中的this强制绑定为组件对象
this.fun = this.fun.bind(this)
}
//新添加方法:内部this默认undefined
fun(){
//得到原有的状态
let flag = !this.state.isLike
// 3、更新状态(因为是单向数据流,只能通过指定方式改变状态)
this.setState({
isLike:flag
})
}
render(){
// 2、读取状态
const {isLike}=this.state;
return <h1 onClick={this.fun}>{isLike?'you like me?':'i like you!'}</h1>
//可以直接这样写,但效率低 return <h1 onClick={this.fun.bind(this)}>{flag?'you like me?':'i like you!'}</h1>
}
}
理解上面后可简化写法:
class Myconponent1 extends React.Component{
state = {
isLike:false
}
fun=()=>{
let {isLike}=this.state;
this.setState({
isLike:!isLike
})
}
render(){
const {isLike}=this.state;
return <h1 onClick={this.fun}>{isLike?'you like me?':'i like you!'}</h1>
}
}
注意
状态更新可能是异步的,不应该依靠它们的值来计算下一个状态。
可使用第二种形式的 setState() 来接受一个函数而不是一个对象。
该函数将接收先前的状态作为第一个参数,将此次更新被应用时的props做为第二个参数
this.setState((prevState, props) => ({
counter: prevState.counter + props.increment
}));
props
基本介绍
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据(包括函数方法)。
props
是所有组件标签的属性的集合对象。
作用
:给标签指定属性, 从目标组件外部向组件内部传递数据(可能是一个function)。
在组件内部读取属性
: this.props.propertyName
扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
默认 Props
你可以通过组件类的 defaultProps 属性为 props 设置默认值,实例如下:
class Hello extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Hello.defaultProps = {
name: 'adoctors'
};
Props 验证
Props 验证使用 propTypes,它可以保证我们的应用组件被正确使用,React.PropTypes 提供很多验证器 (validator) 来验证传入数据是否有效。当向 props 传入无效数据时,JavaScript 控制台会抛出警告。
相关链接:http://npm.taobao.org/package/prop-types
子组件响应父组件变化
componentWillReceiveProps(newVal){
console.log("newVal",newVal)
}
举例如下:
function Persion(props){
return (
<ul>
<li>姓名:{props.name}</li>
<li>年龄:{props.age}</li>
<li>性别:{props.sex}</li>
</ul>
)
}
// 默认属性值
Persion.defaultProps={
name:"tom",
age:18,
sex:"男"
}
//对属性值的类型和必要性限制,需要引入新文件
Persion.propTypes={
name:PropTypes.string.isRequired, //string且必须有
age:PropTypes.number //number可以没有
}
let msg={
name:"adoctors",
age:15,
sex:"男"
}
ReactDOM.render(<Persion {...msg}/>,document.getElementById(('com')))
//只传name,可以直接写则类型为string,若用{}包裹则可以传成number
ReactDOM.render(<Persion name="jack" age={28} />,document.getElementById(('com1')))
refs
React 支持一种非常特殊的属性 Ref ,你可以用来绑定到 render() 输出的任何组件上。
这个特殊的属性允许你引用 render() 返回的相应的支撑实例( backing instance )。这样就可以确保在任何时间总是拿到正确的实例。
下面是几个适合使用 refs 的情况:
- 处理焦点、文本选择或媒体控制。
- 触发强制动画。
- 集成第三方 DOM 库
如果可以通过声明式实现,则尽量避免使用 refs。
不能在函数式组件上使用 ref 属性,因为它们没有实例。
//指定ref
<div ref="myDiv" style={{color:"red"}}>adoctors</div>
<input type="text" ref="ipt0"/>
<input type="text" ref={val=>this.ipt1=val}/>
<input type="text" onBlur={this.getVal}/>
//获取相应的值
getVal=(e)=>{
console.log('获取其他元素的(myDiv)的样式: ',this.refs.myDiv.style.color);
console.log('获取其他元素的(ipt0)值: ',this.refs.ipt0.value)
console.log('获取其他元素的(ipt1)值: ',this.ipt1.value)
console.log('获取本元素的值: ', e.target.value);
}
结果如图:
行内样式
变量控制
let flag={
display:this.props.list.length?'none':'block'
}
<div style={flag}>暂无评论</div>
行内单个样式
<div style={{display: this.props.list.length ? "block" : "none"}}>此标签是否隐藏</div>
行内多个样式
<div style={{display: (index===this.state.currentIndex) ? "block" : "none", color:"red"}}>此标签是否隐藏</div>
动态类名
1、标签中没有其他class,只需要动态添加一个.active的className,来显示内容是否被选中状态,则:
<div className={index===this.state.currentIndex?"active":null}>此标签是否选中</div>
2、如果标签本身有其他class,又要动态添加一个.active的className,来显示内容是否被选中状态,则:
<div className={["container tab", index===this.state.currentIndex?"active":null].join(' ')}>此标签是否选中</div>
注意空格
或者,使用ES6写法(推荐使用ES6写法):
<div className={`container tab ${index===this.state.currentIndex?"active":null}`}>此标签是否选中</div>