Я хотел бы получить innerHTML отображаемого компонента в Vue 3, но я не понимаю, как это сделать. Я знаю, как это сделать с помощью refs в стандартной HTML-разметке, но это не работает с компонентами.

<template>
  <div>
    <div ref="hello"><span>Hello World</span></div>
    <HelloWorld ref="helloworld"><span>Hello World</span></HelloWorld>
  </div>
</template>

<script setup>
import { onMounted, ref, unref } from 'vue';
import HelloWorld from './components/HelloWorld.vue';

const hello = ref();
const helloworld = ref();

onMounted(() => {
  console.log(unref(hello).innerHTML); // <span>Hello World</span>
  console.log(unref(helloworld).innerHTML); // undefined
});
</script>

Я не использую SSR, мое текущее требование — SPA.

Мне удалось сделать это, заключив <HelloWorld> в div с идентификатором и и запросив его, но это немного дерьмово.

Любые идеи?

Благодарность!

0
Ben 4 Фев 2022 в 17:20
Вы имеете в виду ссылки на шаблон? В документации используется .value, если это имеет смысл. Я бы проверил с помощью Vue DevTools
 – 
Peter Krebs
4 Фев 2022 в 17:29
1
@PeterKrebs, unref является более приоритетным способом. позволяет избежать проблем, например, с попаданием в аргумент не Ref один. В этом примере замена unref на .value ничего не изменит.
 – 
7-zete-7
4 Фев 2022 в 17:34
Скорее всего, есть лучший способ сделать то, что вы пытаетесь сделать. Вы можете спросить о своей большей цели, а не об этой технике. См. проблему XY.
 – 
isherwood
4 Фев 2022 в 17:38

2 ответа

Добавьте ref="helloWorldRef" к компоненту, затем helloWorldRef.value?.$el это то же самое, что и document.querySelector(".hello-world"). Вы можете получить .children, .clientWidth, ... так же, как querySelector.

Обратите внимание, что необязательная цепочка необходима, потому что она может быть null, если она еще не смонтирована. Вам нужно будет что-то реализовать, чтобы убедиться, что оно доступно и назначено.

Например.

watch(
  () => helloWorldRef.value?.$el,
  (n) => console.log(n)
);
0
Maarten Coppens 4 Фев 2022 в 17:46

Точные источники не помню, но мне попадался вот такой код:

const stopWatch = watch(helloworld, value => {
  if (value) {
    stopWatch();
    // TODO: Start using the element
  }
}, { immediate: true });

Проблема в том, что когда текущий компонент закончен, дочерний компонент может еще не успеть смонтироваться.

Как часть более разумного описания, вы можете обернуть все это в функцию:

function onRefReady (ref, cb) {
  const stopWatch = watch(ref, value => {
    if (value) {
      stopWatch();
      cb(value);
    }
  }, { immediate: true });
  onScopeDispose(stopWatch);
}

И используйте это так:

onRefReady(helloworld, el => {
  // TODO: Start using the element
})

Короче говоря, согласно написанному коду:

  • watch(ref, fn) — вызывает fn каждый раз, когда значение ref изменяется. Возвращает функцию (stopWatch), вызов которой watch завершится.
  • { immediate: true } — говорит о немедленном запуске переданной функции, если ref уже имеет непустое значение.
  • onScopeDispose(stopWatch) — говорит прекратить просмотр изменений, если компонент уничтожен.

Этот код использует stopWatch, чтобы избежать утечек памяти.

0
7-zete-7 4 Фев 2022 в 18:03