[Vue] One Object to Rule Them All (v-bind & v-on syntax)
Introduction
One of the first things that Vue developers often learn is the magic of using v-bind
and v-on
to supercharge their HTML with dynamic bindings and event listeners. The declarative nature of v-bind
and v-on
make it very easy for other developers to follow.
<input
:id="inputId"
:data-tooltip="tooltipText"
@change="updateForm"
@mouseover="showTooltip"
/>
However, as components grow larger and complex, we can find that this approach becomes limiting and can even create confusion. When it comes to this point, it’s time to learn a hidden secret that most Vue developers don’t know about till much later in their journey: you can dynamically define multiple values for v-bind
and v-on
.
v-bind with No Argument
As I mentioned earlier, most Vue developers are familiar with the following syntax:
<template>
<img v-bind:src="imageAttrs.src" v-bind:alt="imageAttrs.text" />
</template>
<script>
export default {
data() {
return {
imageAttrs: {
src: '/vue-mastery-logo.png',
text: 'Vue Mastery Logo'
}
}
}
}
</script>
What many don’t realize is that this syntax is the href
part of our v-bind
statement is actually an argument. In other words, by passing in an argument to v-bind
, we are telling Vue that we want to bind a specific property to this particular attribute.
However, what’s even more perplexing is that this argument is optional. What does this mean? Well, believe it or not, our code can actually be written instead as:
<img v-bind="{ src: imageAttrs.src, alt: imageAttrs.text }" />
This could then be abstracted one step further to:
<img v-bind="imageAttrs" />
However, while this this is very short and concise, most of us would still prefer the original way of declaring attributes due to its clarity and ease of use.
v-on with No Arguments
When it comes to v-on
, most people are familiar with the following usage:
<template>
<img v-on:click="openGallery" v-on:mouseover="showTooltip" />
</template>
<script>
export default {
methods: {
openGallery() { ... },
showTooltip() { ... }
}
}
</script>
Just like v-bind
, the event name we define is actually an argument being passed to v-on
. As a result, we can also rewrite our input
element as:
<template>
<img v-on="{ click: openGallery, mouseover: showTooltip }" />
</template>
And theoretically, we could abstract this one step further to:
<template>
<img v-on="inputEvents" />
</template>
<script>
export default {
computed: {
inputEvents: {
click: this.openGallery,
mouseover: this.showTooltip
}
},
methods: {
openGallery() { ... },
showTooltip() { ... }
}
}
</script>
However, just like we mentioned earlier in the v-bind
section, most of us would still prefer the original syntax because it is easy to understand and change if necessary.
When would this be useful?
As we illustrated in our earlier examples, simple components with an easy to understand structure has little reason to use an abstracted syntax. However, as our components become more complex and difficult to understand, our newly acquired technique suddenly has a lot of applications.
NewsFeed Scenario
For example, let’s consider the scenario where you are building a NewsFeed
component where the API will pass a series of components that changes based on what the editors want. This means that sometimes you will get NewsArticle
components, but sometimes you’ll get NewsAd
components.
When it comes to implementing this, you may start out with something like the following:
<template>
<main>
<Component
v-for="content in apiResponse"
:key="content.id"
:is="content.type"
:article-title="content.title"
:article-content="content.body"
:ad-image="content.image"
:ad-heading="content.heading"
@click="content.type === 'NewsArticle' ? openArticle : openAd"
@mouseover="content.type === 'NewsArticle' ? showPreview : trackAdEvent"
/>
</main>
</template>
In this scenario, we are:
- Using the
Component
component to dynamically render either theNewsArticle
orNewsAd
component using theis
attribute that is defined withcontent.type
. - Binding dynamic attributes for the
NewsArticle
component:article-title
andarticle-content
- Binding dynamic attributes for the
NewsAd
component:ad-image
andad-heading
And thought it doesn’t look too confusing yet, it is clear that certain props and events only matter in depending on what component it is. As this list of attributes and events becomes much longer, this will become exponentially more difficult to mange and understand.
Refactoring NewsFeed
When a component becomes difficult to understand and manage, this is the time for us to seek out new techniques and abstractions. Using our newly acquired techniques, let’s refactor the NewsFeed
component.
<template>
<main>
<Component
v-for="content in apiResponse"
:key="content.id"
:is="content.type"
v-bind="feedItem(content).attrs"
v-on="feedItem(content).events"
/>
</main>
</template>
<script>
export default {
methods: {
feedItem(item) {
if (item.type === 'NewsArticle') {
return {
attrs: {
'article-title': item.title,
'article-content': item.content
},
events: {
click: this.openArticle,
mouseover: this.showPreview
}
}
} else if (item.type === 'NewsAd') {
return {
attrs: {
'ad-image': item.image,
'ad-heading': item.heading
},
events: {
click: this.openAd,
mouseover: this.trackAdEvent
}
}
}
}
}
}
</script>
And with that, our NewsFeed
article has properly delegated the responsibilities to the specific components rather than mix them up under a single HTML element.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2022-12-02 [Typescript] 124. Binary to Decimal
2019-12-02 [CSS3] Use media query to split css files and Dark mode (prefers-color-scheme: dark)
2019-12-02 [PWA] Storage information for PWA application
2019-12-02 [HTML5] Native lazy-loading for the web
2019-12-02 [Dynamic Programming] 198. House Robber
2016-12-02 [D3] Create Labels from Non-numeric Data with Ordinal Scales in D3 v4
2016-12-02 [D3] Create Labels from Numeric Data with Quantize Scales in D3 v4