Vue is introducing support for declarative UI syntax, bringing it closer to mobile development patterns seen in Kotlin and Swift. This new approach moves away from traditional HTML templates, offering a more modern, type-safe way to build user interfaces.
The Evolution
Traditional Vue templates use HTML:
<template>
<div class="container">
<h1>{{ title }}</h1>
<button @click="handleClick">Click me</button>
</div>
</template>
The new declarative syntax is more similar to SwiftUI or Jetpack Compose:
<script setup>
import { View, Text, Button } from "vue-declarative";
const title = ref("Hello World");
function handleClick() {
console.log("Clicked!");
}
</script>
<template>
<View class="container">
<Text>{{ title }}</Text>
<Button onPress="{handleClick}">Click me</Button>
</View>
</template>
Key Benefits
1. Type Safety
The declarative syntax provides better TypeScript support:
<View>
<Text
fontSize={16} // TypeScript knows this is a number
color="blue" // TypeScript validates color values
>
Hello
</Text>
</View>
2. Component Composition
Easier component composition similar to React or SwiftUI:
<script setup>
import { View, Text, Image } from "vue-declarative";
const Card = ({ title, image }) => (
<View class="card">
<Image src={image} />
<Text>{title}</Text>
</View>
);
</script>
3. Better Mobile Support
The syntax is more aligned with mobile development patterns, making it easier to share code between web and mobile:
// Works similarly on web and mobile
<View>
<Text>Cross-platform component</Text>
</View>
Comparison with Other Frameworks
SwiftUI (iOS)
VStack {
Text("Hello")
Button("Click") {
handleClick()
}
}
Jetpack Compose (Android)
Column {
Text("Hello")
Button(onClick = { handleClick() }) {
Text("Click")
}
}
New Vue Syntax
<View>
<Text>Hello</Text>
<Button onPress={handleClick}>Click</Button>
</View>
Migration Path
Vue provides a gradual migration path:
- Start with new components: Use declarative syntax for new components
- Gradual conversion: Convert existing components over time
- Coexistence: Both syntaxes can coexist in the same project
Example: Building a Todo App
Traditional Vue
<template>
<div class="todo-app">
<input v-model="newTodo" @keyup.enter="addTodo" />
<ul>
<li v-for="todo in todos" :key="todo.id">
{{ todo.text }}
<button @click="removeTodo(todo.id)">Delete</button>
</li>
</ul>
</div>
</template>
Declarative Syntax
<script setup>
import { View, TextInput, List, ListItem, Button } from 'vue-declarative'
const newTodo = ref('')
const todos = ref([])
function addTodo() {
todos.value.push({ id: Date.now(), text: newTodo.value })
newTodo.value = ''
}
function removeTodo(id) {
todos.value = todos.value.filter(t => t.id !== id)
}
</script>
<template>
<View class="todo-app">
<TextInput
v-model={newTodo}
onSubmit={addTodo}
placeholder="Add a todo"
/>
<List>
<ListItem
v-for="todo in todos"
:key="todo.id"
>
<Text>{todo.text}</Text>
<Button onPress={() => removeTodo(todo.id)}>
Delete
</Button>
</ListItem>
</List>
</View>
</template>
Performance Considerations
The declarative syntax can offer performance benefits:
- Better tree-shaking: Unused components are easier to eliminate
- Optimized rendering: More predictable component updates
- Smaller bundle size: More efficient code generation
When to Use
Consider the declarative syntax when:
- Building new projects
- Targeting mobile platforms
- Needing better TypeScript support
- Working with design systems
- Building component libraries
Stick with traditional templates when:
- Maintaining legacy codebases
- Team is more familiar with HTML
- Working with existing Vue 2 projects
Conclusion
Vue’s new declarative UI syntax represents an evolution towards more modern, type-safe, and mobile-friendly development patterns. While it’s not a replacement for traditional templates, it offers developers more options and brings Vue closer to the patterns used in native mobile development.
This change makes Vue more versatile and positions it well for cross-platform development scenarios.