V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
WangLiCha
V2EX  ›  程序员

怎么理解 Vue 和 React 都有的 ref 这个概念?为什么要这样设计?

  •  
  •   WangLiCha · 2023-03-14 16:32:01 +08:00 · 3803 次点击
    这是一个创建于 611 天前的主题,其中的信息可能已经有所发展或是发生改变。

    之前我是做 WPF 的,在 WPF 里的控件(对应 Web 前端的组件)都有一个 Name 属性,在后台代码里可以直接通过这个 Name 属性获取控件的实例,以及根据控件的实例属性获取他全部子元素的实例,然后进行一些操作。

    但是接触到 Web 前端框架过后,发现无论是 Vue 还是 React 都不能像 WPF 一样方便获取组件的实例,而是需要一个不是很直观的 ref 来辅助获取,而且即使获取到了,在通过代码获取子组件也很困难,比如 Ant Design 的 Tabs 控件,除非为所有的 items 的 children 手动添加 ref ,否则是没法获取每个 children 的实例的。

    所以现在很疑惑,应该怎么理解 Vue 和 React 都有的 ref 这个概念?为什么要这样设计呢?

    26 条回复    2023-03-17 16:00:11 +08:00
    xieqiqiang00
        1
    xieqiqiang00  
       2023-03-14 16:43:31 +08:00
    组件有状态
    TWorldIsNButThis
        2
    TWorldIsNButThis  
       2023-03-14 16:44:09 +08:00   ❤️ 2
    react hook 的 ref 类比是 java 的 threadlocal ,更准确的说是未来的 scopedValue
    绑定到组件实例只是一个特殊用法

    react 的思维模型是声明式+单向数据流,渲染结果是 state 的映射,脱离 state 直接操作组件本体是 anti-pattern
    xieqiqiang00
        3
    xieqiqiang00  
       2023-03-14 16:47:11 +08:00
    有些组件是受控组件,由它的父组件的状态来管理,这时候要是直接被别的组件随便改了就出现意料之外的情况了。而且组件是否刷新也要根据状态来定,并且有明确的层级关系才方便确定哪些组件需要刷新。并且组件也不是一直存在的,随时都会创建和销毁
    wanguorui123
        4
    wanguorui123  
       2023-03-14 16:50:31 +08:00   ❤️ 1
    因为有些特殊功能需要通过 MVP 模式实现
    moen
        5
    moen  
       2023-03-14 17:10:16 +08:00
    可是 WPF 下直接操作组件本身就是 anti-pattern
    wu67
        6
    wu67  
       2023-03-14 17:15:48 +08:00
    react 我玩得不多.
    vue 的话, 主要是配合一些三方库的时候, 尤其是需要对 dom 进行操作时(例如部分视频播放器的初始化), 会很有用. 避免了你去手动操作 dom.
    journalistFromHK
        7
    journalistFromHK  
       2023-03-14 17:20:01 +08:00 via iPhone
    vue react 这种的最后都会把页面弄成一个超大的 js…加入 ref 才方便找到元素吧 我猜
    gam2046
        8
    gam2046  
       2023-03-14 17:23:07 +08:00
    WPF 的 Name 就相当于 DOM id ,你为每个组件指定了 id,随时都可以 document.getElementById ,只是前端不要求你强制设置 id 属性而已。

    但是你啥都通过 id 一把梭上去改了,就不需要 vue 这样的框架了
    summerLast
        9
    summerLast  
       2023-03-14 17:30:36 +08:00
    template 和 js 是两套写法,通过 ref 写法 ,只是一个桥
    sparklee
        10
    sparklee  
       2023-03-14 17:31:40 +08:00
    就是为虚拟 dom 指定与页面 dom 之间的关联 key, 我的理解
    WangLiCha
        11
    WangLiCha  
    OP
       2023-03-14 17:55:39 +08:00
    @moen 也不能说操作,不过确实少数特殊场景下确实直接操作或者读取控件是比较方便的,WPF 可以这样做(虽然我知道并不推荐),但是前端框架对此的限制感觉要严格得多,想知道这是为什么
    joesonw
        12
    joesonw  
       2023-03-14 20:44:46 +08:00 via iPhone
    @WangLiCha 谁都能随便改来改去,人多了这项目怎么写,看 render function 就没意义了,render 出来别人也可能改掉了。mvvm 的概念就是 view = f(view model)。view 的改变要通过改变 viewModel 来触发 f 重新渲染。
    anonymous2351d00
        13
    anonymous2351d00  
       2023-03-14 21:27:21 +08:00
    我粗略的理解
    - ref = 引用
    - 在数据层面 ref 大概就是指针?指向内存
    - 在视图层面 ref 大概也是指针?指向视图元素所对应的 object/类 /实体
    jsun
        14
    jsun  
       2023-03-14 21:47:13 +08:00
    现在前端框架的思想是数据驱动视图,要根据数据进行渲染,ref 更多是为了一些特殊场景准备的。
    Rocketer
        15
    Rocketer  
       2023-03-14 22:03:26 +08:00 via iPhone
    angular 也有 ref ,但无论哪个前端框架,直接操作 ref 都是不推荐的。理想状态下所有操作都应该通过属性或者状态管理实现,除非实在不行。

    类似的还有 formcontrol ,实在是恶心至极
    daysv
        16
    daysv  
       2023-03-14 22:37:17 +08:00
    因为 ocaml 有 ref
    mingwiki
        17
    mingwiki  
       2023-03-14 22:38:16 +08:00
    有一个原生的 ref 叫 weakRef 是为了防止被垃圾回收的 我觉得是一个作用
    xiangyuecn
        18
    xiangyuecn  
       2023-03-14 22:46:05 +08:00
    有了 ref ,就能直接访问到目标实例的方法、属性,大幅减少代码量,简单易懂🐶
    IvanLi127
        19
    IvanLi127  
       2023-03-14 23:29:42 +08:00 via Android
    1. 为了写高性能代码
    2. 为了操作更底层的对象
    cyitao
        20
    cyitao  
       2023-03-14 23:50:58 +08:00
    你可以通过 window.divId 获取到 id 为 divId 的 dom 实例。
    zxCoder
        21
    zxCoder  
       2023-03-15 09:25:10 +08:00
    别问,问就是前端工程化
    azcvcza
        22
    azcvcza  
       2023-03-15 09:50:11 +08:00
    用来搞一些比较接近 dom 的操作。在页面读取文件的时候,拿 state 去存总是拿不到的时候,只能上 ref 了
    jchnxu
        23
    jchnxu  
       2023-03-15 09:50:22 +08:00
    因为大部分变量都是 immutable ,或者你至少要用 immutable 的思路去用。实在没法 immutable 的东西,就用个引用来解决

    原生的 UI 框架 WPF / Cocoa 之类的 基本没有走 immutable 这条路,所以不需要
    8XIQz5SCHX1U6c7s
        24
    8XIQz5SCHX1U6c7s  
       2023-03-15 14:26:26 +08:00
    vue 、react 等框架目的不就是为了避免直接操作 dom (比如 jq ),ref 相当于后门?
    SilentDepth
        25
    SilentDepth  
       2023-03-16 20:39:51 +08:00
    Vue 、React 等视图框架的目的是让开发者可以更方便地实现界面而无需过分关心底层元素的操作过程。但有时候我们就是需要直接访问底层元素,比如我们的业务无法通过视图框架直接实现,或者我们需要使用一些第三方库来实现业务而第三方库的工作机制独立于视图框架之外。这个时候就需要视图框架提供一种机制来让开发者可以访问到底层元素。在 Vue 和 React 中,这个机制就是 ref 。

    在常规 Web 开发中,你给元素加上一个 id 也能实现类似的效果,不论是通过 window.<id> 还是 document.getElementById(<id>)。但一来这需要你处理可能的命名冲突,二来这需要你自行实现读写和缓存的逻辑,开发体验就不太好。另外,Vue 和 React 都有意区分数据结构和渲染目标的概念,甚至允许你自行实现一个渲染器。那当一个 Vue/React App 渲染的不再是一个普通的 DOM 树,没有 id 机制,怎么办?这时你只能靠 ref 机制了。
    momocraft
        26
    momocraft  
       2023-03-17 16:00:11 +08:00
    1. 让你的代码能访问到 instance (DOM element 或框架 component) 的方法
    2. 让你的代码有一个 在整个 component lifecycle 中稳定的 box
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5271 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 03:46 · PVG 11:46 · LAX 19:46 · JFK 22:46
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.