vue3-ts项目练习
项目是对一些vue3新语法的使用,以及对ts的使用,基本都是一些常用逻辑,主要学习了一些组件的封装, 以及将一些逻辑封装成hooks。自己来实现一些常见ui库的一些组件。
1.axios封装
axios.defaults.baseURL = "/api/api/"; //配置默认url
// 对请求做封装,请求的时候加载loading组件,响应的时候关闭,收集错误的响应信息。 axios.interceptors.request.use((config) => { store.commit("setLoading", true); store.commit("setError", { status: false, message: "" }); return config; }); axios.interceptors.response.use( (config) => { store.commit("setLoading", false); return config; }, (e) => { console.log(e.response); const { error } = e.response.data; store.commit("setError", { status: true, message: error }); store.commit("setLoading", false); return Promise.reject(error); } );
2.router,store的使用
import { useRouter } from "vue-router"; import { useStore } from "vuex"; const router = useRouter(); const store = useStore();
3.权限认证,可以在路由的meta里面添加对应信息,在route.beforeEach中添加相应的权限认证。
const route = createRouter({ history: routerHistory, routes: [ { path: "/", name: "home", component: Home, }, { path: "/login", name: "login", component: Login, meta: { redirectAlreadyLogin: true }, } ] })
4.setup中有两个参数,props,context
props为父组件传的参数,context中包含attrs
、 emit
、slots
5.封装一些组件,封装前想好可能的参数,自定义部分用slot来实现,将需要自定义的部分尽量细分。
6.drowdown组件的封装。
<dropdown :title="`你好 ${user.nickName}`"> <dropdown-item ><a class="dropdown-item" href="#" @click.prevent="toCreate" >新建文章</a ></dropdown-item > <dropdown-item :disabled="true" ><a class="dropdown-item" href="#">编辑资料</a></dropdown-item > <dropdown-item ><a class="dropdown-item" href="#" @click="logout" >退出登陆</a ></dropdown-item > </dropdown>
内部实现:dropdown中展示一个title,以及一个ul,ul中用slot来留给dropdown-item。
<div class="dropdown" ref="drowDownRef"> <a href="#" class="btn btn-outline-light my-2 dropdown-toggle" @click.prevent="toggleOpen" > {{ title }} </a> <ul class="dropdown-menu" :style="{ display: 'block' }" v-if="isOpen"> <slot></slot> </ul> </div>
dropdown-item,外层用li,里面用slot自由发挥
<li class="dropdown-option" :class="{ 'is-disabled': disabled }"> <slot></slot> </li>
判断当鼠标点击下拉框外部的时候下拉框关闭:点击处于非下拉框&&下拉框打开。
import { ref, onMounted, onUnmounted, Ref } from "vue"; const useClickOutSide = (elementRef: Ref<null | HTMLElement>) => { const isClickOutSide = ref(false); const handler = (e: MouseEvent) => { if (elementRef.value) { if (!elementRef.value.contains(e.target as HTMLElement)) { isClickOutSide.value = false; } else { isClickOutSide.value = true; } } }; onMounted(() => { document.addEventListener("click", handler); }); onUnmounted(() => { document.removeEventListener("click", handler); }); return isClickOutSide; }; export default useClickOutSide;
7.用teleport,封装一个最外层的loading组件
8.validateForm的封装,表单验证组件,分成表单及详细的input框,textarea框
validateForm
<form class="validate-form-container"> <slot name="default"></slot> <div class="submit-area" @click.prevent="submitForm"> <slot name="submit"> <button type="submit" class="btn btn-primary">提交</button> </slot> </div> </form>
validateInput
<input v-if="tag !== 'textarea'" class="form-control" :class="{ 'is-invalid': inputRef.error }" @blur="validateInput" :value="inputRef.val" @input="updateValue" v-bind="$attrs" /> <textarea v-else class="form-control" :class="{ 'is-invalid': inputRef.error }" @blur="validateInput" :value="inputRef.val" @input="updateValue" v-bind="$attrs" ></textarea> <span v-if="inputRef.error" class="invalid-feedback">{{ inputRef.message }}</span>
9.以及上传组件,消息框组件
10.封装路由导航hooks
// import { useRouter, RouteParamsRaw } from "vue-router"; import Vrouter, { RouteParamsRaw } from "vue-router"; const router = Vrouter; export default function useNavigate( route: string, params?: RouteParamsRaw ): void { router.push({ name: route, params, }); }