Вопрос или проблема
У меня возникли проблемы с Vue после обновления, и за 3 дня я так и не смог понять, что сломано или что произошло. Мой проект использует Vue 3 и развернут в Azure с использованием рабочего процесса GitHub Actions. В пятницу (2024-09-27) я отправил несколько совсем незначительных обновлений, и все работало хорошо. Затем в понедельник я отправил еще несколько незначительных обновлений, после чего все сломалось. После этого я очистил docker, пересобрал и перезапустил контейнер разработки, в результате чего проблемы, с которыми я сталкивался на продакшене, стали отображаться у меня в разработке (до этого все работало нормально в разработке). Поскольку проблемы в разработке возникли только после чистой пересборки (где необходимо было снова выполнить ‘npm install’), я полагаю, что проблемы связаны с моими зависимостями.
Обновление в понедельник состояло в изменении конфигурационного файла для добавления всплывающего окна после нажатия кнопки, изменении некоторых комментариев и некоторых не связанных изменениях в бэкенде (node). В результате почти каждое поле ввода в приложении потеряло реактивность. Похоже, что переменные обновляются, но это не вызывает повторный рендеринг в DOM.
Учитывая, что изменения, которые я сделал, так специфичны, они не могут быть причиной проблем. Откат изменений и повторное развертывание приводят к тем же проблемам, несмотря на то, что старый код изначально работал, когда был впервые развернут. Я откатил кодовую базу на 4 дня, 2 недели и 10 недель, и все равно возникали те же проблемы.
Во время отладки я смог создать компонент ниже, который является самым простым примером сломанной реактивности. Скопируйте и вставьте это в новый проект, и он будет работать нормально. Кроме того, если я отключу $autoDirty или удалю фиктивный валидатор, или уберу ссылку на vuelidate из вычисляемого свойства, все будет работать нормально (что заставляет меня думать, что vuelidate является коренной причиной). Встраивание этого примера в мой проект и ввод в поле ввода не изменяет “Тестовый вывод” (который остается начальным значением “asd”). В инструментах разработки Vue переменная теста обновляется после нажатия кнопки обновления (она не обновляется, когда вы вводите текст в поле ввода).
<template>
<div>
<input
class="form-control form-control-sm"
type="text"
v-model="test"
placeholder="Test"
id="test"
/>
<p>Тестовый вывод: {{ test }}</p>
<button v-if="hasChanges">Кнопка</button>
</div>
</template>
<script>
import useVuelidate from "@vuelidate/core";
export default {
name: "TempTest",
validations: () => ({
test: { required: () => true },
}),
setup() {
return {
v$: useVuelidate({ $autoDirty: true }),
};
},
data() {
return {
test: "asd",
};
},
computed: {
hasChanges() {
return !this.v$.$invalid;
},
},
};
</script>
Я пробовал создавать новый проект, устанавливая те же зависимости и перетаскивая тот же исходный код. Я выполнил audit fix, audit fix force и обновил все зависимости до их последней версии (начальные версии указаны ниже). Все это привело к тем же проблемам. Мне удалось временно привести все в рабочее состояние, отключив $autoDirty или добавив вызов $forceUpdate с интервалом 100 мс на протяжении всего жизненного цикла компонентов.
Естественно, это не идеально, и я буду очень признателен за любую помощь в выяснении основной проблемы. Кто-то сталкивался с чем-то подобным?
"dependencies": {
"@googlemaps/markerclusterer": "^2.5.3",
"@vue/compiler-sfc": "^3.2.13",
"@vuelidate/core": "^2.0.3",
"@vuelidate/validators": "^2.0.4",
"axios": "^1.6.1",
"bootstrap": "^5.3.2",
"chart.js": "^3.9.1",
"core-js": "^3.33.2",
"image-blob-reduce": "^4.1.0",
"libphonenumber-js": "^1.10.51",
"luxon": "^3.4.3",
"papaparse": "^5.4.1",
"pinia": "^2.1.7",
"register-service-worker": "^1.7.2",
"socket.io-client": "^4.7.5",
"vue": "^3.2.36",
"vue-advanced-cropper": "^2.8.8",
"vue-chart-3": "^3.1.8",
"vue-jwt-decode": "^0.1.0",
"vue-router": "^4.0.13",
"vue-search-select": "^3.2.0",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@babel/core": "^7.23.2",
"@babel/eslint-parser": "^7.22.15",
"@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-eslint": "~5.0.8",
"@vue/cli-plugin-pwa": "~5.0.8",
"@vue/cli-service": "^5.0.8",
"eslint": "^8.52.0",
"eslint-plugin-vue": "^9.18.1",
"html-webpack-plugin": "^5.5.3"
},
Ответ или решение
Проблема, с которой вы столкнулись, связана с реактивностью в Vue после обновления зависимостей, причем, как вы отметили, возможно, корень проблемы кроется в библиотеке Vuelidate. Давайте подробно разберем основные моменты, которые могут помочь вам решить эту проблему.
1. Проверьте версию Vuelidate
Обратите внимание на используемые версии @vuelidate/core
и @vuelidate/validators
. Если они были обновлены, попробуйте перейти на версии, которые работают в вашей рабочей среде. Ошибки в совместимости версий могут вызывать проблемы с реактивностью.
2. Модификация компонента
Ваш пример компонента показывает, что реактивность не срабатывает должным образом. Попробуйте внести следующие изменения в ваш компонент:
<template>
<div>
<input
class="form-control form-control-sm"
type="text"
v-model="test"
placeholder="Test"
id="test"
/>
<p>Test output: {{ test }}</p>
<button v-if="hasChanges">Button</button>
</div>
</template>
<script>
import { ref, watch } from 'vue';
import useVuelidate from '@vuelidate/core';
export default {
name: 'TempTest',
setup() {
const test = ref('asd');
const v$ = useVuelidate(
{ test: { required: () => true } },
{ $autoDirty: true }
);
watch(test, () => {
// Это добавляет дополнительный триггер для реактивности
v$.$touch();
});
return {
test,
v$,
hasChanges: computed(() => !v$.$invalid),
};
},
};
</script>
3. Убедитесь в правильной инициализации Vuelidate
Проверьте правильность инициализации Vuelidate в методе setup()
. Использование useVuelidate
должно проходить после объявления реактивных переменных.
4. Понимание $autoDirty
Если $autoDirty
вызывает проблемы, возможно, стоит попробовать удалить его. Он отвечает за автоматическое обновление состояния валидатора, что может вызывать ситуации, когда Vue не распознает изменения в состоянии компонента.
5. Проверка других зависимостей
Если проблема по-прежнему сохраняется, попробуйте временно удалить другие зависимости, такие как pinia
, axios
и т. д., чтобы проверить, влияет ли какая-либо из них на реактивность. Иногда другие библиотеки могут вызывать конфликты.
6. Обновление и очистка кэша
После изменений рекомендуется выполнить следующие команды в терминале:
npm cache clean --force
rm -rf node_modules/
npm install
Это поможет убедиться, что все зависимости установлены корректно без конфликта версий.
7. Использование Vue Devtools
Используйте Vue Devtools для отслеживания изменений реактивных переменных. Это поможет вам видеть, изменяются ли ваши переменные в реальном времени и доступна ли им реактивность.
8. Обращение к документации
Если проблема не решается, обратитесь к официальной документации Vuelidate и Vue.js, особенно следите за возможными изменениями в API, которые могут влиять на вашу реализацию.
Заключение
Эти шаги должны помочь определить и устранить проблему с реактивностью в вашем проекте на Vue. Если это не решит ваши проблемы, возможно, вам стоит создать минимальный воспроизводимый пример и задать вопрос на соответствующих форумах или в сообществе Vue.js, чтобы получить более целенаправленную помощь.