Vue 如何实现获取 dom 元素(父组件获取子组件的dom / ref),真的很详细

在 Vue.js 中,获取 DOM 元素和使用 ref 是两种不同的概念,它们在构建组件时扮演着重要的角色。理解它们的基本用途和获取方式对于父子组件间的通信至关重要。

基本概念介绍

Vue 中的 DOM 元素

在 Vue 中,DOM 元素通常指的是由 Vue 实例管理的 HTML 元素。Vue 使用虚拟 DOM 来提高性能,这意味着实际的 DOM 操作比传统方法更少、更高效。

ref

ref 是 Vue 中的一个属性,用于给元素或子组件注册引用信息。引用信息将会在组件的 $refs 对象上注册。你可以使用 ref 来访问 DOM 元素或子组件实例。

父子组件通信

父子组件通信的基本机制

Vue 的组件系统是树形结构的,父子组件之间的通信是开发中常见的需求。父组件可以通过 props 向子组件传递数据,子组件可以通过 $emit 向父组件发送事件。

示例代码

父组件
<template>
  <div>
    <child-component :parent-message="message" @child-emit="handleChildEmit" />
    <button @click="requestChildRef">获取子组件 DOM</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  data() {
    return {
      message: '来自父组件的消息'
    };
  },
  methods: {
    handleChildEmit(childData) {
      console.log('子组件发送的数据:', childData);
    },
    requestChildRef() {
      this.$refs.childComponentMethod();
    }
  }
};
</script>
子组件
<template>
  <div ref="childRef">
    <p>{{ parentMessage }}</p>
    <button @click="emitToParent">发送消息到父组件</button>
  </div>
</template>

<script>
export default {
  props: ['parentMessage'],
  methods: {
    emitToParent() {
      this.$emit('child-emit', '来自子组件的消息');
    }
  }
};
</script>

在上述代码中,父组件通过 props 向子组件传递了一条消息,并定义了一个按钮来触发获取子组件 DOM 的操作。子组件有一个按钮,当点击时会通过 $emit 发送消息回父组件。

讲解

  • 在父组件中,我们使用 :parent-message 将消息传递给子组件,并监听 child-emit 事件来接收子组件的消息。
  • 子组件使用 $emit 方法来触发事件,并向父组件发送数据。
  • 父组件通过 $refs 获取子组件的 DOM 元素或方法。在这个例子中,我们通过 ref="childRef" 注册了子组件的 DOM 引用,并在按钮的点击事件中通过 this.$refs.childComponentMethod() 调用子组件的方法。

 

$refs 的使用

在 Vue 中,$refs 是一个对象,其中包含了所有带有 ref 属性的子组件和 DOM 元素。通过 $refs,父组件可以访问子组件的 DOM,但这通常不是推荐的做法,因为 DOM 应该通过组件的 props 和 events 来操作。

示例代码

子组件
<template>
  <div ref="childDiv">
    <p>这是一个子组件的 DOM 元素。</p>
    <button @click="clickMe">点击我</button>
  </div>
</template>

<script>
export default {
  methods: {
    clickMe() {
      // 子组件的方法,可以在这里触发事件到父组件
    }
  }
};
</script>
父组件
<template>
  <child-component ref="myChild" />
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  mounted() {
    this.$nextTick(() => {
      // 访问子组件的 DOM 元素
      console.log(this.$refs.myChild.$el); // 子组件的根 DOM 元素
    });
  }
};
</script>

在上述代码中,父组件通过 ref="myChild" 引用了子组件,然后在 mounted 钩子中访问了子组件的 $el,即子组件的根 DOM 元素。这种方法可以用来在父组件中获取子组件的 DOM,但请注意,这通常不是 Vue 推荐的做法,因为它破坏了组件的封装性。

ref 的作用和使用场景

ref 的作用域

ref 在 Vue 中的主要用途是给元素或子组件注册引用信息。ref 被注册在父组件的 $refs 对象上,以便访问。

使用场景

  • 访问子组件的方法或数据:当需要从父组件调用子组件的方法或访问其数据时。
  • 操作特定的 DOM 元素:在极少数情况下,如果需要直接操作 DOM,可以使用 ref 来引用特定的元素。

示例代码

子组件
<template>
  <input ref="inputField" type="text" />
</template>
父组件
<template>
  <child-component ref="myInput" />
  <button @click="focusInput">聚焦输入框</button>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    focusInput() {
      this.$refs.myInput.$refs.inputField.focus();
    }
  }
};
</script>

在上述代码中,子组件中的 <input> 元素被赋予了 ref="inputField"。在父组件中,我们通过 ref="myInput" 引用了子组件,并在按钮的点击事件中调用了子组件的 focus 方法来聚焦输入框。

$refs 的限制

使用 $refs 时存在一些限制:

  • $refs 不能用于获取子组件内部的子组件实例或 DOM 元素。
  • $refs 只能在组件渲染完成后使用,即 mounted 钩子之后。
  • 由于 $refs 是同步的,它们不能与异步更新一起使用。

注意事项

  • 避免过度依赖 $refs,因为这可能导致组件耦合增加,难以维护。
  • 使用 $refs 时,确保不要在模板字符串中使用它们,因为这会导致引用失效。
  • 组件销毁后,应该清除 $refs,避免内存泄漏。

示例代码

子组件
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '子组件的消息'
    };
  }
};
</script>
父组件
<template>
  <div>
    <child-component ref="myChild" />
    <button @click="accessChildComponent">访问子组件实例</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    accessChildComponent() {
      // 访问子组件实例
      console.log(this.$refs.myChild.message);
    }
  }
};
</script>

使用 $refs 获取子组件实例

获取子组件实例的方法

在某些情况下,你可能需要通过 $refs 获取子组件的实例,以便访问其方法或数据。然而,这通常不是推荐的做法,因为它破坏了组件的封装性。

示例代码

子组件
<template>
  <div>
    <p>{{ localMessage }}</p>
    <button @click="updateMessage">更新消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      localMessage: '初始消息'
    };
  },
  methods: {
    updateMessage() {
      this.localMessage = '更新后的消息';
    }
  }
};
</script>
父组件
<template>
  <div>
    <child-component ref="myChild" />
    <button @click="updateChildMessage">更新子组件消息</button>
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    updateChildMessage() {
      // 直接更新子组件的数据
      this.$refs.myChild.localMessage = '从父组件更新的消息';
    }
  }
};
</script>

在上述代码中,我们展示了如何通过 $refs 获取子组件实例并访问其内部数据。然而,这种方法并不是 Vue 的推荐做法,因为它破坏了子组件的独立性和封装性。

跨组件方法传递

方法传递的基本概念

在 Vue 中,跨组件传递方法通常意味着允许一个组件触发另一个组件的方法。这可以通过事件监听 ($emit) 和方法引用来实现。

示例代码

子组件
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="emitUpdate">更新消息</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '初始消息'
    };
  },
  methods: {
    emitUpdate() {
      this.$emit('update:message', '通过子组件更新的消息');
    }
  }
};
</script>
父组件
<template>
  <div>
    <child-component
      @update:message="childUpdateMessage"
    />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: {
    ChildComponent
  },
  methods: {
    childUpdateMessage(newMessage) {
      console.log('从子组件接收到的消息:', newMessage);
    }
  }
};
</script>

在上述代码中,子组件有一个按钮,当点击时会触发 emitUpdate 方法,该方法使用 $emit 发出一个自定义事件 update:message,同时传递新的信息。父组件监听这个事件,并定义了 childUpdateMessage 方法来接收和处理消息。

响应式 ref 更新

Vue 3 中的响应式 ref 更新

在 Vue 3 中,ref 是响应式的,Vue 会自动追踪 ref 引用的 DOM 元素的变化。但是,有时候你可能需要手动触发更新,尤其是在使用 JavaScript 直接修改 DOM 时。

示例代码

组件
<template>
  <div>
    <input ref="inputElement" type="text" />
    <button @click="forceUpdateRef">强制更新 ref</button>
  </div>
</template>

<script>
export default {
  mounted() {
    // 初始 ref 更新
    console.log(this.$refs.inputElement.value);
  },
  methods: {
    forceUpdateRef() {
      // 模拟直接修改 DOM 元素的值
      this.$refs.inputElement.value = '新值';
      // 强制更新 ref
      this.$refs.inputElement = this.$refs.inputElement;
    }
  }
};
</script>

在上述代码中,我们展示了如何在组件中使用 ref 来引用一个输入元素,并提供了一个按钮来模拟强制更新 ref 的情况。在实际使用中,通常不需要手动强制更新 ref,因为 Vue 会自动处理 ref 的响应性。

YDUIbuilder:低代码开发,高效率创造 —— Vue应用构建的智能伙伴

 开源免费下载:yduibuilder: 快速开发UI界面,原型设计即前端开发 

 YDUIbuilder,开启低代码开发的全新篇章。无需深入编码,通过直观的拖拽界面,快速构建功能强大、响应迅速的Vue应用。我们提供丰富的组件库和灵活的样式定制,让设计和开发变得简单而直观。YDUIbuilder,让创意落地,让效率倍增,是每一位前端开发者和设计师的理想选择。立即体验YDUIbuilder,释放你的创造潜能,打造令人难忘的数字体验!

YDUIbuilder开源免费低代码平台视频案列演示: 

YDBUilder可视化开发前端界面之懂车帝小程序 热门界面

 

 

 

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值