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']
  }
}
相关文章
|
9天前
|
JavaScript
Vue使用element中table组件实现单选一行
如何在Vue中使用Element UI的table组件实现单选一行的功能。
28 5
Vue使用element中table组件实现单选一行
|
8天前
|
JavaScript
vue项目中使用vue-router进行路由配置及嵌套多级路由
该文章详细说明了如何在Vue项目中配置和使用vue-router进行单页面应用的路由管理,包括设置嵌套路由和实现多级路由导航的示例。
vue项目中使用vue-router进行路由配置及嵌套多级路由
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【vue插件-50.(了解)表单校验插件】
vue尚品汇商城项目-day07【vue插件-50.(了解)表单校验插件】
14 4
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【51.路由懒加载】
vue尚品汇商城项目-day07【51.路由懒加载】
15 4
|
4天前
|
JavaScript
vue尚品汇商城项目-day07【vue插件-54.(了解)生成二维码插件】
vue尚品汇商城项目-day07【vue插件-54.(了解)生成二维码插件】
14 2
|
6天前
|
API UED
如何实现Vue2项目升级Vue3?
如何实现Vue2项目升级Vue3?
13 1
|
8天前
|
JavaScript
vue项目中引入阿里图标iconfont
该文章指导如何在Vue项目中引入并使用阿里图标库Iconfont,包括图标的选取、下载配置文件及在项目中引入和使用图标的具体步骤。
|
17天前
|
JavaScript 前端开发
Vue项目使用px2rem
Vue项目使用px2rem
|
21天前
|
JavaScript 前端开发
Vue项目使用px2rem
Vue项目使用px2rem
|
6天前
|
API UED
升级 Vue3 后,项目的打包体积会有什么变化?
升级 Vue3 后,项目的打包体积会有什么变化?
92 57
下一篇
无影云桌面