Flexibility
Because of the design of Vue Note, every component can be regarded as a JavaScript experssion, it allows you to achieve similar effects as JSX similar but in Vue, it brings more flexibility but also more performance traps. Here are some tips and examples may help you to learn how to use Vue Note properly.
Keep balance between performance and flexibility
Although Vue Note provides a flxeibile way to write component, It's also really important to understand the performance implications. Using defineCommentComponent
the wrong way can make your app slow.
Bad Example: Making Components Too Often
Here's what not to do. The defineCommentComponent
runs again every time foo changes:
export default defineCommentComponent(() => {
const props = defineProps<{ foo: boolean }>()
const DynamicComponent = computed(() =>
props.foo
? defineCommentComponent(() => {
defineTemplate(/* @template
<h1> foo </h1>
*/)
})
: defineCommentComponent(() => {
defineTemplate(/* @template
<h1> not foo </h1>
*/)
})
)
defineTemplate(/* @template
<DynamicComponent />
*/)
})
Better Way: Use v-if
and v-else
Here's a good solution using v-if
and v-else
:
export default defineCommentComponent(() => {
const props = defineProps<{ foo: boolean }>()
const DynamicComponent = defineCommentComponent(() => {
defineTemplate(/* @template
<h1 v-if='props.foo'> foo </h1>
<h1 v-else> not foo </h1>
*/)
})
defineTemplate(/* @template
<DynamicComponent />
*/)
})
Or Even Simpler:
export default defineCommentComponent(() => {
const props = defineProps<{ foo: boolean }>()
defineTemplate(/* @template
<h1 v-if="props.foo">foo</h1>
<h1 v-else>not foo</h1>
*/)
})
The Main Rule
Try to run defineCommentComponent
as few times as possible:
- Define components at the top level if possible
- Use
v-if
andv-else
to show/hide things if possible - Don't define components inside computed or watch unless you know what you are doing
- Don't make new components when data changes unless you know what you are doing
This way your app stays fast but still does what you want!
Examples
Here are some examples about how to use Vue Note with good performance and comfortable flexibility
If you have also some good examples, you can contribute your code by editing this page.
Making a Card
component
import { defineCommentComponent } from 'vue-note'
export const Card = {
wrapper: defineCommentComponent(/* Your component... */),
header: defineCommentComponent(/* Your component... */),
description: defineCommentComponent(/* Your component... */),
body: defineCommentComponent(/* Your component... */),
footer: defineCommentComponent(/* Your component... */),
}
<script lang='ts' setup>
import { Button } from './button'
import { Card } from './card'
import UserInformation from './UserInformation.vue'
</script>
<template>
<Card.wrapper>
<Card.header>User Info</Card.header>
<Card.description>Edit your personal information</Card.description>
<Card.body>
<UserInformation />
</Card.body>
<Card.footer>
<Button.default>Save</Button.default>
<Button.secondary>Cancel</Button.secondary>
</Card.footer>
</Card.wrapper>
</template>
Conditional Complex UI Components
Forked from Vite Devtools
const panels = {
module: defineCommentComponent(/* your component */),
asset: defineCommentComponent(/* your component */),
plugin: defineCommentComponent(/* your component */),
chunk: defineCommentComponent(/* your component */),
}
function useDetailsPanel() {
const router = useRouter()
const route = useRoute()
const currentPanelType = computed(() =>
Object.keys(panels).find(
key => typeof route.query[key] !== 'undefined'
)
)
const CurrentPanel = computed(() =>
currentPanelType.value
&& panels[currentPanelType.value]
)
function closeCurrentPanel() {
if (currentPanelType.value) {
router.replace({ query: {
...route.query,
[currentPanelType.value]: undefined
} })
}
}
return {
data: route.query[currentPanelType],
CurrentPanel,
closeCurrentPanel
}
}
<script setup lang="ts">
const { data, CurrentPanel, closeCurrentPanel } = useDetailsPanel()
onKeyDown('Escape', (e) => {
e.preventDefault()
if (!e.isTrusted || e.repeat)
return
closeCurrentPanel()
})
</script>
<template>
<div
v-if="currentPanelType" fixed inset-0
backdrop-blur-8 backdrop-brightness-95 z-panel-content
@click.self="closeCurrentPanel"
>
<CurrentPanel :data />
</div>
</template>