随笔

Vue 学习笔记

变量 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 })
}

本文链接:https://note.lilonghe.net/post/ikvmel.html

-- EOF --