React&Vue 系列:ref 绑定 dom 节点

背景:作为使用三年 react.js 的搬运工,目前正在积极学习 vue.js 语法,而在学习的过程中,总是喜欢和 react.js 进行对比,这里也不是说谁好谁坏,而是怀有他有我也有,他没我还有的思想去学习,去总结。

  • React18
  • Vue3

ref 绑定 dom 节点,其实也就是对真实 dom 节点进行操作。但是呢,无论是 react 开发还是 vue 开发,通常情况下不需要、也不建议直接操作 DOM 原生,但是在某些特殊的场景下,是需要的。所以还是有必要了解一下这个小小的知识点。

其实,在我脑海中,我还能浮现一个画面:我第一份工作的时候,组长对我的代码(React 实现拖拽分组功能)质量检测时,发现我是直接操作节点,还是使用 document 的方式,当场就是一顿批斗。(说 xxx(难听的话),React 开化是以数据流控制状态 ,而不是要你直接操作状态的,dom 操作交给 React 底层操作,不需要你管),组长下去还专门给我搜了一篇关于React 数据流的博客,让我学习。从那以后,我的开发思维就开始变化了。 第一份工作,是招人白眼的工作,也是一份学习的工作。

回忆往事,时间过得真快呀,都快出来工作三年了。好了,进入正题。

熟悉 React,先写 React

React:ref 绑定 dom 节点

单个节点

在大部分的情况下都是不用操作 dom,但是操作 dom 的时候,大部分都是单节点的形式。

在 React 中提供了一个 hook : useRef。该 hook 既可以保存变量,又可以用来操作 dom。

ts 复制代码
import { useRef } from "react";
​
function App() {
  // 定义一个用来保存 dom 的 ref
  const divDomRef = useRef<HTMLDivElement>(null);
  const btn = () => {
    console.log(divDomRef.current);
  };
  return (
    <>
      {/* ref 绑定 */}
      <div ref={divDomRef}>我是单节点</div>
      <button onClick={btn}>获取dom节点</button>
    </>
  );
}

点击按钮,就能拿到真实的 dom 节点了。

注意要点:

  • ref 和 key 在 React 的 props 中,都是保留的 prop【RESERVED_PROPS】,有单独处理的逻辑。
  • ref 只能绑定原生节点,如果在组件上使用 ref,就需要使用 forwardRef 进行转化。

多个节点

就是拿到一个列表数据,进行渲染,需求就是对每条数据进行 ref 绑定,进行保存。

这是理想状态中的写法:

ts 复制代码
import { useRef, useState } from "react";
​
function App() {
  const [list] = useState([1, 2, 3, 4, 5]);
  const liDomRef = useRef<HTMLLIElement>(null);
  const btn = () => {
    console.log(liDomRef.current);
  };
  return (
    <>
      <ul>
        {list.map((v) => {
          return (
            <li ref={liDomRef} key={v}>
              {v}
            </li>
          );
        })}
      </ul>
      <button onClick={btn}>获取dom节点</button>
    </>
  );
}
​
export default App;

点击按钮,发现只会拿到最后一个列表节点,这肯定不是想要的结果。那么该如何操作呢?

这里又会存在一个小小的知识点:ref 可以接受一个 ref 对象,也可以接受一个函数。嘿,那么思路就来了。

函数的第一个参数,就是 dom 节点,那么我们只需要集中保存即可

ts 复制代码
import { useRef, useState } from "react";
​
function App() {
  const [list] = useState([1, 2, 3, 4, 5]);
  const lisDomRef = useRef<HTMLLIElement[]>([]);
​
  const getRef = (el: HTMLLIElement) => {
    lisDomRef.current.push(el);
  };
​
  const btn = () => {
    console.log(lisDomRef.current);
  };
  return (
    <>
      <ul>
        {list.map((v) => {
          return (
            <li ref={getRef} key={v}>
              {v}
            </li>
          );
        })}
      </ul>
      <button onClick={btn}>获取dom节点</button>
    </>
  );
}

点击按钮,就拿到 dom 集合了。

Vue: ref 绑定 dom 节点

单个节点

ts 复制代码
<script setup lang="ts">
import { ref } from "vue";
​
const divDomRef = ref<HTMLDivElement>();
​
const btn = () => {
  console.log(divDomRef.value);
};
</script>
​
<template>
  <div ref="divDomRef">我是单节点</div>
  <button @click="btn">获取dom节点</button>
</template>

点击按钮,拿取 dom 节点。

多个节点

ts 复制代码
<script setup lang="ts">
import { ref, reactive } from "vue";
​
const list = reactive([1, 2, 3, 4, 5]);
​
const lisDomRef = ref<HTMLLIElement[]>([]);
​
// ?? 这里的类型存在问题
const getRef = (el: any) => {
  if (el) {
    lisDomRef.value.push(el);
  }
};
​
const btn = () => {
  console.log(lisDomRef.value);
};
</script>
​
<template>
  <ul>
    <li v-for="item in list" :key="item" :ref="getRef">
      {{ item }}
    </li>
  </ul>
  <button @click="btn">获取dom节点</button>
</template>

敲码完成。

总结

是不是很快,两个方面:

  • 知识点简单
  • React 和 Vue 无论是单节点还是多节点,使用的方式一模一样。

简单的知识,愉快的学习,后面有时间深入源码理解。

相关推荐
Jack N1 小时前
【Strapi 系列之五】前端怎么接?Next.js + Tailwind 拉取 Strapi 数据(含代码)
开发语言·前端·javascript·strapi
来一首_We_go1 小时前
React Flow Pro 高级交互实现
前端·react.js
weedsfly1 小时前
React 不可变数据:为什么页面“明明数据变了却不更新
前端·javascript·react.js
Gizzap_Tech1 小时前
双语内容审阅台怎么做?用内容指纹保留核验记录
javascript
随风一样自由2 小时前
【React+TS71007】Next.js “use client” 误用导致 TS71007:客户端/服务端引入问题的完整排查与修复
前端·javascript·react.js
林恒smileZAZ4 小时前
用 Vue 3 + Electron 做桌宠:从启动退出到拖拽、单击与鼠标穿透
vue.js·electron·计算机外设
软件技术NINI5 小时前
基于JavaWeb 汽车租聘
java·vue.js·spring boot·后端·python·毕业设计·毕设
2301_322414280412 小时前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
酷炫码神16 小时前
Day 10|Pinia 状态管理:把散落在各组件的数据,收进一个全局仓库
android·开发语言·javascript
酷炫码神18 小时前
Day 8|Vue3 响应式:告别手动操作 DOM,让数据驱动界面
javascript·vue.js·ecmascript