reactive() 和 ref()
1 2 3 4 5 6 7 8 9 10 11 12
| <script setup> import { reactive, ref } from 'vue'
const counter = reactive({ count: 0 }) const message = ref('Hello World!') </script>
<template> <h1>{{ message }}</h1> <h1>{{ message.split('').reverse().join('') }}</h1> <p>Count is: {{ counter.count }}</p> </template>
|
v-bind
v-bind:id=””
v-bind:class=””
v-bind:value=””
简化为
:id=””
:class=””
:value=””
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script setup> import { ref } from 'vue'
const titleClass = ref('title') </script>
<template> <h1 :class="titleClass">Make me red</h1> </template>
<style> .title { color: red; } </style>
|
v-on
Event Listeners
v-on:click=””
v-on:input=””
简化为
@click=””
@input=””
1 2 3 4 5 6 7 8 9 10 11 12 13
| <script setup> import { ref } from 'vue'
const count = ref(0)
function increment() { count.value++ } </script>
<template> <button @click="increment">Count is: {{ count }}</button> </template>
|
v-model
1 2 3 4 5 6 7 8 9 10
| <script setup> import { ref } from 'vue'
const text = ref('') </script>
<template> <input v-model="text" placeholder="Type here"> <p>{{ text }}</p> </template>
|
v-if 和 v-else
Conditional Rendering
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script setup> import { ref } from 'vue'
const awesome = ref(true)
function toggle() { awesome.value = !awesome.value } </script>
<template> <button @click="toggle">Toggle</button> <h1 v-if="awesome">Vue is awesome!</h1> <h1 v-else>Oh no 😢</h1> </template>
|
v-for
List Rendering
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| <script setup> import { ref } from 'vue'
let id = 0
const newTodo = ref('') const todos = ref([ { id: id++, text: 'Learn HTML' }, { id: id++, text: 'Learn JavaScript' }, { id: id++, text: 'Learn Vue' } ])
function addTodo() { todos.value.push({id: id++, text: newTodo.value}); newTodo.value = ''; }
function removeTodo(todo) { todos.value.splice(todos.value.indexOf(todo), 1) } </script>
<template> <form @submit.prevent="addTodo"> <input v-model="newTodo" required placeholder="new todo"> <button>Add Todo</button> </form>
<ul> <li v-for="todo in todos" :key="todo.id"> {{ todo.text }} <button @click="removeTodo(todo)">X</button> </li> </ul> </template>
|
computed
introducing computed().We can create a computed ref that computes its .value based on other reactive data sources:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <script setup> import { ref, computed } from 'vue'
let id = 0
const newTodo = ref('') const hideCompleted = ref(false) const todos = ref([ { id: id++, text: 'Learn HTML', done: true }, { id: id++, text: 'Learn JavaScript', done: true }, { id: id++, text: 'Learn Vue', done: false } ])
const filteredTodos = computed(() => { return hideCompleted.value ? todos.value.filter((t) => !t.done) : todos.value })
function addTodo() { todos.value.push({ id: id++, text: newTodo.value, done: false }) newTodo.value = '' }
function removeTodo(todo) { todos.value = todos.value.filter((t) => t !== todo) } </script>
<template> <form @submit.prevent="addTodo"> <input v-model="newTodo" required placeholder="new todo"> <button>Add Todo</button> </form> <ul> <li v-for="todo in filteredTodos" :key="todo.id"> <input type="checkbox" v-model="todo.done"> <span :class="{ done: todo.done }">{{ todo.text }}</span> <button @click="removeTodo(todo)">X</button> </li> </ul> <button @click="hideCompleted = !hideCompleted"> {{ hideCompleted ? 'Show all' : 'Hide completed' }} </button> </template>
<style> .done { text-decoration: line-through; } </style>
|
Lifecycle and Template Refs
Hook函数 onMounted onUpdated 等 …
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <script setup> import { ref, onMounted } from 'vue'
const pElementRef = ref(null) const customValue = ref("123") onMounted(() => { customValue.value = pElementRef.value.textContent pElementRef.value.textContent = 'mounted!' }) </script>
<template> <p> {{customValue}} </p> <p ref="pElementRef">Hello</p> </template>
|
watch
1 2 3 4 5 6 7 8
| import { ref, watch } from 'vue'
const count = ref(0)
watch(count, (newCount) => { console.log(`new count is: ${newCount}`) })
|
watch() can directly watch a ref, and the callback gets fired whenever count’s value changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <script setup> import { ref, watch } from 'vue'
const todoId = ref(1) const todoData = ref(null)
async function fetchData(id) { todoData.value = null const res = await fetch( `https://jsonplaceholder.typicode.com/todos/${id.value}` ) todoData.value = await res.json() } fetchData(todoId) watch(todoId, (todoId) => { fetchData(todoId); })
</script>
<template> <p>Todo id: {{ todoId }}</p> <button @click="todoId++" :disabled="!todoData">Fetch next todo</button> <p v-if="!todoData">Loading...</p> <pre v-else>{{ todoData }}</pre> </template>
|
Components
1 2 3 4 5 6 7 8
| <script setup> import ChildComp from './ChildComp.vue' </script>
<template> <ChildComp></ChildComp> </template>
|
Props
A child component can accept input from the parent via props. First, it needs to declare the props it accepts:
App.vue
1 2 3 4 5 6 7 8 9 10
| <script setup> import { ref } from 'vue' import ChildComp from './ChildComp.vue'
const greeting = ref('Hello from parent') </script>
<template> <ChildComp :msg="greeting" /> </template>
|
ChildComp.vue
1 2 3 4 5 6 7 8 9
| <script setup> const props = defineProps({ msg: String }) </script>
<template> <h2>{{ msg || 'No props passed yet' }}</h2> </template>
|
Emits
In addition to receiving props, a child component can also emit events to the parent:
1 2 3 4 5 6 7 8 9 10 11
| <script setup> import { ref } from 'vue' import ChildComp from './ChildComp.vue'
const childMsg = ref('No child msg yet') </script>
<template> <ChildComp @response="(msg) => childMsg = msg " @response1="(msg)=> childMsg=msg"/> <p>{{ childMsg }}</p> </template>
|
1 2 3 4 5 6 7 8 9 10
| <script setup> const emit = defineEmits(['response', 'response1'])
emit('response', 'hello from child') emit('response1', "flafkjka") </script>
<template> <h2>Child component</h2> </template>
|
Slots
In addition to passing data via props, the parent component can also pass down template fragments to the child via slots
App.vue
1 2 3 4 5 6 7 8 9 10
| <script setup> import { ref } from 'vue' import ChildComp from './ChildComp.vue'
const msg = ref('from parent') </script>
<template> <ChildComp></ChildComp> </template>
|
ChildComp.vue
1 2 3
| <template> <slot>Fallback content</slot> </template>
|