一、ref
1、字符串形式的 ref
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>字符串形式的 ref</title>
</head>
<body>
<div id="test"></div>
</body>
<script src="../js/react/react.development.js" type="text/javascript"></script>
<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
<script src="../js/react/babel.min.js" type="text/javascript"></script>
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
// 这里收集的是真实 DOM
alert(this.refs.input1.value);
};
showData2 = () => {
alert(this.refs.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("test"));
</script>
</html>
2、回调函数形式的 ref
html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>回调函数形式的 ref</title>
</head>
<body>
<div id="test"></div>
</body>
<script src="../js/react/react.development.js" type="text/javascript"></script>
<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
<script src="../js/react/babel.min.js" type="text/javascript"></script>
<script type="text/babel">
class Demo extends React.Component {
showData = () => {
alert(this.input1.value);
};
showData2 = () => {
alert(this.input2.value);
};
render() {
return (
<div>
<input
ref={(currentNode) => {
this.input1 = currentNode;
}}
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("test"));
</script>
</html>
二、回调 ref 回调执行次数的问题
1、基本介绍
-
每次渲染时,内联回调都会被重新创建,类方法回调则不会被重新创建
-
先调用旧的 ref 回调,传入 null(清理),再调用新的 ref 回调,传入当前的 DOM 元素
| 阶段 | 类方法回调 | 内联回调 |
|---|---|---|
| 挂载 | 传入 DOM(1 次) | 传入 DOM(1 次) |
| 更新 | 不执行 | 先 null 后 DOM(2 次) |
| 卸载 | 传入 null(1 次) | 传入 null(1 次) |
2、演示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>回调 ref 回调执行次数的问题</title>
</head>
<body>
<div id="test"></div>
</body>
<script src="../js/react/react.development.js" type="text/javascript"></script>
<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
<script src="../js/react/babel.min.js" type="text/javascript"></script>
<script type="text/babel">
class Demo extends React.Component {
state = {
isHot: true,
};
changeWeather = () => {
const { isHot } = this.state;
this.setState({
isHot: !isHot,
});
};
showData = () => {
alert(this.input1.value);
};
getInput2 = (currentNode) => {
this.input2 = currentNode;
console.log("#", currentNode);
};
showData2 = () => {
alert(this.input2.value);
};
render() {
const { isHot } = this.state;
return (
<div>
<div>今天天气很{isHot ? "炎热" : "凉爽"}</div>
<button onClick={this.changeWeather}>点我切换天气</button>
<br />
<input
ref={(currentNode) => {
this.input1 = currentNode;
console.log("@", currentNode);
}}
type="text"
placeholder="点击按钮提示数据"
/>
<button onClick={this.showData}>点击提示左侧的数据</button>
<input ref={this.getInput2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test"));
</script>
</html>
三、createRef 函数
1、基本介绍
- React 的 createRef 函数在调用后返回一个容器,该容器可以存储被 ref 所标识的节点
2、演示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>createRef()</title>
</head>
<body>
<div id="test"></div>
</body>
<script src="../js/react/react.development.js" type="text/javascript"></script>
<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
<script src="../js/react/babel.min.js" type="text/javascript"></script>
<script type="text/babel">
class Demo extends React.Component {
input1 = React.createRef();
input2 = React.createRef();
showData = () => {
console.log(this.input1);
alert(this.input1.current.value);
};
showData2 = () => {
console.log(this.input2);
alert(this.input2.current.value);
};
render() {
return (
<div>
<input ref={this.input1} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点击提示左侧的数据</button>
<input ref={this.input2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test"));
</script>
</html>
四、事件处理
1、基本介绍
-
通过 onXxx 属性指定事件处理函数
-
原生:onclick,React:onClick
-
React 使用的是自定义(合成)事件,不是原生的 DOM 事件(为了更好的兼容性)
-
React 中的事件是通过事件委托的方式处理的(委托给组件最外层的元素,为了高效)
-
可以通过 event.target 得到发生事件的原生 DOM 对象
-
-
发生事件的元素正好是要操作的元素,就可以省略 ref,不要过度使用 ref
2、演示
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>事件处理</title>
</head>
<body>
<div id="test"></div>
</body>
<script src="../js/react/react.development.js" type="text/javascript"></script>
<script src="../js/react/react-dom.development.js" type="text/javascript"></script>
<script src="../js/react/babel.min.js" type="text/javascript"></script>
<script type="text/babel">
class Demo extends React.Component {
input1 = React.createRef();
input2 = React.createRef();
showData = () => {
alert(this.input1.current.value);
};
showData2 = (event) => {
alert(event.target.value);
};
render() {
return (
<div>
<input ref={this.input1} type="text" placeholder="点击按钮提示数据" />
<button onClick={this.showData}>点击提示左侧的数据</button>
<input ref={this.input2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
</div>
);
}
}
ReactDOM.render(<Demo />, document.getElementById("test"));
</script>
</html>