Как получить HTMLElements в слотах с помощью vue3?

Что-то случилось, когда я пытался разработать компонент слоя. Вот код:

// Wrapper.vue

<template>
  <slot v-bind = "attrs"></slot>
</template>

<script lang = "ts" setup>
import {
  defineProps,
  ref,
  watch,
  useAttrs,
  onMounted,
  onUnmounted,
  getCurrentInstance,
} from "vue";

const props = defineProps({
  name: { type: String, default: "" },
  zIndex: { type: Number, default: 0 },
});
const attrs = useAttrs();
const inst = getCurrentInstance();

const observer = ref<MutationObserver | null>(null);

watch(
  () => [props.zIndex, props.name],
  () => {
    setBrothersAttrs();
  }
);

onMounted(() => {
  let el = inst?.vnode.el;
  if (el) {
    if (!observer.value)
      observer.value = new MutationObserver(setBrothersAttrs);
    observer.value.observe(el.parentElement, { childList: true });
  }
  setBrothersAttrs();
});

onUnmounted(() => {
  if (observer.value) observer.value.disconnect();
});

const setBrothersAttrs = () => {
  let el = inst?.vnode.el;
  let children = el?.parentElement?.children;
  if (el && children) {
    for (let i = 0; i < children.length; i++) {
      let bro = children[i];
      if (bro === el) continue;
      bro.style.zIndex = props.zIndex;
    }
  }
};
</script>

// Тест.vue

<template>
  <div class = "test">
    <Wrapper name = "wrapper1" :z-index = "1">
      <img class = "picture1" />
      <div class = "inner">
        <Wrapper name = "wrapper2" :z-index = "2">
          <img class = "picture2" />
        </Wrapper>
      </div>
      <Wrapper name = "wrapper3" :z-index = "3">
        <img class = "picture3" />
      </Wrapper>
    </Wrapper>
  </div>
</template>

<script lang = "ts" setup>
import Wrapper from "./Wrapper.vue";
</script>

// Результат в HTML:

<div class = "test">
  <img class = "picture1" style = "z-index: 1" /><!-- if no wrapper3, "z-index: 3" -->
  <div class = "inner" style = "z-index: 1">
    <img class = "picture2" style = "z-index: 2" />
  </div>
  <img class = "picture3" style = "z-index: 1" /><!-- if no wrapper3, "z-index: 3" -->
</div>

Как видно из приведенного выше кода, компонент Wrapper является пустым компонентом. Его цель - установить z-индекс HTMLElements в слоте ["по умолчанию"].

К сожалению, я не могу найти дочерние элементы в useSlots()["default"]. Поэтому я пытаюсь позволить наблюдателю мутаций наблюдать за дочерним списком родителя.

Он отлично работает в одиночку (например, picture1 и picture2 в примере). Но он переопределяет друг друга, когда несколько Wrapper объединяются (например, picture3 в примере, z-индекс picture3, установленный wrapper3, переопределяется wrapper1). Это означает, что они имеют одного и того же родителя, так что потомки родителя всегда будут одинаковыми.

Итак, теперь проблема снова стала «Как получить HTMLElements в слотах» ... Может ли какой-нибудь мастер vuejs мне помочь?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
2
0
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это можно было бы сделать намного проще, используя функции рендеринга Vue: Слоты рендеринга

const { createApp, h } = Vue;

const Wrapper = {
  props:  {
    name: { type: String, default: "" },
    zIndex: { type: Number, default: 0 },
  },
  setup(props, { slots }) {
    let children = slots.default();
    if (children) {
      for (let i = 0; i < children.length; i++) {
        children[i].props.style = `z-index: ${props.zIndex}`;
      }
    }  
    return () => slots.default()
  }
}

const App = { 
  components:  { Wrapper }
}

const app = createApp(App)
const vm = app.mount('#app')
#app { line-height: 2; }
[v-cloak] { display: none; }
<div id = "app" v-cloak>
   <div class = "test">
   Test
    <Wrapper name = "wrapper1" :z-index = "1">
      <img class = "picture1" />
      <div class = "inner">
        <Wrapper name = "wrapper2" :z-index = "2">
          <img class = "picture2" />
        </Wrapper>
      </div>
      <Wrapper name = "wrapper3" :z-index = "3">
        <img class = "picture3" />
      </Wrapper>
    </Wrapper>
  </div>
</div>
<script src = "https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>

Спасибо за ваш ответ. h('div', slots.default()) Этот код создает элемент div, который не соответствует моим потребностям. Я не хочу создавать какой-либо элемент в качестве дочернего родителя, но хочу изменить дочерние атрибуты. Возможно ли это?

XUX 25.04.2023 04:03

Вам действительно не нужно div. Я обновил игровую площадку.

Tolbxela 25.04.2023 09:18

Другие вопросы по теме