项目背景:
一个以前的项目( 刚入职实习的时候写的,用的vuecli2 ),然后这次要添加修改东西,看着代码看的头大,冲动之下就重构了( 想打死自己,写的啥玩意 ),刚好用下最近刚学的typescript,从搭建开始,一步步更新记录下,怕自己之后忘了再回过头来看看。( 顺便说一句,用起来有点别扭,不过还是挺爽的,期待vue3.0... )
一.项目搭建:
使用命令 vue create news 创建项目
配置自定义,贴一下我自定义的安装依赖
ts+vuex+router这几个肯定是要的,这里的css我选择的是scss,unit测试也来一个
之后一些的选项就自己选择
3. 搭建好后目录就是这样
├── public // 静态页面 ├── src // 主目录 ├── assets // 静态资源 ├── components // 组件 ├── views // 页面 ├── App.vue // 页面主入口 ├── main.ts // 脚本主入口 ├── router.ts // 路由 ├── shims-tsx.d.ts // 相关 tsx 模块注入 ├── shims-vue.d.ts // Vue 模块注入 └── store.ts // vuex 配置 ├── tests // 测试用例 ├── .eslintrc.js // eslint 相关配置 ├── .gitignore // git 忽略文件配置 ├── babel.config.js // babel 配置 ├── postcss.config.js // postcss 配置 ├── package.json // 依赖 └── tsconfig.json // ts 配置
想着为了以后更好的维护,就修改了一下目录结构
├── public // 静态页面 ├── src // 主目录 ├── api // 接口 ├── assets // 静态资源 ├── filters // 过滤 ├── store // vuex 配置 ├── styles // 样式 ├── utils // 工具方法(axios封装,全局方法等) ├── views // 页面 ├── App.vue // 页面主入口 ├── main.ts // 脚本主入口 ├── router.ts // 路由 ├── shime-global.d.ts // 相关 全局或者插件 模块注入 ├── shims-tsx.d.ts // 相关 tsx 模块注入 ├── shims-vue.d.ts // Vue 模块注入, 使 TypeScript 支持 *.vue 后缀的文件 ├── tests // 测试用例 ├── .eslintrc.js // eslint 相关配置 ├── postcss.config.js // postcss 配置 ├── .gitignore // git 忽略文件配置 ├── babel.config.js // preset 记录 ├── package.json // 依赖 ├── README.md // 项目 readme ├── tsconfig.json // ts 配置 └── vue.config.js // webpack 配置
tsconfig.js是ts的配置项
具体可以看官网自己配置: https://www.tslang.cn/docs/handbook/compiler-options.html
4.初步修改vue.config.js
const path = require("path"); const webpack = require('webpack'); function resolve(dir) { return path.join(__dirname, dir) } const router='http://xxx.xxx.xxx' module.exports = { publicPath: "./", //基本路径 outputDir: 'dist', //打包时生成的文件夹 lintOnSave: process.env.NODE_ENV === 'development', productionSourceMap: process.env.NODE_ENV === 'development', devServer: { port: 8080, open: true, proxy: { '/test': { target: router, changeOrigin: true } } }, configureWebpack: { name: process.env.VUE_APP_NAME, resolve: { alias: { '@': resolve('src'), } }, externals: {}, plugins: [], }, }
至此,项目初步搭建完成,然后就开始封装安装插件
二. 安装插件和基本内容填充
这里我使用 的element-ui,echarts, babel-polyfill,jquery等
这里有个注意的,在typescript 中使用jquery,echarts等插件的 时候,必须要安装对应的声明文件,当然typescripe社区已经有很多大佬写好了,前人种树,后人乘凉复制代码
什么是声明文件:
https://github.com/xcatliu/typescript-tutorial/blob/master/basics/declaration-files.md
声明文件搜索地址: microsoft.github.io/TypeSearch/
untils 文件夹(可以放一些常用的工具函数,节流、防抖、localStorage等)
这个里面我存放了一些工具函数,date函数,axios的封装等
styles 文件夹 (存放全局scss文件)
这里面除了初始化一些样式外,我还定义了一些常亮,例如导航栏的高度,颜色等,便于 好改
router 文件夹(懒加载)
因为这个系统权限之类的并没有很复杂,路由也不是很多,就没有按模块引入,就直接写了。
/* webpackChunkName: "login" */ /*这里名字是什么,打包出来的名字就是什么*/ { path: '/', name: 'login', component: () => import(/* webpackChunkName: "login" */ '@/views/login/index.vue'), meta: { title:'登录页' keepAlive: false, } }, { path: "/home", name: "home", redirect: "/homepage", component: () => import(/* webpackChunkName: "home" */"@/views/Home.vue"), children: [ { path: "/homepage", component: () => import(/* webpackChunkName: "homepage" */ "@/views/homepage/index.vue"), name: "homepage", meta: { title: "首页", keepAlive: true } }, ] }
api 文件夹
根据不同模块的接口,去建不同的文件
三.vue中typescript的写法
typescript的写法和vue差不多,只是script的区别,例:
import { Component, Prop, Vue, Watch } from 'vue-property-decorator' @Component({ name: 'homepage', components: {} }) export class MyComponent extends Vue { @Prop({ default: '' }) private name!: string @Watch('name', { deep: true }) changeName(newVal,olVal){} //data private count:number=5 private arr:string[]=[] mounted(){} //methods private test(){} }
四.typescript使用中的问题
1.获取refs
写法:
let layoutList:any = this.$refs.layout as HTMLDivElement
2.引用插件,且找不到声明文件或引用Json文件
在shims-vue.d.ts 文件中声明,再在组件中引用
declare module "*.json" { const value: any; export default value; } declare module "vue-count-to" { const count: any; export default count; }
页面里面
import * as myJson from '../../../public/test.json'
使用 myJson.default
3.计算属性
get age() { return this.aTagDatasF.filter(item => item.visible) }
4.@prop
@Prop()private datas!: any
感叹号是非null和非undefined的类型断言,所以上面的写法就是对datas这个属性进行非空断言
5.引入vue组件时,后面必须加 .vue
6.定义接口类型,前面加 I,例如,接口尽量定义类型,规范管理
interface IUserInfo{ name:string, index:number }
7.定义全局变量(可以用vuex取代)
在.ts文件里面
export var User:IUserInfo={ name:'111', index:996 }
其他页面import ,然后 就可以获取到这个值
8.强行让ts不检测
//@ts-ignore 下一行不检测
五.开始改造页面代码(开始吐槽自己)
槽点1:组件切换
以前的代码(部分片段)
改造后:用component 用is去动态判断就行
<div class="haveClick> <component :is="echartsIndex" :obj="obj"/> </div>
槽点2:对象赋值
以前的代码(部分片段):
改造后:
//这样写是因为initObj还有别的key for(let i in this.obj){ if(this.initObj(i)!=undefined){ this.initObj[i]=this.obj[i] } } //或者 写一个函数,如果key值一样就赋值
槽点3:switch case 判断之前的代码:
//片段,有十几个case optionList:['饼图','柱状图','折线图','...'] 筛选下拉后,aa为index switch (aa) { case 0: this.getData() break; case 1: this.avgBqzs() break; case 2: this.areaCount() break; case 3: this.yiqing() break; case 4: this.avgFinish() break; }
修改后:
private optionList=[{ title:'饼图', type:'getData' },{ title:'柱状图', type:'avgBqzs'} ...... ] 下拉后,用change事件获取 item (这里就不获取index了) 例如: changeSelect(item:any){ //当然这里不能通过ts的编译 @ts-ignore this[item.type]()}
六.个人项目规范
1.尽量不要使用for,使代码观赏性更高
forEach 遍历 , map转换,filter 过滤
2.调接口使用 尽量 async和await来调用接口
例如:
private async getData() { const { data } = await getTransactions({}) }
3.只需要部分筛选条件的时候用解构去获取值
public sizeTop={ id:'', City:'', County:'', time:'' } const {City,County}=this.sizeTop private async getData() { const { data } = await getTransactions({City,County}) }
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]