vue3笔记

模板语法

reactive() 只适用于对象,它不能持有如 string、number 或 boolean 这样的原始类型,对解构操作不友好。ref() 则可以接受任何类型。ref对象解包后不用使用.value
v-bind:<attribute> :class
v-on也可以@

v-for
v-bind:[attributeName]
@submit.prevent

v-if
v-else​
v-else-if
v-show

<template>

v-if v-for同时使用优先级不明显,v-if优先级更高,无法访问v-for的变量,会报错。使用computed计算filter后再用v-for

v-model

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 计算属性
const publishedBooksMessage = computed(() => {
return author.books.length > 0 ? 'Yes' : 'No'
})

// 挂载后处理原生dom
onMounted(() => {
ElementRef.value.textContent = 'mounted!'
})

// 副作用
watch(todoId, callback)

// 定义获取的属性值
defineProps(['title'])

// 属性传入事件
const emit = defineEmits(['response'])
emit('response', 'hello from child')
<ChildComp @response="(msg) => childMsg = msg" />

事件处理:@keyup.alt.enter="clear"

<tr is="vue:blog-post-row"></tr>

<BlogPost v-bind="Object" />

我们可以通过设定defineOptions({ inheritAttrs: false })和使用 v-bind=”$attrs” 来实现属性透传到非直接子组件

父元素:<slot name="header"></slot>子元素:<template #header>
slot子元素添加样式<div v-if="$slots.footer" class="card-footer">

依赖注入:组件后代提供数据

1
2
3
4
5
6
// 祖先元素处
const message = ref('hello')
provide('message', message)

//后代元素处
const message = inject('message')
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// 定义默认值
const props = withDefaults(defineProps<Props>(), {
msg: 'hello',
labels: () => ['one', 'two']
})

// 选项式API路由
$route.fullPath
$router.push('/about')

// 组合式API
import { useRoute, useRouter } from 'vue-router'
const router = useRouter()
const route = useRoute()
const search = computed({
get() {
// route.query
return route.query.search ?? ''
},
set(search) {
router.replace({ query: { search } })
},
})
router.push()
router.replace()
router.go(n)

// 指向/user/erina
<router-link :to="{ name: 'profile', params: { username: 'erina' } }">
User profile
</router-link>

// id路由
const routes = [
// 动态字段以冒号开始
{ path: '/users/:id', component: User },
]
{{ $route.params.id }}

// 对路由变化做出响应...
import { watch } from 'vue'
import { useRoute } from 'vue-router'
const route = useRoute()
watch(() => route.params.id, (newId, oldId) => {
// 对路由变化做出响应...
})


const routes = [
{
path: '/user/:id',
component: User,
children: [
// 当 /user/:id 匹配成功
// UserHome 将被渲染到 User 的 <router-view> 内部
{ path: '', component: UserHome },
{
// 当 /user/:id/profile 匹配成功
// UserProfile 将被渲染到 User 的 <router-view> 内部
path: 'profile',
component: UserProfile,
},
{
// 当 /user/:id/posts 匹配成功
// UserPosts 将被渲染到 User 的 <router-view> 内部
path: 'posts',
component: UserPosts,
},
],
},
]
<!-- User.vue -->
<template>
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view />
</div>
</template>

// 请注意redirect,导航守卫并没有应用在跳转路由上,而仅仅应用在其目标上。在上面的例子中,在 /home 路由中添加 beforeEnter 守卫不会有任何效果。

// 以 / 开头,以使嵌套路径中的路径成为绝对路径

// 登录重定向
router.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
else next()
})

// 登录重定向
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: (to, from) => {
// reject the navigation
return false
},
},
]

// 路由重定向
function removeQueryParams(to) {
if (Object.keys(to.query).length)
return { path: to.path, query: {}, hash: to.hash }
}
function removeHash(to) {
if (to.hash) return { path: to.path, query: to.query, hash: '' }
}
const routes = [
{
path: '/users/:id',
component: UserDetails,
beforeEnter: [removeQueryParams, removeHash],
},
{
path: '/about',
component: UserDetails,
beforeEnter: [removeQueryParams],
},
]

// 路由懒加载,代码分片
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({
// ...
routes: [
{ path: '/users/:id', component: UserDetails }
// 或在路由定义里直接使用它
{ path: '/users/:id', component: () => import('./views/UserDetails.vue') },
],
})