ref 是一个入口 允许您直接访问DOM元素或组件实例。
使用ref的三大原则:
1.可以在dom元素上面使用ref属性
2.可以在class组件上面使用ref属性
3.不准在函数组件上面使用ref属性,原因:函数组件没有实例,父组件获取子组件的ref,其实是在获取子组件的实例;
但是可以在函数组件中 获取子组件实例的ref,并用一个变量存储起来,这个是没有问题的
代码描述 ref 的使用
import React, {Component, Fragment} from 'react'
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: ''
}
this.inputChange = this.inputChange.bind(this)
}
render() {
return (
<Fragment>
<div>
{/*
箭头函数构建一个 ref
箭头函数会自动的接收一个参数,参数的名字可以随便取 (input)
this.input = input 这句话的意思是 指向input Dom节点
ref={(input) => {this.input = input}}
*/}
<input
value={this.state.inputValue}
onChange={this.inputChange}
ref={(input) => {this.input = input}}/>
</div>
</Fragment>
)
}
inputChange(e) {
console.log(this.input.value) //通过Dom获取 (ref)
console.log(e.target.value) //通过数据形式
}
}
export default TodoList;
不推荐用ref,React建议我们数据驱动形式来编写代码尽量不要直接操作Dom,如果用ref有的时候会遇到各种各样的问题。举例:
import React, {Component, Fragment} from 'react'
import TodoItem from "./TodoItem";
class TodoList extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '',
list: ['星期一', '星期二', '星期三']
}
this.inputChange = this.inputChange.bind(this)
this.setInputChange = this.setInputChange.bind(this)
this.delListItem = this.delListItem.bind(this)
}
render() {
return (
<Fragment>
<div>
<input
value={this.state.inputValue}
onChange={this.inputChange}
ref={(input) => {
this.input = input
}}/>
<button onClick={this.setInputChange}>提交</button>
</div>
<ul ref={(ul) => {this.ul = ul}}>
{this.getTodoItem()}
</ul>
</Fragment>
)
}
getTodoItem() {
return this.state.list.map((item, index) => {
return (
<TodoItem
key={index}
content={item}
index={index}
deleteItem={this.delListItem}
/>
)
});
}
inputChange(e) {
const value = e.target.value
this.setState(() => ({
inputValue: value
}));
}
setInputChange() {
/* this.setState((prevState) => ({
* list: [...prevState.list, prevState.inputValue],
* inputValue: ''
* }));
* console.log(this.ul.querySelectorAll('li').length)
* 打印值是错误的。你获取的长度永远会比实际长度少一个
* 上方的 querySelectorAll 是react提供给我的一个方法可以获取ul下的内容
*/
/* 错误原因
* setState是异步函数也就是说setState还没被执行已经执行console
* 下方是解决方法
*/
this.setState((prevState) => ({
list: [...prevState.list, prevState.inputValue],
inputValue: ''
}), () => {
console.log(this.ul.querySelectorAll('li').length)
});
}
delListItem(index) {
this.setState((prevState) => {
const list = [...prevState.list]
list.splice(index, 1)
return {
list
}
});
}
}
export default TodoList;