Vue不推荐开发者直接操作dom(当然这并不表示不能这么做),有以下几个原因:

  1. 破坏了代码模块化结构导致代码腐化:

组件原本可以控制哪些dom操作可以对外暴露(即对应methods中的方法),但直接操作dom跳过了这个控制,这会导致不可预料的后果。

例如组件A中有一个输入框,且组件A没有暴露可以删除输入框的方法,此时组件A会认为输入框是必定存在的,可以放心获取输入框的信息,但在其他组件中通过直接操作dom的方式删除了这个输入框,组件A无法感知,此时获取输入框信息时就会出错。

而当直接操作dom的行为随着项目代码的膨胀越来越多时,项目代码会趋于腐化,当组件数量达到一定程度时,定位直接操作dom导致的问题耗时会呈指数级上升,这对多人参与开发的项目来说灾难性的。

用上面给出的例子来说,如果组件A的开发者不是直接操作dom行为的作者,那对这个开发者而言,定位输入框究竟在哪里被删掉了无疑是恐怖的:

任何一个组件都有可能这么做,要定位就必须一个组件一个组件排查;
即使运气不错很快排查到问题所在,也不敢随便改动,因为不清楚在其他组件里为什么要这么做,是逻辑设计的漏洞,还是代码出了bug,只有写这块逻辑的人才知道;
最可怕的是,开发者不知道以后还会有多少这样的问题,如果是个通用模块或基础组件,也许隔三差五就要来这么一次。

  1. 过多的直接操作dom行为增加了代码的耦合性:

当包含直接操作dom行为的组件在别处使用时,直接操作dom的代码有可能不可用。

如果直接操作dom的代码没有检查dom状态或没有严格检查dom是否为想要操作的dom,则直接复用可能导致不可预料的后果,即意味着这个组件只能在特定位置使用,耦合性提高,复用性降低。

  1. 操作不属于自己的dom时,dom状态无法预知:

dom归属于其他组件时,dom可能没有生成,也有可能dom所属组件并没有被加载或使用。

如dom所在组件用v-if控制了dom的隐藏/显示,这样就必须在操作dom之前判断dom的状态,增加了冗余代码;

组件状态的变化可能导致获取到的dom不是预想的dom。

如本来想获取组件A下的class为xxx的dom,但获取dom时组件A已经被替换为组件B,而组件B内恰好同样有class为xxx的dom,这样如果没有严格检查的话很容易操作了错误的dom。

下面上一个简单的例子,组件container会操作不属于自己的span元素,进而导致原span元素上的cilck行为失效:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jquery</title>
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
</head>
<body>
<div id="app">
    <div class="infoContainer">
        <span class="getInfo">getInfo</span>
    </div>
    <container></container>
</div>
<script>
    Vue.component('container', {
        template: '<div><button type="button" @click="change">change</button></div>',
        methods: {
            change: function () {
                $(".getInfo").remove();
                $(".infoContainer").append('<span class="getInfo">getInfo</span>');
            }
        }
    });
    new Vue({
        el: '#app',
        mounted: function () {
            $(this.$el).find(".getInfo").on("click", function () {
                console.log("it is app");
            });
        }
    });
</script>
</body>
</html>

效果如下图:
在这里插入图片描述

可以看到初始span元素的click事件可以正常执行(即控制台正常打印it is app信息),当触发组件container更新span元素后,click事件失效了。

Logo

前往低代码交流专区

更多推荐