目录
state
事件绑定
props
函数式组件使用props
refs
state
state是组件对象最重要的属性,值是对象(可以包含多个 key-value的组合);组件被称为“状态机”,通过更新组件来对应页面显示(重新渲染组件),也就是有状态组件:
事件绑定
在React中进行事件绑定来渲染数据通过使用以下方式进行:
<body>
<div id="root"></div>
<!-- 引入react核心库 -->
<script src="./node_modules/react/umd/react.development.js"></script>
<!-- 引入react-dom,用于支持react操作dom -->
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
<!-- 引入babel,用于将jsx转为js -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
// 创建组件
class Weather extends React.Component {
constructor(props){
super(props)
this.state = {isHot:true,wind:'微风'}
// 将changeWeather的this指向Weather的实例对象上
this.changeWeather = this.changeWeather.bind(this)
}
render(){
// 读取状态
const {isHot,wind} = this.state
return (
<div>
<h1>今天天气很{isHot ? '炎热' : '寒冷'},{wind}</h1>
<button onClick={this.changeWeather}>点击切换天气</button>
</div>
)
}
changeWeather(){
// 获取原来的isHot的值
const isHot = this.state.isHot
// 注意:状态必须通过 setState 进行更新,且更新是一种合并不是替换
this.setState({isHot:!isHot})
// 禁止直接对state状态进行修改
// this.state.isHot = !isHot 这种写法是错误的
}
}
// 渲染页面到组件
ReactDOM.render(<Weather/>,document.getElementById('root'))
</script>
</body>
虽然能实现效果,但是未免有些过于繁琐,要知道我们在创建类的时候,如果不是通过new出来的实例传入的数据,我们完全可以把固定的数据写在构造器的外面,如下:
<script>
class person {
constructor(name,age){
this.name = name
this.age = age
}
// 类里面可以直接写赋值语句
gender = '男'
}
const p1 = new person('张三',18)
console.log(p1)
</script>
所以我们也可以将state状态写在构造器外面,构造器可以直接省略,通过箭头函数的this指向外层的this来达到修改state中this数据的目的:
<script type="text/babel">
// 创建组件
class Weather extends React.Component {
// 初始化状态
state = {isHot:true,wind:'微风'}
render(){
// 读取状态
const {isHot,wind} = this.state
return (
<div>
<h1>今天天气很{isHot ? '炎热' : '寒冷'},{wind}</h1>
<button onClick={this.changeWeather}>点击切换天气</button>
</div>
)
}
// 自定义方法---要用赋值语句的形式+箭头函数
changeWeather = ()=> {
const isHot = this.state.isHot
this.setState({isHot:!isHot})
}
}
// 渲染页面到组件
ReactDOM.render(<Weather/>,document.getElementById('root'))
</script>
注意:
1)组件中render方法中的this为组件实例对象。
2)组件自定义的方法中this为undefined,强制绑定this可以通过函数对象的bind()或箭头函数。
3)状态数据,不能直接修改或更新。
props
每个组件对象都会有 props 属性,组件标签的所有属性都保存在 props 中。其基本使用如下:
<script type="text/babel">
// 创建组件
class Person extends React.Component {
render(){
const {name,age,gender} = this.props
return (
<ul>
<li>姓名: {name}</li>
<li>年龄: {age}</li>
<li>性别: {gender}</li>
</ul>
)
}
}
// 渲染页面到组件
ReactDOM.render(<Person name="张三" age="18" gender="男" />,document.getElementById('root'))
</script>
如果想批量传递props,可以通过以下方式:
构造器是否接受props,是否传递给super,取决于:是否希望在构造器中通过this访问props。
函数式组件使用props
<script type="text/babel">
// 函数式组件使用props
function Person(props){
const {name,age,gender} = props
return (
<ul>
<li>姓名: {name}</li>
<li>年龄: {age}</li>
<li>性别: {gender}</li>
</ul>
)
}
// 渲染页面到组件
ReactDOM.render(<Person name="张三" age="18" gender="男"/>,document.getElementById('root'))
</script>
注意:
1)通过标签属性从组件外向组件内传递变化的数据
2)props是只读的,组件内部不要修改props
refs
组件内的标签可以定义ref属性来标识自己
字符串形式的ref
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
// 展示输入框左侧的数据
showData = ()=>{
const {input1} = this.refs
alert(input1.value)
}
// 展示输入框右侧的数据
showData2 = ()=>{
const {input2} = this.refs
alert(input2.value)
}
render(){
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮显示数据" />
<button onClick={this.showData}>点我显示数据</button>
<input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
// 渲染组件
ReactDOM.render(<Demo/>,document.getElementById('root'))
</script>
虽然这种方式很简单,但是存在一定的效率问题,官方文档明确说明不建议去使用它:
回调形式的ref
拿到当前ref所在的节点,react帮助我们调用函数然后传进来,之后挂载到实例自身上。
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
// 展示输入框左侧的数据
showData = ()=>{
const {input1} = this
alert(input1.value)
}
// 展示输入框右侧的数据
showData2 = ()=>{
const {input2} = this
alert(input2.value)
}
render(){
return (
<div>
<input ref={c => this.input1 = c} type="text" placeholder="点击按钮显示数据" />
<button onClick={this.showData}>点我显示数据</button>
<input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
)
}
}
// 渲染组件
ReactDOM.render(<Demo/>,document.getElementById('root'))
</script>
使用回调形式的ref会出现以下问题,如果想解决这个问题,可以用以下方式:
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
// 展示输入框的数据
showData = ()=>{
const {input1} = this
alert(input1.value)
}
saveInput = (c)=>{
this.input1 = c
console.log('@');
}
render(){
return (
<div>
{/*在JSX语法中,注释的书写方式是外层包裹大括号,表明里面是JS语法,写上注释即可表明当前为注释*/}
<input ref={this.saveInput} type="text" placeholder="点击按钮显示数据" />
<button onClick={this.showData}>点我显示数据</button>
</div>
)
}
}
// 渲染组件
ReactDOM.render(<Demo/>,document.getElementById('root'))
</script>
createRef的使用
React.createRef调用后可以返回一个容器,该容器可以存储被ref所标识的节点。但这种形式有一种缺点就是只能容纳一个元素进行使用,如果想出里多个元素需创建多个createRef容器。
<script type="text/babel">
// 创建组件
class Demo extends React.Component {
// 创建容器
myRef = React.createRef()
myRef1 = React.createRef()
// 展示输入框的数据
showData = ()=>{
console.log(this.myRef.current);
alert(this.myRef.current.value)
}
showData1 = ()=>{
console.log(this.myRef1.current);
}
render(){
return (
<div>
{/*在JSX语法中,注释的书写方式是外层包裹大括号,表明里面是JS语法,写上注释即可表明当前为注释*/}
<input ref={this.myRef} type="text" placeholder="点击按钮显示数据" />
<button onClick={this.showData}>点我显示数据</button>
<input type="text" onBlur={this.showData1} ref={this.myRef1} placeholder="另一个input" />
</div>
)
}
}
// 渲染组件
ReactDOM.render(<Demo/>,document.getElementById('root'))
</script>