V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mostkia
V2EX  ›  Vue.js

vue 是不是在理论上,任何情况下都不需要操作 dom?

  •  
  •   mostkia · 2022-04-04 07:59:16 +08:00 · 4146 次点击
    这是一个创建于 998 天前的主题,其中的信息可能已经有所发展或是发生改变。
    请教一下,vue 是不是在理论上,任何情况下都不需要操作 dom ?看到 vue 的官方说明里提到,尽量不要操作 dom ,应该交给 vue 来处理。

    但某些情况下似乎的确得操作 dom ,比如点击时一个 dom 时需要操作另外一个 dom 时(后来发现可以在 data 里面写个对象,然后让另外一个 dom 监视它做出反应,而 on 方法里直接改这个对象就行),但我很清楚,因为我比较熟悉传统写法,而新学 vue ,总会有 vue 写法暂时无法解决但直接操作 dom 能解决的事情,一方面想引经据典,尽量不操作 dom ,一方面一个现成方案摆在眼前不用真的有些眼馋。

    有时候总在想,是不是 vue 有更好的方法解决,我这样写是不是成了异端,vue 真的是能不用就不用 dom 吗?那些情况下大家都是会选择操作 dom 的?
    Biwood
        1
    Biwood  
       2022-04-04 08:14:31 +08:00 via iPhone   ❤️ 2
    是不要直接操作 DOM ,能用数据驱动界面更新更新的情况下话为什么还有写一堆繁杂的原生 JS 逻辑?这也是 Vue 这类框架存在的意义,既然用它就要适应他的思维方式

    当然,有些情况下还是需要直接访问 DOM 的,我能想到的有:
    1. 所有对 Vue 实例挂载节点之外的 DOM 操作,比如 window/document/body 这些
    2. 需要获取某些 DOM 原生属性的时候,比如 offsetHeight 之类的
    placeholder
        2
    placeholder  
       2022-04-04 08:20:03 +08:00   ❤️ 2
    你这种情况,就是应该先用你现有的知识把功能写出来,

    然后随着学习 vue 的深入,慢慢的改成 vue 提供的方式或者方法。

    不用太过纠结。
    mostkia
        3
    mostkia  
    OP
       2022-04-04 08:22:25 +08:00
    @Biwood 好的,第二种情况下,好像都是需要操作 dom 的,比如获取到 html 标签内容,一些属性等。一般来讲需要 js 里获取的数据都是双向绑定的,但也不排除偶尔需要获取到没绑定变量的写死标签里的内容或属性
    mostkia
        4
    mostkia  
    OP
       2022-04-04 08:24:57 +08:00
    @placeholder 好的,我也是这样想的,有得选的话,肯定是优先使用 vue 的方案来解决问题,尽量的适应 vue 的写法,这种情况下可能脑子里清空旧知识反而学 vue 会快一些,我碰到过一些学前端的,dom 都操作不来,但不影响他们写页面😂
    Kawa
        5
    Kawa  
       2022-04-04 08:55:30 +08:00 via Android   ❤️ 1
    别问, 问就是写着写着 Vue 就想引入一个 jQuery
    Vue 绝大部分情况下不需要操作 DOM, 但是一旦需要操作就是痛苦面具, 特别是用了 ts+setup 的情况, 写起来是真的蛤人.
    IvanLi127
        6
    IvanLi127  
       2022-04-04 09:21:32 +08:00 via Android   ❤️ 1
    能用 Vue 做数据驱动就用 Vue 做,不能就直接操作 DOM 。不过,直接操作 DOM 的,包在 Vue 组件内,比较雅观。
    IvanLi127
        7
    IvanLi127  
       2022-04-04 09:23:00 +08:00 via Android   ❤️ 1
    @IvanLi127 补充下: 我的意思是需要 DOM 操作的元素单独放在一个组件内。
    Cbdy
        8
    Cbdy  
       2022-04-04 09:29:38 +08:00 via Android   ❤️ 1
    有一些操作还是需要操作 DOM 的,所以 Vue 也提供了 ref API
    sadfQED2
        9
    sadfQED2  
       2022-04-04 09:36:23 +08:00 via Android   ❤️ 1
    😂我们公司的屎山项目就是 vue+jquery ,结果就是你永远不知道某个 ui 为啥消失出现
    des
        10
    des  
       2022-04-04 09:48:59 +08:00 via iPhone   ❤️ 1
    是容易出现 9 楼那种问题,而且容易有 bug
    类比一下,你可以想象一个提线木偶。然后木偶的动作( html 显示什么)都是通过线( bind )由你(数据)来控制的
    至于和 dom 直接互动建议用 ref

    另外你说的眼馋不会指的是 jQuery 吧?
    Desiree
        11
    Desiree  
       2022-04-04 09:57:05 +08:00   ❤️ 2
    不要为了用框架而用框架,先理解框架是为了解决什么问题。
    jorneyr
        12
    jorneyr  
       2022-04-04 10:21:26 +08:00   ❤️ 1
    写 directive 的时候可能会用到,例如 DOM 获取焦点,创建一些子 DOM 。
    statumer
        13
    statumer  
       2022-04-04 11:25:04 +08:00   ❤️ 1
    楼主应该是还没学会 Vue 的状态管理库吧,不会跨组件控制
    mostkia
        14
    mostkia  
    OP
       2022-04-04 11:26:59 +08:00
    @Kawa 是挺纠结的,偶尔需要操作一下 dom 时,原生代码真的老大一串,引入的话,又是很大的一个文件。所以说还是会点原生 js 比较好
    mostkia
        15
    mostkia  
    OP
       2022-04-04 11:30:17 +08:00
    嗯,$ref 这玩意儿挺好使的,也是官方提供的。
    mostkia
        16
    mostkia  
    OP
       2022-04-04 11:32:10 +08:00   ❤️ 1
    @sadfQED2 笑死,所以官方才不推荐这样操作吧,vue:肯定 jquery 干的,我没动过这 dom 。jquery:莫挨老子,我都没读取过这 dom 节点🤣
    mostkia
        17
    mostkia  
    OP
       2022-04-04 11:37:05 +08:00
    @des 不是,眼馋是指有些情况下需要某个标签的属性或者 text 内容,或者跨节点操作,vue 似乎不提供现成方法,这时就很想拿到 dom 来操作,我之前写原生 js 比较多,习惯还一下子改不过来。
    mostkia
        18
    mostkia  
    OP
       2022-04-04 11:40:06 +08:00
    @statumer 你说的是 vuex 吗?那个的确没学,我看文档才一周不到,现在刚刚用顺手 vue ,至少不是负效率写页面了,现在觉得还是挺香的,小项目使用$ref 偶尔协调一下应该够用了,毕竟需要直接操作 dom 的场景不多
    mostkia
        19
    mostkia  
    OP
       2022-04-04 11:41:22 +08:00
    @IvanLi127 好的,感谢,我会作为参考的
    mostkia
        20
    mostkia  
    OP
       2022-04-04 11:45:03 +08:00
    @sadfQED2 jquery 要用也是配合 vue 的逻辑用比较好,大范围的独立于 vue 之外干预 vue 控制的 dom 的确是个烂主意
    GeruzoniAnsasu
        21
    GeruzoniAnsasu  
       2022-04-04 13:45:31 +08:00   ❤️ 4
    @mostkia 我后端写得多一些,半吊子前端。反正我的感觉是,vue 的设计目标就是数据-视图的自动渲染器,因为我的思维都是从后端出发的,所以好像没感觉到什么 需要 获得 dom 来取得里面数据的场景。

    比方说你想拿到「某个标签的内容」,按我的自然思路是,这个内容应该也是某组数据渲染出来的,那我直接用数据不就好了,如果不存在,那是这个组件有问题,我得改这个组件让它能提供一个暴露数据的接口

    如果是想「修改另一个节点的状态」,那也应该是节点 /组件各司其职,提供一个 emit 来让别人通知节点自己变更状态。这个思路跟桌面 GUI 是一样的,qt 那的 signal/slots 跟 vue 的 emits 基本上是同一种东西

    -------

    可能也是写过桌面 GUI 的原因,我是很忌惮直接去改变非自控 dom 的状态的,因为在桌面 GUI 程序里这样写是大忌——很容易搞不清自己当前在哪个线程里。跨线程去操作 ui 组件容易引发访问违例、死锁、竞争等各种各样奇怪的问题,所以传统桌面 GUI 的程序一律在使用各种事件去通知组件重绘自己的内容。这跟传统 js 出来的「宏状态」一把梭,一个位置掌控全页面 dom 的思路就很不一样。我倒是「天生更适应现代的前端框架」
    nomagick
        22
    nomagick  
       2022-04-04 14:28:48 +08:00   ❤️ 1
    既然你已经会操作 Dom 并且知道有些事 Vue 做不了,那么你已经超过 99.9%的 Vue 用户并且不是 Vue 的目标用户群。
    这个时候你就果断根据自己的判断行动就可以了。

    当它能够帮你的时候就酌情用用,帮不了你也别把它奉若圭臬。
    doommm
        23
    doommm  
       2022-04-04 17:29:14 +08:00 via Android   ❤️ 1
    我感觉这不是哪一个框架的问题,而是一个编程思维(或者说编程模型?)的问题。
    直接操作 dom 当然是被允许的,某些情况下是必须这么做的,但前提是遵守 vue 的一些规定,否则就会出问题。建议去看看 vue 的文档的相关部分
    mostkia
        24
    mostkia  
    OP
       2022-04-04 21:08:58 +08:00
    好的,感谢,人总是得从群体中汲取智慧,车辙印虽然可能不好走,但肯定也不会把自己带进坑里,问一下大家的看法还是很有必要的 @nomagick @doommm
    mostkia
        25
    mostkia  
    OP
       2022-04-04 21:45:56 +08:00
    其实前端 js 从底层设计就是基于 dom 操作视图的,所有 api 都是围绕这个目标设计的,并没有一个统一的 dom 状态管理器,没人干的活,原生 js 挑大梁自己干自然不存在你说的这种冲突。vue 这类库算是走出了第一步吧,但的确还不够健壮,还不能覆盖开发的方方面面,手动操作 dom 可以作为点缀,不能喧宾夺主,并行和 vue 两套逻辑各自争夺 dom 的控制权,我想这就是 vue 文档里说的意思吧。这里还是提出一个问题,不是抬杠啊,是实在我也不知道在 vue 里面该用什么方案解决比较好,比如要完整移动一个 dom (包括它绑定的事件,所以不能以拷贝节点方式实现,vue 中没提供相关方法,应该只能直接操作其 dom )这在拖拽功能中是很常见的一类需求。
    mostkia
        26
    mostkia  
    OP
       2022-04-04 21:46:28 +08:00
    mostkia
        27
    mostkia  
    OP
       2022-04-04 21:48:09 +08:00
    忽然发现自己开发的一套轻量化的 MVC 组件非常适合和 vue 互补,哪天有空开源算了
    Biwood
        28
    Biwood  
       2022-04-05 09:33:06 +08:00 via Android
    @mostkia 你说的拖拽和拷贝这类操作其实不适合用 vue 来写,vue 适合做那种丰富的数据展示和数据流动的系统。拖拽这类虽然 vue 也能写,也有已经封装好的插件,但是总归是不够灵活,会有很多必须按照 vue 的方式来写的约束。这种情况一般直接用一些第三方的轻量级的纯 JS 插件也是可以的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   946 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 21:33 · PVG 05:33 · LAX 13:33 · JFK 16:33
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.