Sergey Zhuravlev

+3
с 2023
0 подписчиков
1 подписка

Цель публикации — разобраться, какова структура компонентов Vue. js, что такое реактивные свойства и как они работают.

Компоненты — это фрагменты кода, представляющие собой независимые модули, которые могут быть повторно использованы в различных частях приложения.

3
\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Основываясь на описанной структуре, для примера создам компонент, который приветствует пользователя по имени, в том числе позволяет нажатием кнопки поприветствовать Vue в ответ. Но прежде отмечу, что одним из плюсов Vue. js является возможность при разработке отталкиваться как от шаблона приложения, так и от работы с данными. А поскольку в моем примере шаблон носит условный характер, буду следовать второму пути.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Для начала приведу код компонента полностью, затем рассмотрю детально.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"Component.vue\n\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Создание компонента начинается с определения входных свойств, которые должны быть переданы извне. В моем случае – это имя пользователя customName, которое ожидается в качестве значения в атрибуте props. Также в качестве внутренней переменной объявляю и устанавливаю значение по умолчанию defaultName, на случай, если никаких свойств в props передано не будет.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"props: [\"customName\"],\ndata() {\n return {\n defaultName: \"пользователь\",\n }\n},","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Исходя из этого, мне следует определить, было ли фактически передано значение customName и, если нет – подменить ожидаемое дефолтным. Это возможно сделать с помощью специального метода created(), который автоматически вызывается после создания экземпляра компонента. Created относится к одному из хуков жизненного цикла компонентов, о которых подробнее можно узнать в официальной документации (https://vuejs. org/guide/essentials/lifecycle. html).

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"created () {\n if (!this.customName) {\n return this.customName = this.defaultName\n }\t\n },","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Также я хочу, чтобы мой компонент при нажатии на кнопку, выводил ответное приветствие ко Vue, для чего напишу соответствующий метод answer():

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"methods: {\n answer() {\n this.customName = \"Vue\"\n }\n},","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Наконец, остается лишь указать где в шаблоне полученные данные будут отображаться и как вызываться функция. Соответствующую разметку прописываю в блоке template:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Как говорил ранее, главная особенность компонентов – это их переиспользуемость. Это означает, что я могу импортировать полученный компонент в родительский и вызывать его многократно. Привожу ниже код родительского компонента Parent. vue:

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"Parent.vue\n\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Здесь вызывается три экземпляра дочернего компонента Component. vue, причем каждый экземпляр является самостоятельным и не зависит от других. Это, в свою очередь, позволяет вызывать их с собственными атрибутами. Например, первый вызывается без передачи атрибутов, что должно привести к замене имени пользователя дефолтным значением. Во второй экземпляр я передаю строку с именем пользователя, а в третий – переменную newName с заранее заданным значением. Таким образом, на странице отобразятся все три экземпляра с разным приветствием, а при нажатии на каждую из кнопок произойдет независимый от остальных ответ.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Если компоненты помогают упорядочить блоки интерфейсов, то их динамичность целиком зависит от реактивных свойств.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Реактивность в Vue. js — это механизм, который автоматически обновляет представление компонентов при изменении данных, от которых они зависят. Реактивные свойства реализованы с помощью автоматического метода Vue. observable() . При вызове в него передается объект, который нужно сделать реактивным. В результате получается новый объект, который содержит все свойства и методы оригинального объекта, но с возможностью отслеживания изменений. Когда свойство реактивного объекта изменяется, Vue. js автоматически обновляет все зависимые свойства, в том числе обновляет пользовательский интерфейс.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Для работы с реактивными свойствами Vue. js предоставляет ряд атрибутов, методов и директив, такие как watch, computed, v-model и другие. Метод watch, например, позволяет отслеживать изменения конкретного свойства данных и выполнять определенные действия при их изменении. Computed свойства позволяют вычислять значения на основе данных и обновляться только при изменении зависимых свойств. Директива v-model позволяет связать данные с элементом формы, таким как input, select или textarea. При изменении значения элемента, данные автоматически обновляются, а при изменении данных — обновляется значение элемента формы.

"}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Ниже приведен пример использования директивы v-model, которая связывает новый элемент input, в написанном ранее компоненте, с переменной enteredName. В результате, при вводе имени в поле input автоматически последует изменение приветствия, что является наглядным примером реактивности Vue. js.

"}},{"type":"code","cover":false,"hidden":false,"anchor":"","data":{"text":"Component.vue\n\n","lang":""}},{"type":"text","cover":false,"hidden":false,"anchor":"","data":{"text":"

Подводя итог отмечу, что благодаря своей реактивности и компонентной структуре Vue. js предоставляет практически безграничные возможности создания интерактивных интерфейсов, тем самым помогая решать самый широкий спектр корпоративных задач с помощью легких адаптируемых веб-приложений. Грамотное использование компонентов помогает существенно сократить время разработки, а также упростить дальнейшее сопровождение кода. Тогда как реактивные свойства обеспечивают динамику и отзывчивость, что, в конечном итоге, создает удобство и позитивный опыт использования приложения для конечных пользователей.

"}}],"summaryContent":null,"isExistSummaryContent":false,"warningFromEditor":null,"warningFromEditorTitle":null,"counters":{"comments":0,"favorites":3,"reposts":0,"views":1240,"hits":512,"reads":null,"online":0},"dateFavorite":0,"hitsCount":512,"isCommentsEnabled":true,"isLikesEnabled":true,"isRemovedByUserRequest":false,"isFavorited":false,"isPinned":false,"repostId":null,"repostData":null,"subscribedToTreads":false,"isEditorial":false,"isAudioAvailable":false,"audioUrl":null,"isAudioAvailableToGenerate":false,"commentEditor":{"enabled":true,"who":null,"text":"","until":null,"reason":null,"type":"everybody"},"isBlur":false,"isPublished":true,"isDisabledAd":false,"withheld":[],"ogTitle":null,"ogDescription":null,"url":"https://vc.ru/id2075784/806999-vuejs-sozdaem-dinamicheskii-interfeis","author":{"id":2075784,"name":"Sergey Zhuravlev","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e04c02c7-f3c9-568d-9ceb-57ee8443ee6c","width":1200,"height":797,"size":375070,"type":"jpg","color":"3f3835","hash":"","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":3385880,"userId":2075784,"count":0,"shareImage":"https://api.vc.ru/achievements/share/3385880"}],"lastModificationDate":1764930704,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"subsite":{"id":2075784,"name":"Sergey Zhuravlev","nickname":null,"description":null,"uri":"","avatar":{"type":"image","data":{"uuid":"e04c02c7-f3c9-568d-9ceb-57ee8443ee6c","width":1200,"height":797,"size":375070,"type":"jpg","color":"3f3835","hash":"","external_service":[]}},"cover":null,"achievements":[{"title":"Год на vc.ru","code":"registration_1_year","description":"Первый год с vc.ru. Получена 24 июля 2025.","previewUuid":"0d11c244-49de-50e7-894e-b9b27945d42b","formats":{"glb":"https://static.vc.ru/achievements/fish.glb","usdz":"https://static.vc.ru/achievements/fish.usdz"},"viewData":{"contentColor":"#C67AA3","textMaxWidth":0.634765625,"textX":0.5888671875,"textY":0.54296875,"logoX":0.5859375,"logoY":0.6669921875,"logoXNoText":0.6044921875,"logoYNoText":0.5439453125},"id":3385880,"userId":2075784,"count":0,"shareImage":"https://api.vc.ru/achievements/share/3385880"}],"lastModificationDate":1764930704,"isSubscribed":false,"isSubscribedToNewPosts":false,"isMuted":false,"isAvailableForMessenger":true,"badgeId":null,"isDonationsEnabled":false,"isPlusGiftEnabled":true,"isUnverifiedBlogForCompanyWithoutPro":false,"isRemovedByUserRequest":false,"isFrozen":false,"isDisabledAd":false,"isPlus":false,"isVerified":false,"isPro":false,"yandexMetricaId":null,"badge":null,"isOnline":false,"tgChannelShortname":null,"isUnsubscribable":true,"type":1,"subtype":"personal_blog"},"reactions":{"counters":[{"id":1,"count":3}],"reactionId":0},"isNews":false,"source":null,"clusters":[],"donations":{"amount":0,"isDonated":false},"commentsSeenCount":null}}],"cursor":"PuR2GsZKFTvhhGJRA4fr4drVS6IzQAa09I6wtbz/zlbeaPDONLWnxUVe5WlNnG4=","isAnonymized":true}};