1、通过原生JS获取Dom去操作
通过document.querySelector('#title')
原生js的方式去拿到dom节点,然后去进行操作。
import {Component} from "react";
class App extends Component {
//定义获取Dom的函数
handleGetDom(){
let title = document.querySelector('#title');
console.log(title);
title.style.background = 'skyblue'
}
render() {
return (
<>
<h1 id="title">测试节点</h1>
<button onClick={this.handleGetDom}>点击操作Dom</button>
</>
)
}
}
export default App;
2、通过react官方提供的ref以及refs去获取DOM元素
但是需要值得一提的是,官方的refs将在未来的时间段内会被废除,并且因ref挂载的节点是挂载在组件实例上,因此函数不能使用es5的写法,如果使用es5的写法,需要.bind去更改this指向,否则this.refs拿到的将是undefined。
handleGetDom = () => {
console.log(this);
let { header } = this.refs;
header.style.background = 'gold';
}
render() {
return (
<>
<h1 ref={'header'}>测试节点</h1>
<button onClick={this.handleGetDom}>点击操作Dom</button>
</>
)
}
3、通过react官方提供的ReactDOM.findDOMNode去操作DOM元素
使用这种方式需要注意的是ReactDOM需要使用import ReactDOM from 'react-dom'
提前引入进来,否则是找不到findDOMNode这个方法的。
import {Component} from "react";
import ReactDOM from 'react-dom'
class App extends Component {
handleGetDom = () => {
let title = document.querySelector('#title');
ReactDOM.findDOMNode(title).style.background = 'green'
}
render() {
return (
<>
<h1 id="title">测试节点</h1>
<button onClick={this.handleGetDom}>点击操作Dom</button>
</>
)
}
}
export default App;
4、通过react官方推荐的ref回调函数去获取DOM元素
前面涉及到refs
即将被删除,因此,新版本 React 不推荐 使用ref string去操作DOM,转而推荐我们使用 ref callback的使用方式,通过这种方式挂载到实例对象上面,只需要在回调函数中使用this.属性名即可
import {Component} from "react";
class App extends Component {
handleGetDom = () => {
this._title.style.background = 'red'
}
render() {
return (
<>
<h1 ref={(ele)=>{this._title = ele}}>测试节点</h1>
<button onClick={this.handleGetDom}>点击操作Dom</button>
</>
)
}
}
export default App;
5、react官方推荐的写法:React.createRef()
Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问。
ref 的值根据节点的类型而有所不同:
- 当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
- 当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
- 不能在函数组件上使用 ref 属性,因为他们没有实例。
示例:
通过实现监听输入框的值以及将输入框的值追加到获取到的dom元素ul中去,在通过获取ul的子节点li,去给所有的li添加点击事件
import React, {Component} from "react";
class App extends Component {
state = {
msg:''
}
// 使用官方推荐的获取节点的写法进行操作
title = React.createRef();
// 监听输入框的值
handleChange = (e) => {
this.setState({
msg:e.target.value
})
}
// 将监听到输入框的值追加到获取到的ul的DOM元素中去
handleAdd = () => {
let {current} = this.title; //解构refs绑定的dom
current.innerHTML += `<li>${this.state.msg}</li>`;
// 追加完成后清空输入框
this.setState({
msg:''
})
// 打印下是否获取到了ul下的所有子节点
console.log(current.childNodes);
// 通过操作DOM给每个子节点li再次添加点击事件
this.title.current.childNodes.forEach((item,index)=>{
item.onclick = ()=>{
item.innerHTML +=`<b>点击了li元素<b>`;
}
})
}
render() {
return (
<>
<input type="text" value={this.state.msg} onChange={this.handleChange}></input>
<button onClick={this.handleAdd}>添加数据</button>
<ul ref={this.title}></ul>
</>
)
}
}
export default App;