Vue 中使用 TypeScript以及多种写法-笔记

文章目录

  • 前言
  • 两种方式
    • Vue CLI 创建
    • 项目变动以及说明
    • 已有项目增加ts配置
  • Vue的多种写法
    • 常规
    • Options APIs
    • Class APIs
    • Class APIs+
  • 关于Vue3.0
  • 使用 realworld 练习
    • 创建模板 Layout
      • 在 public 中的 index 引入 css
      • 创建layout组件,将 realworld 提供的 Header 以及 Footer 拷贝过来
      • 修改 router 下的 index.ts
      • 修改 App.vue
    • 创建 home 组件
      • 将 realworld 提供的 Home 拷贝过来
      • 修改 router 下的 index.ts
    • 创建 login/register 组件
      • 将 realworld 提供的 Login/Register 拷贝过来
      • 修改 router 下的 index.ts
    • 使用 TS 开发业务功能
      • 安装 axios 以及封装
      • 封装 api
      • login/register 开发

前言

TypeScript (下面简称ts)越来越火爆(框架,github开源项目,公众号,文章都在增加ts相关内容…),不久的将来会成为前端必备技能(学不动了啊),记录怎样在vue项目中使用ts(写一些简单的demo)以及vue的多种写法。

两种方式

  1. Vue CLI 创建支持 TypeScript 的 Vue 项目
  2. 在一个已有的 Vue 项目中配置 ts 支持

Vue CLI 创建

  1. 进入目录创建项目
npx vue create vue-ts
? Please pick a preset: Manually select features
? Check the features needed for your project:Babel, TS, Router, Vuex, CSS Pre-processors, Linter
// CSS Pre-processors 使用less sass/scss stylus
// 是否使用class风格的语法
? Use class-style component syntax? (Y/n)y
// 是否使用babel转换ts之外的内容
// 选择之后还可以自动处理polyfills 转换JSX
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) y
// 是否使用history模式 服务端渲染必须使用history模式
? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)n
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):Less
? Pick a linter / formatter config:Standard
// 什么情况下触发ESLinter校验代码
? Pick additional lint features: Lint on save, Lint and fix on commit
// 怎样生成配置文件
? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.?In dedicated config files
? Save this as a preset for future projects?(y/N)n
  1. 创建完成,启动项目,启动成功浏览器打开是以下页面
    Vue 中使用 TypeScript以及多种写法-笔记_第1张图片

项目变动以及说明

初始项目结构以及变动的文件
Vue 中使用 TypeScript以及多种写法-笔记_第2张图片

package.json变动
Vue 中使用 TypeScript以及多种写法-笔记_第3张图片
HellowWord示例说明
Vue 中使用 TypeScript以及多种写法-笔记_第4张图片
总结:增加一些ts相关的配置,以及组件的写法
优点:强类型语言,编译阶段避免类型引起的作用,类型提示

已有项目增加ts配置

已有项目可以根据变动增加相应的内容,即可使用ts进入开发,详细内容参考官方文档

Vue的多种写法

常规

<script lang="ts">
  // 常规写法
  export default {
     
    data () {
     
      return {
     
        message: 'Hellow World'
      }
    },
    created () {
     }
  }

</script>

Options APIs

<script lang="ts">
  import Vue from 'vue'
  export default Vue.extend({
     
    name: 'Foo',
    data () {
     
      return {
     
        message: 'Hellow World'
      }
    },
    created () {
     }
  })
</script>

组件继承自Vue,类型更明确

Class APIs

<script lang="ts">
 import {
      Component, Vue } from 'vue-property-decorator'
 // 装饰器:一个函数用来拓展 Vue
 // 目前装饰器语法还不稳定,没有发布正式版不推荐
  @Component
  // 类名:组件的 name
  export default class Foo extends Vue {
     
    message: string = 'Hellow World'
  }
</script>

在App.vue中使用Foo组件
Vue 中使用 TypeScript以及多种写法-笔记_第5张图片
在Class写法中更改了data、methods、computed、watch等内容,详情请参考官方文档
代码

<!-- Foo -->
<template>
  <div id="">
    <h1>Foo 组件</h1>
    <p @click="test">{
     {
     size}}</p>
  </div>
</template>
<script lang="ts">
// Class APIs
import {
      Component, Vue, Watch } from 'vue-property-decorator'
// 装饰器:一个函数用来拓展 Vue
@Component
// 类名:组件的 name
export default class Foo extends Vue {
     
    message = 'Hellow World'
    count = 10
    // methods
    test () {
     
      console.log('Foo')
    }

    get size () {
     
      return this.message + '!'
    }
	
	// Watch 需要从 vue-property-decorator 中导入
	// @Watch('xx') 来监听某个属性
    @Watch('message')
    // 后续跟着处理函数,如果想要多个处理函数 可以在后面继续写
    getMessage (newVal: string, oldVal: string) {
     
      console.log('getMessage', newVal, oldVal)
    }
	getMessages (newVal: string, oldVal: string) {
     
      console.log('getMessages', newVal, oldVal)
    }
    
    @Watch('count')
    counts (newVal: string, oldVal: string) {
     
      console.log('counts', newVal, oldVal)
    }

    created () {
     
      setTimeout(() => {
     
        this.message = 'aaa'
        this.count++
      }, 3000)
    }
}
</script>

Class APIs+

进一步的提升了 Class APIs 的语法
详情参考文档(不是官方的)

关于Vue3.0

尤大大在B站 直播分享了vue-next v3.0.0-beta.1 版本
提出了6大亮点

  1. Performance:性能更比Vue 2.0强
  2. Tree shaking support:可以将无用模块“剪辑”,仅打包需要的
  3. Composition API:组合API
  4. Fragment, Teleport, Suspense:“碎片”,Teleport即Protal传送门,“悬念”
  5. Better TypeScript support:更优秀的Ts支持
  6. Custom Renderer API:暴露了自定义渲染API

由于版本还没有定稿,就不分享了,初体验网上到处都是大家随便看看,体验体验…

使用 realworld 练习

详细 API 请查看官网 (ps:还是官网)
realworld:提供了页面模板以及数据接口(示例:一个论坛)

创建模板 Layout

示例

在 public 中的 index 引入 css

Vue 中使用 TypeScript以及多种写法-笔记_第6张图片

创建layout组件,将 realworld 提供的 Header 以及 Footer 拷贝过来

<!-- layout -->
<template>
<div id="">
  <!-- 头部导航栏 -->
  <nav class="navbar navbar-light">
    <div class="container">
      <a class="navbar-brand" href="index.html">conduit</a>
      <ul class="nav navbar-nav pull-xs-right">
        <li class="nav-item">
          <!-- Add "active" class when you're on that page" -->
          <a class="nav-link active" href="">Home</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="">
            <i class="ion-compose"></i>&nbsp;New Post
          </a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="">
            <i class="ion-gear-a"></i>&nbsp;Settings
          </a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="">Sign up</a>
        </li>
      </ul>
    </div>
  </nav>

  <!-- 子路由出口 -->
  <router-view />

  <!-- 尾部 -->
  <footer>
    <div class="container">
      <a href="/" class="logo-font">conduit</a>
      <span class="attribution">
        An interactive learning project from <a href="https://thinkster.io">Thinkster</a>. Code &amp; design licensed under MIT.
      </span>
    </div>
  </footer>
</div>
</template>

<script lang='ts'>
import Vue from 'vue'
export default Vue.extend({
     
	name: 'LayoutIndex'
})
</script>

修改 router 下的 index.ts

import Vue from 'vue'
import VueRouter, {
      RouteConfig } from 'vue-router'
Vue.use(VueRouter)
const routes: Array<RouteConfig> = [
  // 使用异步路由
  {
     
    path: '/',
    component: () => import('@/views/layout/index.vue'),
    children: [
    ]
  }
]
const router = new VueRouter({
     
  routes
})
export default router

修改 App.vue

<template>
  <div id="app">
    <!-- 跟路由出口 -->
    <router-view />
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
     })
</script>

项目正常运行,且 Header 和 Footer 展示正常

创建 home 组件

将 realworld 提供的 Home 拷贝过来

Vue 中使用 TypeScript以及多种写法-笔记_第7张图片

修改 router 下的 index.ts

{
     
    path: '/',
    component: () => import('@/views/layout/index.vue'),
    children: [
      {
     
        path: '', // 默认子路由  path为空是会将内容默认渲染到组件当中
        name: 'home',
        component: () => import('@/views/home/index.vue')
      }
    ]
  }

启动项目,页面展示正常

创建 login/register 组件

将 realworld 提供的 Login/Register 拷贝过来

Vue 中使用 TypeScript以及多种写法-笔记_第8张图片

修改 router 下的 index.ts

{
     
    path: '/',
    component: () => import('@/views/layout/index.vue'),
    children: [
      {
     
        path: '', // 默认子路由  会将path为空的路由默认渲染到父路由当中
        name: 'home',
        component: () => import('@/views/home/index.vue')
      },
      {
     
        path: '/login',
        name: 'login',
        component: () => import('@/views/login/index.vue')
      }
    ]
  }

修改地址链接http://localhost:8080/#/login,进入 login 路由正常

使用 TS 开发业务功能

使用 realworld 提供的 requese API

安装 axios 以及封装

安装 axios
创建 utils 文件夹以及 request.ts
简易封装 axios
Vue 中使用 TypeScript以及多种写法-笔记_第9张图片

封装 api

创建 api 文件夹
封装 register 接口
Vue 中使用 TypeScript以及多种写法-笔记_第10张图片
修改 eslint 配置,接口不使用分隔符
.eslintrc.js 修改 rules
新增

'@typescript-eslint/member-delimiter-style': 'off'

login/register 开发

<!-- login/register -->
<template>
<div class="auth-page">
  <div class="container page">
    <div class="row">
      <div class="col-md-6 offset-md-3 col-xs-12">
        <h1 class="text-xs-center">Sign up</h1>
        <p class="text-xs-center">
          <a href="">Have an account?</a>
        </p>
        <ul class="error-messages">
          <li>That email is already taken</li>
        </ul>
        <form @submit.prevent="onSubmit">
          <fieldset class="form-group">
            <input v-model="user.username" class="form-control form-control-lg" type="text" placeholder="Your Name">
          </fieldset>
          <fieldset class="form-group">
            <input v-model="user.email" class="form-control form-control-lg" type="text" placeholder="Email">
          </fieldset>
          <fieldset class="form-group">
            <input v-model="user.password" class="form-control form-control-lg" type="password" placeholder="Password">
          </fieldset>
          <button class="btn btn-lg btn-primary pull-xs-right">
            Sign up
          </button>
        </form>
      </div>

    </div>
  </div>
</div>
</template>
<script lang='ts'>
import Vue from 'vue'
import {
      register } from '@/api/auth'

export default Vue.extend({
     
  name: 'LoginIndex',
  data () {
     
    return {
     
      user: {
     
        username: '',
        email: '',
        password: ''
      }
    }
  },
  methods: {
     
    onSubmit () {
     
      try {
     
        // 获取表单数据
        // 表单验证
        // 提交表单
        const data = register({
     
          user: this.user
        })
        console.log(data)
        // 根据返回结果处理后续操作
        this.$router.push({
     
          name: 'home'
        })
      } catch (error) {
     
        console.log('提交失败...', error)
      }
    }
  }
})
</script>

完成,接口访问正常,注册正常

你可能感兴趣的:(vue,vue)