变量 Variable
import { ref, reactive } from 'vue';
const age = ref(20);
const user = reactive({ name:'tom', age: 30 });
console.log(age.value);
console.log(user.age);
Props
const props = defineProps(['data']);
const props = defineProps({
propA: Number,
propB: {
type: String,
required: true
}
})
模版 Template
v-bind:name
绑定变量,缩写为 :name
v-on:click
绑定事件,缩写为 @click
传递组件
因为采用的是模板方案,所以自然会想到 include 之类的标识,这里 Vue 采用的是 <slot>
内置组件,即占位符方案。
比如一个 Card 组件,接收一个组件作为内容,那么只需要在想要放置传入组件位置的地方使用
// Card.vue
<template>
<div class="card">
<div class="card-content">
<slot></slot>
</div>
</div>
</template>
<style>
.card {
box-shadow: 0 0 3px #CCC;
padding: 10px;
}
</style>
// App.vue
<script setup>
import Card from './Card.vue';
</script>
<template>
<Card>
<div>
Card Content
</div>
</Card>
</template>
Card 组件只允许定制 Content 肯定是不够,如果再加一个 Header 传递多个组件呢?给 slot
加个名字就可以了
// Card.vue
<template>
<div class="card">
<div class="card-header">
<slot name="header"></slot>
</div>
<div class="card-content">
<slot name="content"></slot>
</div>
</div>
</template>
<style>
.card {
box-shadow: 0 0 3px #CCC;
}
.card-header {
padding: 10px;
border-bottom: 1px solid #FAFAFA;
}
.card-content {
padding: 10px;
}
</style>
// App.vue
<script setup>
import Card from './Card.vue';
</script>
<template>
<Card>
<template v-slot:header>
<div>
Card Header
</div>
</template>
<template v-slot:content>
<div>
Card Content
</div>
</template>
</Card>
</template>
组件导入
发现一个比较有趣的事情,导入组件第一个想到的肯定是import,这里还就不一样了,如果直接import是木有任何作用的。
Setup 导入
<script setup>
import H2 from './HelloWorld2.vue';
</script>
import H2 from './HelloWorld2.vue';
setup() {
return { H2 }
}
Component 注册
import H2 from './HelloWorld2.vue';
components: {
H2
}
App Component 注册
import H2 from './components/HelloWorld2.vue';
app.component("H2", H2)
导入后也有一个有趣的事情,它会自动把驼峰命名转为中划线分割,比如 CourseList
可以分别使用 <CourseList />
以及 <course-list />
Vue Router
定义 Router
import { createRouter, createWebHistory } from 'vue-router';
import CourseList from './components/CourseList.vue';
import CourseDetail from './components/CourseDetail.vue';
import CourseDetailExtend from './components/CourseDetailExtend.vue';
import CourseDetailExtend2 from './components/CourseDetailExtend2.vue';
import TeacherList from './components/TeacherList.vue';
const routes = [
{ path: '/courses', component: CourseList },
{ path: '/courses/:id', component: CourseDetail, children: [
{ path: 'extend', component: CourseDetailExtend },
]},
{ path: '/courses/:id/extend2', component: CourseDetailExtend2 },
{ path: '/teachers', component: TeacherList },
{ path: '/:pathMatch(.*)*', redirect: to => {
return { path: '/courses' }
}},
];
const router = createRouter({
history: createWebHistory(),
routes
})
app.use(router)
使用 Router
<router-link to='/courses'>Course</router-link>
<router-link to='/teachers'>Teacher</router-link>
<router-view />
Vuex
定义 Store
vuex 中的 mutations 类似于 redux 的 reducer, 整体看起来跟dva很相似,同步变更放在mutations,异步放在actions里面
import { createStore } from 'vuex'
const courseStore = {
state: () => ({
courseList: [],
courseTotal: 0,
}),
mutations: {
onGetCourseList(state, payload) {
const { list, total } = payload;
state.courseList = list;
state.courseTotal = total;
}
},
actions: {
async GetCourseList({ commit }, payload) {
const { limit, offset } = payload;
let list = [1,312,31,Math.random()];
let total = list.length;
commit('onGetCourseList', { list, total })
}
}
}
注册 Store
当然注册也是不可避免的
const store = createStore({
modules: {
course: CourseStore
}
})
app.use(store)
使用 Store
vue文件中使用如下
computed: mapState({
courseList: state=>state.course.courseList,
courseTotal: state=>state.course.courseTotal,
}),
created() {
this.$store.dispatch('GetCourseList', { limit: 10, offset: 0 })
}