serii81
@serii81
Я люблю phр...

Почему во Vue3 не срабатывает computed, когда меняется ref?

Всем привет.
Есть компонент Input
<script setup>
	import { ref } from '@vue/reactivity';

	const props = defineProps({
		type: {
			type: String,
			default: 'text',
		},
		label: {
			type: String,
			required: false,
		},
		placeholder: {
			type: String,
			required: false,
		},
		value: {
			type: [String, Number],
			required: false,
		},
		behaviour: {
			type: String,
			required: false,
		},
		error: {
			type: String,
			required: false,
		},
	});

	const emits = defineEmits(['change']);
	const current = ref(props.value);

	function changeHandler() {
		emits('change', current);
	}
</script>
<template>
	<div class="input">
		<label v-if="label" :for="value">{{ label }}</label>
		<input
			:id="value"
			:type="type"
			:placeholder="placeholder !== undefined ? placeholder : null"
			:class="[
				{ 'input--success': behaviour === 'success' },
				{ 'input--error': behaviour === 'error' },
			]"
			v-model="current"
			@change="changeHandler"
		/>
		<p v-if="error" class="input__message input__message--error">
			{{ error }}
		</p>
	</div>
</template>

И страница, где используется этот компонет
<script setup>
import Input from "../components/ui/Input.vue";
import Checkbox from "../components/ui/Checkbox.vue";
import {items} from "../data/lorem-ipsum";
import {computed, watch} from "@vue/runtime-core";
import {ref} from "@vue/reactivity";

const count = ref(1);

const filtered = computed(() => {
  const result = items.slice(0, count.value);
  return result;
})

function changeCount(value) {
  count.value = value;
}

</script>
<template>
  <div class='lorem-ipsum'>
    <div class="container">
      <h1 class="title">Lorem ipsum generator</h1>
      <header class="lorem-ipsum__header">
        <span>Paragraphs: </span>
        <Input type="number" :value="count" @change="changeCount"/>
      </header>
      <div class="lorem-ipsum__filter">
        <Checkbox label="Use title" value="title"/>
        <Checkbox label="Use subtitle" value="subtitle"/>
        <Checkbox label="Use text" value="text"/>
        <Checkbox label="Use footer" value="footer"/>
      </div>
      <ul class="lorem-ipsum__list" v-if="filtered.length">
        <li v-for="({id, title, subtitle, text, date}) in filtered" :key="id">
          <h2>{{ title }}</h2>
          <h3>{{ subtitle }}</h3>
          <p>{{ text }}</p>
          <footer>Date: ({{ date }})</footer>
        </li>
      </ul>
    </div>
  </div>
</template>


Проблема в том что, когда меняю input, то count в родителе тоже меняется, но computed нет, почему?

63c307281f538046253174.jpeg

Добавил sandbox

Sandbox
  • Вопрос задан
  • 505 просмотров
Решения вопроса 2
Aetae
@Aetae Куратор тега Vue.js
Тлен
Во первых:
import { computed, ref } from "vue";

Во-вторых:
<Input type="number" :value="count" @change="changeCount"/>


Дальше при нормальных данных и компонентах должно работать, однако возможно энтот твой Input в change возвращает не значение, а event, тут хз сам смотри.
Ответ написан
0xD34F
@0xD34F Куратор тега Vue.js
const current = ref(props.value);

Так, ref, хорошо.

emits("change", current);

Этот ref отдаёте родителю. Странно, но допустим.

А что в родителе?

@change="changeCount"

Слушаете change, окей.

function changeCount(value) {
  count.value = value;
}

Но при этом зачем-то устанавливаете в качестве значения одного ref'а другой ref, полученный из дочернего компонента. Это как?

Отправляйте из дочернего компонента число вместо ref'а:

emits("change", current); ---> emits("change", current.value);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы