基于Vue3+TS+StoryUI+elementPlus的个人网站——StoryWeb
前言:各位读者,大家好,很开心你能够阅读这篇文章,这篇文章的目的是对我通过近2个月,利用工作之余,开发的个人网站做一个总结。同时,我认为写博客最大的意义在于能够记录自己的成长以及帮助他人。所以我会尽量在分享自己心得体会的同时,尽量多写一些干货,希望能够对得起看这篇文章的你,好了,接下来我们开始吧!
1.简介篇
访问地址:http://songxiaopenggitee.gitee.io/story-web-v1
源码地址:https://gitee.com/songxiaopenggitee/mystoryweb.git
概况:这个网站的特色,主题可以更换,移动端和PC端都做了适配,在项目中大量使用TS,尽量不用any,组件更多是使用自己一点点写出来的基于Vue3的UI组件。尽量不使用第三方组件库(但其实也用到了自己封装不了的(无奈))。
结构:网站分为首页、博客、组件、文章四个部分。
起因:我一直想做一个个人的网站,可以记录属于自己的一些文章,个人的组件库,个人的博客等。但之前因为比较忙,而且那时候无暇顾及这个,最近不忙的时候就开始开动了,因为是自己的网站,所以技术选型上也比较放的开,相对在自己公司用的技术,会更加的激进一点,此外所有的前后端,以及UI设计都需要自己搞定,所以也体会到的UI工程师他们的不易,我感觉我很多时间都是在纠结用什么颜色好(笑哭),最后弄了个我觉得还算看的过去的UI吧!
样例:
PC端
首页
博客
组件
移动端
首页
组件
心得:其实为什么要做这个网站,其实还是来源于一直想拥有一个更加私有和独立的空间,作为一名工程师,我想既然自己可以,就应该为属于自己的一个个人小作品用心去做一个,即便这个网站有很多不足,但是我会一直去维护,也欢迎看到这篇文章的小伙伴如果看到bug或者不足,能够帮助我去提出来,我会将其做的尽善尽美。
2.技术篇
<1>:message组件
为了好好总结一下我的组件库,我真的花了很多功夫在看源码上面,尤其是ele的源码,下面我分享一下在写message这个组件时我看源码的体会。
为什么我想分享一下这个组件的源码,因为message组件使用的方式和暴露的接口和一般的组件是不一样的。
为什么这么说呢?
因为一般组件我们都是在模板里面提前定义好,比如说:
<template><ElTable>....</ElTable>
</template>
import { ElTable } from 'elementPlus'
export default {name:'组件名称',components:{ElTable}
}
可以发现,一般的组件都是需要像这样提前在模板中定义好,如果需要动态的进行显示隐藏,一般我们都是根据情况使用v-if
或者v-show
来进行控制。
但是在使用message时,各位有印象么?我们并不是进行显式的定义在模板当中,而是使用编程式创建(类似于下面这样)
let instance = getCurrentInstance()
instance.$message({type:'success',message:'这是一个成功的提示'...
})
我们会发现一个问题,我们只是单纯的调用了一个暴露的api,那么说明message实例,包括DOM结构一定是UI组件库动态帮助我们去创建的,它是怎么做到的呢?
或者说假如我们知道了如何动态的创建组件,那是不是我们以后也可以只在JS当中动态的创建组件,而不用提前定义在模板当中不是么?
import { createVNode, render } from 'vue'
import MessageConstructor from './index.vue'
const vm = createVNode(MessageConstructor,options)
const container = document.createElement('div')
render(vm, container)
上面并不是完整的源码,确实我摘录出来最核心的部分,想要动态的创建一个组件,并且挂载到页面中,需要借助vue提供的两个方法:{ createVNode, render }
,前者是专门根据一个组件实例配置项,创建一个虚拟DOM,后者是render方法,将虚拟DOM渲染成为真实DOM并且挂载到第二个参数(DOM元素)上,而调用$message
方法时,它就在这个过程中,帮助我们做了这一步,并且添加了动画,自动关闭等等,功能。
以上便是我在写message组件时,对于动态组件的书写有了一些小体会,不得不说,其实这样的创建方式更符合我们开发者的本能,就是随时需要,随时创建的理念。
但我思考了一下,这个也有一定的劣势,就是它必须知道一个明确的DOM元素,因此一般组件这样写并不适用,适用那些全局有效的,并且优先级很高的组件,比如遮罩层,提示框类似这样的组件。
<2>:TS使用体会
不得不说,TS使用起来真的是降低开发速度,很多时候我更多的时间是在凑类型,分析报错(苦笑),其实实际上还是我需要加强TS的功底,不过不得不说,我使用TS感觉代码的提示真的好很多,而且会有一种更安全,更优雅的感觉,提前定义好类型后,后面无论是传参还是声明都有很友好的提示。
export type TimeMap = {YYYY:string,MM:string,DD:string,HH:string,mm:string,ss:string
}export type TargetContext = '__blank' | '__self'export interface CallBack {(args:any):any
}export interface EventType {[prop:string]:Array<CallBack>
}export interface ViewportOffsetResult {left: numbertop: numberright: numberbottom: numberrightIncludeBody: numberbottomIncludeBody: number
}export interface Fn<T = any, R = T> {(...arg: T[]): R
}
我有很多这样的声明类型的文件,统一管理起来还是很方便的,比如统一管理出错的提示,统一管理常量等等。
<3>:hooks
另外vue3就不得不提到hooks了,在vue3中,我在写draw时使用到了hooks,这样可以将组件内的逻辑抽离出组件,功能分布的很均匀,维护起来也很方便;
所谓hooks,本质上来说和vue2的mixin功能是一样的,不过弥补了mixin数据来源不清晰这一劣势,并且更符合我们开发者的编程习惯,提高组件的复用率。在这个组件当中。useClass提供整个组件,所用到的类库,useEvent专门负责组件的事件逻辑。我认为这样的方式是非常好帮助我们去进行管理和书写的。