Vue + TypeScript + Element 项目实践(简洁时尚博客网站)及踩坑记(上)

简介: Vue + TypeScript + Element 项目实践(简洁时尚博客网站)及踩坑记(上)

前言


本文讲解如何在 Vue 项目中使用 TypeScript 来搭建并开发项目,并在此过程中踩过的坑 。


TypeScript 具有类型系统,且是 JavaScript 的超集,TypeScript 在 2018年 势头迅猛,可谓遍地开花。


Vue3.0 将使用 TS 重写,重写后的 Vue3.0 将更好的支持 TS。2019 年 TypeScript 将会更加普及,能够熟练掌握 TS,并使用 TS 开发过项目,将更加成为前端开发者的优势。

所以笔者就当然也要学这个必备技能,就以 边学边实践 的方式,做个博客项目来玩玩。

此项目是基于 Vue 全家桶 + TypeScript + Element-UI 的技术栈,且已经开源,github 地址 blog-vue-typescript


因为之前写了篇纯 Vue 项目搭建的相关文章 基于vue+mint-ui的mobile-h5的项目说明 ,有不少人加我微信,要源码来学习,但是这个是我司的项目,不能提供原码。


所以做一个不是我司的项目,且又是 vue 相关的项目来练手并开源吧。


1. 效果


效果图:


  • pc 端



  • 移动端


微信图片_20220513221624.gif


完整效果请看:https://biaochenxuying.cn


2. 功能


已经完成功能


  • [x] 登录
  • [x] 注册
  • [x] 文章列表
  • [x] 文章归档
  • [x] 标签
  • [x] 关于
  • [x] 点赞与评论
  • [x] 留言
  • [x] 历程
  • [x] 文章详情(支持代码语法高亮)
  • [x] 文章详情目录
  • [x] 移动端适配
  • [x] github 授权登录


待优化或者实现


  • [ ] 使用 vuex-class
  • [ ] 更多 TypeScript 的优化技巧
  • [ ] 服务器渲染 SSR


3. 前端主要技术



所有技术都是当前最新的。


  • vue: ^2.6.6
  • typescript : ^3.2.1
  • element-ui: 2.6.3
  • vue-router : ^3.0.1
  • webpack: 4.28.4
  • vuex: ^3.0.1
  • axios:0.18.0
  • redux: 4.0.0
  • highlight.js: 9.15.6
  • marked:0.6.1


4. 5 分钟上手 TypeScript


如果没有一点点基础,可能没学过 TypeScript 的读者会看不懂往下的内容,所以先学点基础。


TypeScript 的静态类型检查是个好东西,可以避免很多不必要的错误, 不用在调试或者项目上线的时候才发现问题 。


  • 类型注解


TypeScript 里的类型注解是一种轻量级的为函数或变量添加约束的方式。变量定义时也要定义他的类型,比如常见的 :


// 布尔值
let isDone: boolean = false; // 相当于 js 的 let isDone = false;
// 变量定义之后不可以随便变更它的类型
isDone = true // 不报错
isDone = "我要变为字符串" // 报错


// 数字
let decLiteral: number = 6; // 相当于 js 的 let decLiteral = 6;


// 字符串
let name: string = "bob";  // 相当于 js 的 let name = "bob";


// 数组
// 第一种,可以在元素类型后面接上 [],表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3]; // 相当于 js 的let list = [1, 2, 3];
// 第二种方式是使用数组泛型,Array<元素类型>:
let list: Array<number> = [1, 2, 3]; // 相当于 js 的let list = [1, 2, 3];


// 在 TypeScript 中,我们使用接口(Interfaces)来定义 对象 的类型。
interface Person {
    name: string;
    age: number;
}
let tom: Person = {
    name: 'Tom',
    age: 25
};
// 以上 对象 的代码相当于 
let tom = {
    name: 'Tom',
    age: 25
};


// Any 可以随便变更类型 (当这个值可能来自于动态的内容,比如来自用户输入或第三方代码库)
let notSure: any = 4;
notSure = "我可以随便变更类型" // 不报错
notSure = false;  // 不报错


// Void 当一个函数没有返回值时,你通常会见到其返回值类型是 void
function warnUser(): void {
    console.log("This is my warning message");
}


// 方法的参数也要定义类型,不知道就定义为 any
function fetch(url: string, id : number, params: any): void {
    console.log("fetch");
}


以上是最简单的一些知识点,更多知识请看 TypeScript 中文官网


5. 5 分钟上手 Vue +TypeScript



vue-class-component 对 Vue 组件进行了一层封装,让 Vue 组件语法在结合了 TypeScript 语法之后更加扁平化:


<template>
  <div>
    <input v-model="msg">
    <p>prop: {{propMessage}}</p>
    <p>msg: {{msg}}</p>
    <p>helloMsg: {{helloMsg}}</p>
    <p>computed msg: {{computedMsg}}</p>
    <button @click="greet">Greet</button>
  </div>
</template>
<script>
import Vue from 'vue'
import Component from 'vue-class-component'
@Component({
  props: {
    propMessage: String
  }
})
export default class App extends Vue {
  // initial data
  msg = 123
  // use prop values for initial data
  helloMsg = 'Hello, ' + this.propMessage
  // lifecycle hook
  mounted () {
    this.greet()
  }
  // computed
  get computedMsg () {
    return 'computed ' + this.msg
  }
  // method
  greet () {
    alert('greeting: ' + this.msg)
  }
}
</script>


上面的代码跟下面的代码作用是一样的:


<template>
  <div>
    <input v-model="msg">
    <p>prop: {{propMessage}}</p>
    <p>msg: {{msg}}</p>
    <p>helloMsg: {{helloMsg}}</p>
    <p>computed msg: {{computedMsg}}</p>
    <button @click="greet">Greet</button>
  </div>
</template>
<script>
export default {
  // 属性
  props: {
    propMessage: {
      type: String
    }
  },
  data () {
    return {
      msg: 123,
      helloMsg: 'Hello, ' + this.propMessage
    }
  },
  // 声明周期钩子
  mounted () {
    this.greet()
  },
  // 计算属性
  computed: {
    computedMsg () {
      return 'computed ' + this.msg
    }
  },
  // 方法
  methods: {
    greet () {
      alert('greeting: ' + this.msg)
    }
  },
}
</script>



vue-property-decorator 是在 vue-class-component 上增强了更多的结合 Vue 特性的装饰器,新增了这 7 个装饰器:


  • @Emit
  • @Inject
  • @Model
  • @Prop
  • @Provide
  • @Watch
  • @Component (从 vue-class-component 继承)


在这里列举几个常用的@Prop/@Watch/@Component, 更多信息,详见官方文档


import { Component, Emit, Inject, Model, Prop, Provide, Vue, Watch } from 'vue-property-decorator'
@Component
export class MyComponent extends Vue {
  @Prop()
  propA: number = 1
  @Prop({ default: 'default value' })
  propB: string
  @Prop([String, Boolean])
  propC: string | boolean
  @Prop({ type: null })
  propD: any
  @Watch('child')
  onChildChanged(val: string, oldVal: string) { }
}


上面的代码相当于:


export default {
  props: {
    checked: Boolean,
    propA: Number,
    propB: {
      type: String,
      default: 'default value'
    },
    propC: [String, Boolean],
    propD: { type: null }
  }
  methods: {
    onChildChanged(val, oldVal) { }
  },
  watch: {
    'child': {
      handler: 'onChildChanged',
      immediate: false,
      deep: false
    }
  }
}


  • vuex-class


vuex-class :在 vue-class-component 写法中 绑定 vuex


import Vue from 'vue'
import Component from 'vue-class-component'
import {
  State,
  Getter,
  Action,
  Mutation,
  namespace
} from 'vuex-class'
const someModule = namespace('path/to/module')
@Component
export class MyComp extends Vue {
  @State('foo') stateFoo
  @State(state => state.bar) stateBar
  @Getter('foo') getterFoo
  @Action('foo') actionFoo
  @Mutation('foo') mutationFoo
  @someModule.Getter('foo') moduleGetterFoo
  // If the argument is omitted, use the property name
  // for each state/getter/action/mutation type
  @State foo
  @Getter bar
  @Action baz
  @Mutation qux
  created () {
    this.stateFoo // -> store.state.foo
    this.stateBar // -> store.state.bar
    this.getterFoo // -> store.getters.foo
    this.actionFoo({ value: true }) // -> store.dispatch('foo', { value: true })
    this.mutationFoo({ value: true }) // -> store.commit('foo', { value: true })
    this.moduleGetterFoo // -> store.getters['path/to/module/foo']
  }
}
相关文章
|
5天前
|
JavaScript
如何创建一个Vue项目(手把手教你)
这篇文章是一篇手把手教读者如何创建Vue项目的教程,包括使用管理员身份打开命令行窗口、找到存放项目的位置、通过vue-cli初始化项目、填写项目信息、进入项目目录、启动项目等步骤,并提供了一些常见第三方库的引入方法。
如何创建一个Vue项目(手把手教你)
|
6天前
|
JavaScript 前端开发
在Vue2或Vue3中项目中使用 Isotope(同位素) 过滤和排序神奇的布局神器,全网独家实现!
本文介绍了在Vue2或Vue3项目中如何使用Isotope(同位素)布局库来创建动态的网格布局,并提供了详细的代码实现和效果展示,包括过滤和排序功能。
19 0
在Vue2或Vue3中项目中使用 Isotope(同位素) 过滤和排序神奇的布局神器,全网独家实现!
|
1天前
|
JavaScript
Vue项目如何生成树形目录结构
这篇文章介绍了如何在Vue项目中生成树形目录结构,通过安装并使用`mddir`命令行工具来创建一个`directoryList.md`文件,从而快速获取项目的树形目录列表。
Vue项目如何生成树形目录结构
|
6天前
|
数据可视化 JavaScript
Vue3项目使用G6可视化组件实现一个树形机构图
在Vue 3项目中使用G6可视化组件库实现树形机构图的构建和展示。
73 1
Vue3项目使用G6可视化组件实现一个树形机构图
|
6天前
|
JavaScript UED
如何在Vue3项目中使用防抖节流技巧
在Vue 3项目中使用防抖和节流技巧以优化组件性能,包括使用`lodash`库和自定义实现这两种方法。
14 0
如何在Vue3项目中使用防抖节流技巧
|
6天前
在 Vue3 + ElementPlus 项目中使用 el-autocomplete 控件
本文介绍了在Vue3 + ElementPlus项目中如何使用`el-autocomplete`控件实现自动补全输入功能,并探讨了不同版本ElementPlus中`clearable`属性的兼容性问题。
37 0
在 Vue3 + ElementPlus 项目中使用 el-autocomplete 控件
|
6天前
|
JavaScript
创建 Vue3 项目
创建 Vue3 项目
13 0
|
6天前
|
JavaScript
在Vue3+ElementPlus项目中使用具有懒加载的el-tree树形控件
在Vue 3和Element Plus项目中实现具有懒加载功能的el-tree树形控件,以优化大数据量时的页面性能。
27 0
|
6天前
|
JavaScript 前端开发
在Vue3+ElementPlus项目中实现一个简单的新增/移除行记录的小组件
在Vue 3和Element Plus项目中创建一个支持新增和移除行记录的简单表格组件。
39 0
|
6天前
在Vue3项目中使用 vue3-seamless-scroll 无缝滚动插件
本文介绍了如何在Vue3项目中使用`vue3-seamless-scroll`插件实现无缝滚动效果,并提供了详细的示例代码和运行效果。
141 0