写点什么

Vue3 TypeScript 使用教程 - 实战 Vue3 element-plus 开发「待办清单」

作者:蒋川
  • 2022 年 5 月 27 日
  • 本文字数:7693 字

    阅读完需:约 25 分钟

Vue3 TypeScript 使用教程 - 实战 Vue3 element-plus 开发「待办清单」

本文完整版:《Vue3 TypeScript 使用教程 - 实战 Vue3 element-plus 开发「待办清单」


Vue3 的源码使用 TypeScript 全部重构,而 TypeScript 是 JS 的一个超集,主要提供对 ES6 的支持以及更棒的代码可读性和高维护性。可以说 Vue3 Typescript 已经成为开发标配。本文带领大家从搭建环境开始,手把手带领大家用 Vue3 Typescript + element-plus 开发一个极简「待办清单」app,在实战中学习 Vue3 TypeScript。


如果你正在搭建后台管理工具,又不想处理前端问题,推荐使用卡拉云 ,卡拉云是新一代低代码开发工具,可一键接入常见数据库及 API ,无需懂前端,仅需拖拽即可快速搭建属于你自己的后台管理工具,一周工作量缩减至一天,详见本文文末。

Vue3 Typescript 环境搭建

这里我们通过 vue-cli 脚手架来初始化项目,如果没有全局安装 vue-cli 也没有关系,可以通过 node 自带的 npx 命令来初始化项目:


vue create kalacloud-vue3-ts// ORnpx vue create kalacloud-vue3-ts
复制代码


执行上面的命令,会进入一个交互式的命令行界面:



会有 3 个选项,分别是 Vue2 的项目模版、Vue3 的项目模版以及手动安装模式。这里我们选择手动安装,因为我们需要添加 Typescript 的支持,然后按回车键会进入到下一步:



这里需要选择我们需要安装的其他支持,按空格键来选中 Typescript,然后再按回车键,进入下一步,会让我们选择 Vue 的版本:



这里选择 3.x,然后按回车键进入下一步,这个界面是询问我们是否使用 vue-class-component 形式来开发代码:



我们输入 n,因为 Vue3 开始,官方推荐开发者使用 Composition API 的形式来组织代码,然后进入下一步:



这个选项的含义是说使用 babelTypescript 做代码编译(包括自动引入 polyfill,编译 JSX 等),这里我们输入 y,然后进入下一步:



这里我们选择 ESLint + Standard config 来作为代码检测工具,然后进入下一步:



选择 Lint on save 即可,在代码保存的时候,自动修正不符合 eslint 规则的代码,然后进入下一步:



这个选项的含义是说把 babel eslint 这些工具单独放在各自的配置文件还是统一写入 package.json 文件中,这里我们选择 In dedicated config files,然后按回车进入下一步:



这里是询问我们是否要保存刚才的选项配置,我们输入 n 即可,然后开始初始化项目代码,并安装对应的依赖包:



出现这样的界面,恭喜你,安装成功!



拓展阅读:《Vue3 Typescript + Axios 全栈开发教程:手把手教你写 APP 实战

Vue3 TypeScript 目录及重点文件解读

安装成功之后,会有一个初始项目结构:



下面给大家介绍下主要的文件:


|-- public //无需打包的静态资源文件|-- src //项目源代码目录    |-- assets //需要打包的静态资源    |-- components //公共组件    |-- main.ts //项目入口文件    |-- shims-vue.d.ts //声明文件|-- .browserslistrc //兼容目标浏览器范围的配置文件|-- .eslintrc.js //eslint配置文件|-- babel.config.js //babel配置文件|-- tsconfig.json //ts配置文件
复制代码


tsconfig.json 配置文件需要重点了解下:


{  "compilerOptions": {    "target": "esnext", //指定 ECMAScript 的目标版本,这里使用 “esnext” 是因为 vue-cli 内置的 webpack 会帮我们编译代码    "module": "esnext", //指定使用的模块规范    "strict": true, //是否开启严格模式    "jsx": "preserve", //指定 jsx 代码的生成    "importHelpers": true, //是否使用 ts 原生 lib 库中支持的辅助工具    "moduleResolution": "node", //模块解析策略    "skipLibCheck": true, //是否跳过默认库声明文件的类型检查    "esModuleInterop": true, //开启此选项可以修复 esm 和 cjs 在使用 import 的时候导致的兼容性问题    "allowSyntheticDefaultImports": true, //此选项允许开发者从没有设置默认导出的模块中进行默认导入    "sourceMap": true, //是否生成对应的 .map 文件    "baseUrl": ".", //用于解析模块名称的根目录    "types": [ //指定需要包含的类型声明的目录      "webpack-env"    ],    "paths": { //指定路径映射规则,类似 webpack 中 alisa 的用法      "@/*": [        "src/*"      ]    },    "lib": [ //指定要包含在编译中的库文件      "esnext",      "dom",      "dom.iterable",      "scripthost"    ]  },  "include": [ //指定需要编译的文件类型或目录    "src/**/*.ts",    "src/**/*.tsx",    "src/**/*.vue",    "tests/**/*.ts",    "tests/**/*.tsx"  ],  "exclude": [ //排除不需要编译的文件或目录    "node_modules"  ]}
复制代码


然后我们运行 npm run serve,即可启动开发服务器,然后打开浏览器,输入 http://localhost:8081 就可以访问项目首页:



扩展阅读:《Vue form 表单异步验证终极教程 async-validator 表单校验

Vue3 Typescript 快速上手

接下来我们谈谈相对于 Vue2来说 Vue3有哪些提升与变化,了解这些变化,让我们更容易上手 Vue3,我打算从性能差别及 Composition API 使用两个大方面来谈,帮助大家快速上手。

Vue3 Typescript 与 Vue2 性能优化对比

  • 性能优化

  • 源码体积的优化,Vue3 引入 tree-shaking 的技术,减少打包体积

  • 底层响应式的优化,Vue3 底层依赖 Proxy API 实现数据响应式,对比 Vue2Object.defineProperty 有更强的数据劫持能力,并且可以做到“惰性监听”

  • 编译时优化,提出 block tree 概念,每次 diff 只会比较两棵树的动态节点,对比 Vue2 的组件树全量 diff,有明显的性能优势

  • 语法 API 优化:Composition API

  • 优化代码逻辑组织,可以让代码逻辑更聚焦

  • 类似 hook 的使用方法,优化组件复用的能力

  • 源码优化

  • 使用 monorepo 更好的代码管理代码

  • 使用 TypeScript 重构项目源码,利于代码的维护


以上几点都是 Vue3 的这次主要改进,接下来开始学习 Composition API 的使用。


扩展阅读:《Element Plus 如何按需引入和自动导入?

Vue3 setup & ref 使用教程

src 目录下新建文件夹 test-api,并创建 Setup.vue 文件:


<template>  <div>    <h2>ref & setup 基本使用方法</h2>    <h2>{{ counter }}</h2>    <button @click="add">+</button>    <button @click="minus">-</button>  </div></template>
<script lang="ts">import { defineComponent, ref } from 'vue'
export default defineComponent({ name: 'Setup', setup (props, context) { console.log(props, context) const counter = ref(0)
const add = () => { counter.value = counter.value + 1 }
const minus = () => { counter.value = counter.value - 1 }
return { counter, add, minus } }})</script>
复制代码


然后修改 App.vue 文件如下:


<template>  <SetupVue /></template>
<script lang="ts">import { defineComponent } from 'vue'import SetupVue from './test-api/Setup.vue'
export default defineComponent({ name: 'App', components: { SetupVue }})</script>
<style>#app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}</style>
复制代码


可以看到界面会发生变化,并且可以正常使用加减功能:


14-vue-ts-setup-ref.gif


这是最简单的 setupref 的使用,setup 就是 Composition API 的入口,可以认为是组件的逻辑入口。ref 用来创建响应式的数据对象,传入的参数为基本类型,返回一个对象,该对象是响应式对象,并且只包含一个 value 属性,用于读取这个对象的值。


扩展阅读:《5 款最棒的 Vue UI 移动端组件库 - 特别针对国内使用场景推荐

Vue3 reactive 使用教程

reactive 有点类似 ref,只不过 reactive 接受的是引用类型,比如对象,数组等,返回的也是一个响应式数据。 在 test-api 下新建 Reactive.vue 文件:


<template>  <div>    <h2>reactive 基本使用方法</h2>    <h2>{{ info.name }} - {{ info.en }}</h2>    <h3>{{ info.desc }}</h3>    <button @click="updateDesc">update desc</button>  </div></template>
<script lang="ts">import { defineComponent, reactive } from 'vue'
export default defineComponent({ name: 'Setup', setup () { const info = reactive({ name: '卡拉云', en: 'kalacloud', desc: '' })
const updateDesc = () => { info.desc = '「卡拉云 - 极速搭建企业内部工具,十倍提升开发效率」' }
return { info, updateDesc } }})</script>
复制代码


然后再 App.vue 中导入,可以看到效果:


15-vue-ts-reactive.gif


reactiveref 不同的是,ref 创建出来的数据可以直接在模版中使用,不需要 .value 取值,vue 内部会帮我们自动处理。


不想处理 Vue 前端问题?

试试卡拉云,拖拽组件连接 API 和数据库直接生成后台管理工具,数月的工期降低至 1 天


扩展阅读:《如何在 Vue 中加入图表 - Vue echarts 使用教程

Vue3 watch 使用教程

这个 API 和 Vue2 中 watch 功能基本一致,接受三个参数:监听的值、回调、其他配置项,我们来使用一下,这里基于 Setup.vue 稍作修改即可:


<template>  <div>    <h2>watch 基本使用方法</h2>    <h2>{{ counter }}</h2>    <button @click="add">+</button>    <button @click="minus">-</button>  </div></template>
<script lang="ts">import { defineComponent, ref, watch } from 'vue'
export default defineComponent({ name: 'Setup', setup (props, context) { console.log(props, context) const counter = ref(0)
const add = () => { counter.value = counter.value + 1 }
const minus = () => { counter.value = counter.value - 1 }
watch(counter, (newValue, oldValue) => { console.log('counter 发生了变化,最新的值是:', newValue) })
return { counter, add, minus } }})</script>
复制代码


可以看到,每次 counter 发生改变,都可以输出到控制台最新的结果:


16-vue-ts-watch.gif


watch 第三个参数接受一个可选对象:


{   immediate: true, // 初始化的时候就会执行一次回调函数  deep: false, // 深度监听对象的变化  flush: 'pre' | 'post' | 'sync' // pre=回调函数在渲染前调用;post=回调函数在渲染后调用;sync=回调将被同步调用,慎用!可能会阻塞页面渲染}
复制代码


扩展阅读:《最好用的 6 款 Vue 拖拽组件库推荐

Vue3 computed 使用教程

computed 是计算属性,其值依赖响应式数据,如果响应式数据发生改变,vue 会帮我们自动计算改变后的值,像这样使用,在 test-api 新建 Computed.vue 文件:


<template>  <div>    <h2>computed 基本使用方法</h2>    <h3>「卡拉云 - 极速搭建企业内部工具,十倍提升开发效率」</h3>    <h2>{{ info }}</h2>    <button @click="update">update</button>  </div></template>
<script lang="ts">import { computed, defineComponent, reactive, ref } from 'vue'
export default defineComponent({ name: 'Setup', setup () { const prefix = ref('') const msg = reactive({ name: '卡拉云' })
const info = computed(() => prefix.value + msg.name)
const update = () => { prefix.value = 'kalacloud - ' }
return { info, update } }})</script>
复制代码


我们会发现,prefix 发生了改变,info 也会随之改变,这就是 computed 的用法


17-vue-ts-computed.gif


如果被依赖的响应式数据没有发生改变,那么也不会重新计算,所以 computed 还有缓存的特性,一般用于缓存计算量比较大的数据。


以上是 Vue3 Composition API 的一些使用方法,接下来,我会带领大家实际开发一个简单的应用,巩固学习的这些 API。


扩展阅读:《ToolJet 是什么,怎么样? —— 低代码开发平台测评

使用 Vue3 TypeScript + element-plus 开发「待办清单」实例

先为我们的应用安装 UI 框架,这样视觉上会好看些,在命令行执行下面的命令:


npm install element-plus --save
复制代码



安装好之后,在 main.ts 中 z 户厕组件并导入样式文件:


import { createApp } from 'vue'import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'import App from './App.vue'
const app = createApp(App)app.use(ElementPlus)
app.mount('#app')
复制代码


先创建一个 types 文件夹,用来存放项目中类型声明文件,比如我们这个 todo 应用,可以创建一个 todo.ts:


export interface Todo {  id: number;  title: string;  done: boolean;}
复制代码


然后在 components 文件夹下新建 TodoList.vue,这个组件用来实现处理每个待办事项的操作逻辑


<template>  <div class="todo-item">    <el-checkbox v-model="todo!.done" />    <el-alert class="alert" :title="todo!.title" :type="todo!.done ? 'success' : 'warning'" :closable="false" />    <el-button type="danger" @click="remove">删除</el-button>  </div></template>
<script lang="ts">import { defineComponent, PropType } from 'vue'import { Todo } from '../types/todo'
export default defineComponent({ props: { todo: { type: Object as PropType<Todo> } }, emits: ['toggle', 'remove'], setup (props, context) { const toggle = () => { context.emit('toggle', props.todo!.id) }
const remove = () => { context.emit('remove', props.todo!.id) }
return { toggle, remove } }})</script>
<style scoped>.todo-item { display: flex; align-items: center; margin-bottom: 20px;}.alert { margin: 0 20px;}</style>
复制代码


我们把 toggleremove 这两个操作通过 emit 派发给父组件,在父组件去实现具体的业务逻辑,不过先不着急,我们先实现添加待办事项的组件,同样在 components 中创建 AddTodo.vue:


<template>  <div class="add-todo">    <el-input type="text" v-model="state.inputValue" />    <el-button @click="onClick" class="add-button" type="primary">添加</el-button>  </div></template>
<script lang="ts">import { defineComponent, reactive, watchEffect } from 'vue'
interface State { inputValue: string;}export default defineComponent({ emits: ['add'], setup (_, context) { const state = reactive<State>({ inputValue: '' })
const onClick = () => { context.emit('add', state.inputValue) state.inputValue = '' }
return { state, onClick } }})</script>
<style scoped>.add-todo { display: flex;}.add-button { margin-left: 20px;}</style>
复制代码


同样的,使用 context.emit('add', state.inputValue) 来派发事件给父组件,然后我们先实现 addremovetoggle 这三个方法,并封装成一个工具函数,在 src 目录中创建 utils 文件夹,然后创建 todoAction.ts,用来承载具体的业务逻辑:


import { Ref } from 'vue'import { Todo } from '@/types/todo'
export default (todos: Ref<Todo[]>) => { const addTodo = (title: string) => { todos.value = [...todos.value, { id: todos.value.length + 1, title, done: false }] }
const removeTodo = (id: number) => { todos.value = todos.value.filter(todo => todo.id !== id) }
const toggleTodo = (id: number) => { const todo = todos.value.find(todo => todo.id === id) if (!todo) return todo.done = !todo.done }
return { addTodo, removeTodo, toggleTodo }}
复制代码


addTodo 用来实现添加一个待办事项,removeTodo 用来实现移除一个待办事项,toggleTodo 用来更新待办事项的状态。最后我们来实现父组件,创建 Todo.vue 文件:


<template>  <todo-list    v-for="todo in todos"    :todo="todo"    :key="todo.id"    @toggle="toggleTodo"    @remove="removeTodo"  />  <add-todo    @add="addTodo"  /></template>
<script lang="ts">import { defineComponent, watchEffect, ref } from 'vue'import TodoList from './TodoList.vue'import AddTodo from './AddTodo.vue'import todoAction from '../utils/todoAction'import { Todo } from '../types/todo'
const initialTodos: Todo[] = [ { id: 1, title: '使用卡拉云创建表单', done: false }, { id: 2, title: '使用卡拉云创建图表', done: false }, { id: 3, title: '使用卡拉云创建应用', done: false }]
export default defineComponent({ components: { TodoList, AddTodo }, setup () { const todos = ref<Todo[]>(initialTodos) const { addTodo, removeTodo, toggleTodo } = todoAction(todos)
return { todos, addTodo, removeTodo, toggleTodo } }})</script>
复制代码


组件的代码实现基本完成了,在 App.vue 中进行使用,最后的效果如下:


19-vue3-ts-final.gif


这个应用虽然简单,但是五脏俱全,通过这篇文章,大家可以学习到如何基于 Vue3 的组合 API 并结合 Typescript 进行开发。本文中的所有代码均可以在 kalacloud-vue3-ts 中找到。


扩展阅读:《appsmith 是什么?怎么样,评价如何

Vue3 Typescript 上手教程总结

本文详细讲解新版 Vue3 Typescript 与旧版 Vue 有什么区别及代码上的不同。其实如果你根本不想处理复杂的前端问题,完全可以使用卡拉云来搭建前端工具,卡拉云内置多种常用组件,无需懂任何前端,仅需拖拽即可快速生成,一键连接后端数据源,极速开发后台管理工具。


卡拉云可帮你快速搭建企业内部工具,下图为使用卡拉云搭建的内部广告投放监测系统,无需懂前端,仅需拖拽组件,10 分钟搞定。你也可以快速搭建一套属于你的后台管理工具,了解更多



卡拉云是新一代低代码开发平台,与前端框架 Vue、React 等相比,卡拉云的优势在于不用首先搭建开发环境,直接注册即可开始使用。开发者完全不用处理任何前端问题,只需简单拖拽,即可快速生成所需组件,可一键接入常见数据库及 API,根据引导简单几步打通前后端,数周的开发时间,缩短至 1 小时。立即免费试用卡拉云


扩展阅读:


发布于: 刚刚阅读数: 4
用户头像

蒋川

关注

我的微信:HiJiangChuan 2020.09.08 加入

卡拉云 CMO 卡拉云是一套帮助后端程序员搭建企业内部工具的系统,欢迎试用 www.kalacloud.com

评论

发布
暂无评论
Vue3 TypeScript 使用教程 - 实战 Vue3 element-plus 开发「待办清单」_typescript_蒋川_InfoQ写作社区