如何使用 VueJs 3 组合 api 中的 Mounted 函数?

Max*_*ern 11 vue.js vue-composition-api

我正在尝试 vueJs 3 中的组合 api。不幸的是我不知道如何在 setup() 中包含我安装的代码。当我将代码放入设置中时,JavaScript 会尝试访问尚未渲染的 DOM。谁能告诉我如何重写这个?

选项 api 风格(有效)

<script>
export default {
    name: "NavBar",
    data() {
        return {};
    },
    methods: {},
    mounted() {
        const bm = document.querySelector('#toggle');
        const menu = document.querySelectorAll('nav ul li');
        const overlay = document.querySelector('#overlay');

        // ...
        bm.addEventListener('click', () => {  
            bm.classList.toggle("active");
            overlay.classList.toggle("open");
        })
 
    },
}
</script>
<template>
    <header>
        <div class="button_container" id="toggle">
          <span class="top"></span>
          <span class="middle"></span>
          <span class="bottom"></span>
        </div>
        <div class="overlay" id="overlay">
          <nav class="overlay-menu">
            <ul>
            <li><a href="#home">Home</a></li>
            <!-- ... -->
            </ul>
          </nav>
        </div>      
    </header>    
</template>
Run Code Online (Sandbox Code Playgroud)

Den*_*han 8

    \n
  1. 首先,这不是一个通过 获取 html 元素的好习惯document.querySelector(),请参阅如何在 vue3 中绑定事件
  2. \n
\n
// bad\n\n<div class="button_container" id="toggle">...</div>\n\nmounted() {\n    const bm = document.querySelector(\'#toggle\');\n    bm.addEventListener(\'click\', () => {  \n        bm.classList.toggle("active");\n        overlay.classList.toggle("open");\n    })\n}\n\n// good\n<div class="button_container" id="toggle" @click="toggleContainer">...</div>\n\nmethods: {\n    toggleContainer() {\n        ...\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 如果你真的想document.querySelector()setup()\xef\xbc\x8c 中,你可以使用onMounted
  2. \n
\n
import { onMounted } from \'vue\';\n\nexport default {\n    setup() {\n        onMounted(() => {\n             const bm = document.querySelector(\'#toggle\');\n             bm.addEventListener(\'click\', () => {  \n                 bm.classList.toggle("active");\n                 overlay.classList.toggle("open");\n             })\n        });\n    }\n}\n\n// or inside <script setup>\n\nimport { onMounted } from \'vue\';\n\nonMounted(() => {\n   ....\n});\n
Run Code Online (Sandbox Code Playgroud)\n

但是,正如@kissu评论的那样,ref如果你必须直接在 vue 中处理 html 标签,这是一个更好的方法

\n
<div\n   ref="toggler">\n   ...\n</div>\n\n<script setup>\nimport { ref, onMounted } from \'vue\';\n\nconst toggler = ref(null);\n\nonMounted(() => {\n    console.log(toggler.value) // <div></div>\n});\n</script>\n\n
Run Code Online (Sandbox Code Playgroud)\n
    \n
  1. 但以上都没有遵循Vue的理念,即Vue是由数据驱动的
  2. \n
\n

由于您似乎创建了一个单击事件侦听器,它将影响 html 中的类,因此这是 Vue 方式:

\n
<template>\n    <header>\n        <div\n          class="button_container"\n          id="toggle"\n          :class="{\n             \'active\': isActiveBm\n          }"\n          @click="toggle">\n          <span class="top"></span>\n          <span class="middle"></span>\n          <span class="bottom"></span>\n        </div>\n        <div\n          class="overlay"\n          id="overlay"\n          :class="{\n             \'open\': isOpenOverlay\n          }">\n          <nav class="overlay-menu">\n            <ul>\n            <li><a href="#home">Home</a></li>\n            <!-- ... -->\n            </ul>\n          </nav>\n        </div>      \n    </header>    \n</template>\n\n<script setup>\nimport { ref } from \'vue\';\n\nconst isActiveBm = ref(false);\nconst isOpenOverlay = ref(false);\n\nconst toggle = () => {\n    isActiveBm.value = !isActiveBm.value;\n    isOpenOverlay.value = !isOpenOverlay.value;\n}\n</script>\n
Run Code Online (Sandbox Code Playgroud)\n