export default {
data: () => ({
products: [],
showing: true,
mousePosX: 42,
mousePosY: 42
})
}
export default {
data: () => ({
products: [],
uiState: {
showing: true,
mousePosition: {
x: 42,
y: 42
}
}
})
}
Code is cleaner, more organized, and readable
Works best with IDE/editor code grouping support to help with your focus
export default {
data: () => ({
▸ products: {…}
▸ uiState: {…}
})
}
<style lang="scss" scoped>
.my-component {
font-size: 1.2rem;
border-radius: 5px;
background-color: rebeccapurple;
position: fixed; // 🤔
top: 10px; // 🤔
left: 30px; // 🤔
z-index: 42; // 🤔
}
</style>
<style lang="scss" scoped>
.my-component {
font-size: 1.2rem;
border-radius: 5px;
background-color: rebeccapurple;
}
</style>
<style lang="scss" scoped>
.wrapper-component {
.my-component {
position: fixed;
top: 10px;
left: 30px;
z-index: 42;
}
}
</style>
<style lang="scss" scoped>
.my-component {
font-size: 1.2rem;
border-radius: 5px;
background-color: rebeccapurple;
position: fixed;
top: 10px;
left: 30px;
z-index: 42;
}
</style>
<template>
<div>The answer to the universe is {{ answerToUniverse }}</div>
</template>
<script>
export default {
data: () => ({
answerToUniverse: 42
})
}
</script>
<template>
<div>The answer to the universe is {{ answerToUniverse }}</div>
</template>
<script>
export default {
data: () => ({}),
answerToUniverse: 42
}
</script>
<template>
<div>The answer to the universe is {{ $options.answerToUniverse }}</div>
</template>
<script>
export default {
data: () => ({}),
answerToUniverse: 42
}
</script>
Less prone to bugs due to side effects
Consider grouping these data into e.g. $options.nonReactive or something similar
Watch out for name collisions e.g. propsData.
import { eventBus } from '@/utils'
import { userObserver } from '@/observers'
export default {
created () {
userObserver.init()
},
methods: {
fetch (fn) {
return eventBus.$emit(event.$names.FETCH_USER_DATA).then(fn)
}
}
}
import { eventBus } from '@/utils'
import { userObserver } from '@/observers'
export default {
created: () => userObserver.init(),
methods: {
fetch: fn => eventBus.$emit(event.$names.FETCH_USER_DATA).then(fn)
}
}
import { eventBus } from '@/utils'
import { userObserver } from '@/observers'
export default {
created () {
console.log(this) // the Vue instance
userObserver.init()
},
methods: {
fetch (fn) {
console.log(this) // the Vue instance
return eventBus.$emit(event.$names.FETCH_USER_DATA).then(fn)
}
}
}
<template>
<Communicator :communicate="whisper" />
</template>
<script>
export default {
methods: {
whisper: message => alert(message.toLowerCase())
}
}
</script>
<template>
<BlogPost
:id="post.id"
:title="post.title"
:content="post.content"
/>
</template>
<script>
export default {
data: () => ({
post: {
id: 42,
title: 'The Duck Song',
content: 'Do you have grapes?'
}
})
}
</script>
<template>
<BlogPost :post="post" />
</template>
<script>
export default {
data: () => ({
post: {
id: 42,
title: 'The Duck Song',
content: 'Do you have grapes?'
}
})
}
</script>
<script id="blogPostComponent">
export default {
props: {
id: {
type: Number,
validator: isUnsignedInteger
},
title: {
type: String,
required: true,
validator: isNotEmpty
},
content: {
type: String,
validator: hasSeveralParagraphs
}
}
}
</script>
<script id="blogPostComponent">
export default {
props: {
post: {
type: Object,
required: true,
validator: value => {
return isUnsignedInteger(value.id)
&& isNotEmpty(value.title)
&& hasSeveralParagraphs(value.content)
}
}
}
}
</script>
<template>
<BlogPost v-bind="post"/>
</template>
<script>
export default {
data: () => ({
post: {
id: 42,
title: 'The Duck Song',
content: 'Do you have grapes?'
}
})
}
</script>
<script id="blogPostComponent">
export default {
props: {
id: {
type: Number,
validator: isUnsignedInteger
},
title: {
type: String,
required: true,
validator: isNotEmpty
},
content: {
type: String,
validator: hasSeveralParagraphs
}
}
}
</script>
<script id="eventListenerComponent">
import { userService } from '@/services'
export default {
render: h => null,
created () {
[$events.LOG_OUT]: async () => {
await userService.logOut()
location.reload()
}
}
}
</script>
<template>
<div>
<EventListener/>
<!-- Other stuff -->
</div>
</template>
<script id="app">
import EventListener from '@/components/EventListener.vue'
export default {
components: { EventListener }
}
</script>
import { UserList } from '@/components/UserList.vue'
export default {
components: {
UserList
}
}
export default {
components: {
UserList: () => import('@/components/UserList.vue')
}
}
import { shallowMount } from '@vue/test-utils'
import Component from '@/components/FooBar.vue'
describe('components/foo-bar', () => {
it('renders correctly', () => {
expect(shallowMount(Component)).toMatchSnapshot())
}
})
Catches UI breakages and unwanted copy changes early
Reduces visual testing overhead (but doesn't replace it)
Supported out of the box by Jest + Vue Test Utils
<template>
<button @click.prevent="addNew">New User</button>
</template>
<script>
import { PostMixin, UserMixin } from '@/mixins'
export default {
mixins: [PostMixin, UserMixin]
}
</script>
Keep non-Vue code out of Vue
Resist the tendency to make every method Vue component's. Instead, keep methods and properties neutral (i.e. in a service/module) if you don't need Vue-related objects and functions.
BYOB (Build Your Own Blocks)
Instead of adding new npm packages, consider creating your own libraries, plugins, directives etc. if the functionality is simple enough.
Learn how Vue's reactivity works
Understand common reactivity caveats and how to work around them
Avoid reactivity-related bugs and write more performant code.