【Vue3】自定义组件嵌套

实现效果

  1. 最底部输入框输入文本,点击发送广播按钮
  2. 当前页面其他所有input亮起,
  3. 点击任意亮起input,将输入文本复制至当前input

注:input可能穿插至当前页面任何地方,所以不能通过循环生成input

【Vue3】自定义组件嵌套_第1张图片
【Vue3】自定义组件嵌套_第2张图片
【Vue3】自定义组件嵌套_第3张图片

使用组件嵌套实现(同组件相似)

  • 当前页面
<script setup>
import { ref } from 'vue'
import YysFather from './components/yys-father.vue'
import YysChildren from './components/yys-children.vue'

// 页面组件
const father = ref(null)

// 广播数据
const message = ref('')

// 当前输入框
const input1 = ref('')
const toShow1 = t => (input1.value = t)
const input2 = ref('')
const toShow2 = t => (input2.value = t)
const input3 = ref('')
const toShow3 = t => (input3.value = t)
const input4 = ref('')
const toShow4 = t => (input4.value = t)

const sendBroadcast = () => {
  father.value.open(message.value)
}
script>

<template>
  <yys-father ref="father">
    <yys-children name="name1" @toShow="toShow1">
      <el-input v-model="input1" />
    yys-children>
    <yys-children name="name2" @toShow="toShow2">
      <el-input v-model="input2" />
    yys-children>
    <yys-children name="name3" @toShow="toShow3">
      <el-input v-model="input3" />
    yys-children>
    <yys-children name="name4" @toShow="toShow4">
      <el-input v-model="input4" />
    yys-children>
  yys-father>
  <el-input v-model="message" placeholder="Please input">
    <template #append>
      <el-button type="text" @click="sendBroadcast()">触发广播el-button>
    template>
  el-input>
template>
  • 组件一:父级组件(所有input都在当前组件内)
<script setup>
import { provide, ref, defineExpose, computed } from 'vue'

// 是否高亮
const isR = ref(false)
provide(
  'isHighlight',
  computed(() => isR.value)
)
// 广播文本
const text = ref('')
provide(
  'text',
  computed(() => text.value)
)

// 取消事件
provide('uncheck', () => {
  isR.value = false
})

// 点击广播
const open = _t => {
  isR.value = true
  text.value = _t
}

defineExpose({ open })
script>

<template>
  <div class="page">
    <slot />
  div>
template>

<style lang="scss" scoped>
.page {
  margin: 20px;
}
style>
  • 组件二:子级组件(每个input需要放在该组件中)
<script setup>
import { ref, inject, defineEmits } from 'vue'

// 接收参数
const props = defineProps({
  name: {
    type: String,
    required: true
  }
})

// 发送方法
const emit = defineEmits(['toShow'])

// 是否高亮
const isRed = ref(inject('isHighlight'))

// 广播文本
const text = ref(inject('text'))

// 取消报红事件
const uncheck = inject('uncheck')

// 点击输入框
const clickChildren = () => {
  if (isRed.value) {
    uncheck()
    emit('toShow', text.value)
  } else {
    console.log('无效点击')
  }
}
script>

<template>
  <div class="page" :class="isRed ? 'isHighlight' : ''" @click="clickChildren">
    <slot />
  div>
template>

<style lang="scss" scoped>
.page {
  margin-top: 20px;
}
.isHighlight {
  ::v-deep(.el-input__inner) {
    border: 1px solid red;
    border-radius: 4px;
  }
}
style>

你可能感兴趣的:(Vue3,vue.js,javascript,前端)