Vue CLI中同一页面复用带同名Props的组件失效问题求助
嘿,我一眼就看出你组件复用失效的核心问题了——你在操作DOM的时候用了全局选择器,这在多组件实例的场景下绝对会出问题!咱们一步步拆解问题,然后搞定它:
问题根源
你的代码里有几个关键错误:
- 全局DOM选择器冲突:
document.querySelector(".logo")会在整个页面中找第一个带.logo类的元素,当多个Logo组件渲染时,只有第一个(也就是Navbar里的那个)能被选中,后面的组件根本拿不到自己的DOM节点,样式自然无法生效。 - 生命周期钩子用错了:
created钩子执行时,组件的DOM还没挂载到页面上,这时候去查找DOM元素是不稳定的,甚至可能直接找不到。 - Props类型不规范:你传递的
size是字符串(比如"20"),虽然拼接px时能凑合用,但不符合响应式逻辑的预期,换成数字类型更稳妥。
修复方案
我们从Logo组件开始改,再调整其他组件的传值:
1. 重构Logo组件:用组件内DOM引用替代全局选择器
Vue提供了$refs来让我们安全地获取当前组件内的DOM元素,再也不会和其他组件的元素冲突了:
<template lang="html"> <div class="logoCon"> <!-- 给logo标签添加ref属性,方便组件内定位 --> <a class="logo" ref="logoNode">Some name for Logo</a> </div> </template> <script> export default { name: 'Logo', // 规范Props的类型、必填性和默认值 props: { size: { type: Number, required: true, default: 20 } }, methods: { logoSizing(size) { // 这里保留你原来的响应式布局逻辑即可 console.log('当前Logo尺寸:', size); } }, // 把created换成mounted,此时DOM已经挂载完成,可以安全操作 mounted() { // 用$refs获取当前组件内的logo元素 const logoEl = this.$refs.logoNode; // 执行尺寸计算逻辑 this.logoSizing(this.size); // 设置字号(size已经是数字,直接拼接即可) logoEl.style.fontSize = `${this.size}px`; } } </script>
2. 调整Navbar组件:传数字类型的size
把原来的字符串"20"改成数字20,同时别忘了注册Logo组件(之前的代码里没写,这也是潜在隐患):
<template lang="html"> <div class="navbarCon"> <!-- 其他导航栏代码 --> <logo :size="logoSize" /> </div> </template> <script> // 如果是单文件组件,记得导入Logo import Logo from './Logo.vue'; export default { name: 'Navbar', data: () => ({ logoSize: 20 // 字符串转数字 }), components: { Logo } // 注册Logo组件 } </script>
3. 调整Landing组件:同样传数字类型的size
把"400"改成400,确保组件注册正确:
<template lang="html"> <div class="landingCon"> <navbar /> <logo :size="logoSize" /> </div> </template> <script> // 导入需要的组件 import Navbar from './Navbar.vue'; import Logo from './Logo.vue'; export default { name: 'Landing', data: () => ({ logoSize: 400 // 字符串转数字 }), components: { Navbar, Logo } } </script>
额外优化小技巧
如果你只是设置字号,其实完全不用写JS,用Vue的样式绑定更简洁:
<template> <div class="logoCon"> <a class="logo" :style="{ fontSize: `${size}px` }">Some name for Logo</a> </div> </template> <script> export default { name: 'Logo', props: { size: { type: Number, required: true, default: 20 } } } </script>
这样连mounted钩子和方法都可以省掉,代码更清爽!
内容的提问来源于stack exchange,提问作者ErfanQSN
相关产品推荐
相关产品推荐

