Vue 3
约 1030 字大约 3 分钟
vuevue3
2024-09-02
Vue3 官网 https://cn.vuejs.org/
vue3 快速安装 pnpm create vue@latest
1. defineEmits
用于定义组件的事件。通过调用该函数,可以声明组件所触发的事件,并且将事件的名称、参数等信息进行声明。
export declare function defineEmits<TypeEmit>(): TypeEmit;类似于defineProps也是一个函数,可以通过范型参数定义
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', array: number[]): void }
>()其实这两个方法本质上来说就是函数function() , 跟范型函数的写法是一致的:
// 范型函数
const emitFunc = <T>(args: T): void => {}
function emitFunc2<T>(args: T): void {}
// defineProps
function defineProps<TypeProps>(): Readonly<TypeProps>
// defineEmits
function defineEmits<TypeEmit>(): TypeEmit2. pinia
合理的使用一些 pinia 的 api 可以很好的简化代码、优化代码。
2.1. 基本使用
新建一个 store.ts
import { defineStore } from "pinia"
type TStore = {
counter: number
name: string
}
export const useStore = defineStore('myStore', {
state: (): TStore => {
return {
counter: 1,
name: '小美老师'
}
},
getters: {
addCount: (state) => {
return state.counter++
},
addCount2(): number {
return this.counter * 3;
}
},
actions: {
induce() {
this.counter--
}
}
})要注意两点:
- state 是一个函数,
所以类型推断的时候是需要按照函数的类型推断方式,推荐使用箭头函数更方便。 - 有两种 getters 的写法,但是个人更推荐通过常规函数用 this 访问整个 store 的实例。
2.2. state的获取
- 通过store实例访问 state,可以直接
读取和写入,store.counter++。 - 通过
store.$reset()方法可以将 state 重置为初始值。 - 通过
store.$patch()方法可以完成 state 值的批量修改。 - 通过
store.$subscribe()订阅 state 的变化,在 patches 修改之后订阅只会触发一次。
这个2和3其实真的很好用,但是我在项目中看到用的不多。
如上代码,我们在项目中引入一下:
<template>
<div>{{ name }}</div>
<div> {{ counter }}</div>
<button @click="patch">patch</button>
<button @click="reset">reset</button>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import { storeToRefs } from 'pinia'
import { useStore } from '../src/store'
const store = useStore()
const { name, counter } = storeToRefs(store)
const reset = () => {
store.$reset(); // 重置成功
};
const patch = () => {
// 直接修改state里面的值,不用在批次修改。
store.$patch({
counter: store.counter + 1,
name: "啊,小美老师",
});
}
store.$subscribe(
() => {
console.log("啊,小美老师发生了变化");
},
{ detached: true }
);
</script>这里的detached属性可能是用来指示这个监听器是否应该与组件的生命周期解绑。如果detached为true,那么即使组件被销毁,这个监听器也会继续监听状态变化。
这里面尤其是store.$subscribe我在项目中很少看到,都是在通过watch监听store里面值的改变。这个是可以推广使用的。
3. extend() / createApp()
vue2
export const verfiyFeishu = async (configData: any) => {
const validateConfig = configData.validateConfig;
const FeishuDialog = require('./FeishuDialog.vue').default;
const dv = document.createElement('div');
document.body.append(dv);
const Cpn = Vue.extend(FeishuDialog);
return new Promise(resolve => {
const instance = new Cpn({
el: dv,
propsData: {
verifyData: validateConfig.verify_data,
tenantIdMd5: validateConfig.tenant_id_md5,
websiteId: validateConfig.website_info_id
}
}) as any;
instance.openDialog();
instance.$on('verifyFinished', val => {
const result = createResult(val ? '' : '投递失败', !val);
resolve(result);
instance.$destroy();
});
});
};vue3
export const verfiyFeishu = async (configData: any) => {
const validateConfig: any = configData.validateConfig;
const FeishuDialog = require('./FeishuDialog.vue').default;
const dv = document.createElement('div');
document.body.append(dv);
return new Promise(resolve => {
const propsData = {
// props -> verifyData/tenantIdMd5/websiteId
verifyData: validateConfig.verify_data,
tenantIdMd5: validateConfig.tenant_id_md5,
websiteId: validateConfig.website_info_id,
// emit -> verifyFinished
onVerifyFinished: val => {
const result = createResult(val ? '' : '投递失败', !val);
resolve(result);
app.unmount();
}
};
const app = createApp(FeishuDialog, propsData);
const instance = app.mount(dv);
instance.openDialog();
// instance.$on('verifyFinished', val => {
// const result = createResult(val ? '' : '投递失败', !val);
// resolve(result);
// instance.$destroy();
// });
});
};4. defineAsyncComponent & Suspense
相关文档:Suspense | Vue.js defineAsyncComponent() | Vue.js
Vue3 中使用 defineAsyncComponent 延迟加载组件使用 Vue3 的 defineAsyncCom - 掘金
<template>
<button @click="show = true"> Login </button>
<Suspense v-if="show">
<template #default>
<ArticleList />
</template>
<template #fallback>
<p> Loading... </p>
</template>
</Suspense>
</template>
<script setup>
import { defineAsyncComponent } from 'vue'
const ArticleList = defineAsyncComponent({
loader: () => import('./ArticleList.vue'),
// 加载异步组件时使用的组件
loadingComponent: LoadingComponent,
// 加载失败时使用的组件
errorComponent: ErrorComponent
// 在显示加载组件之前延迟。默认值:200ms。
delay: 1000,
// 超过给定时间,则会显示错误组件。默认值:Infinity。
timeout: 3000
})
const show = ref(false)
</script>