写点什么

Vue3 + TypeScript 开发实践总结

用户头像
HaiJun
关注
发布于: 2 小时前
Vue3 + TypeScript 开发实践总结

前言

迟来的 Vue3 文章,其实早在今年 3 月份时就把 Vue3 过了一遍。<br/>在去年年末又把 TypeScript 重新学了一遍,为了上 Vue3 的车,更好的开车。<br/>在上家公司 4 月份时,上级领导分配了一个内部的 党务系统开发 ,这个系统前端是由我一个人来开发,功能和需求也不怎么复杂的一个B 端 系统,直接上的 Vue3 + TypeScript + Element Plus 开发的,开发两周到最后的上线,期间也遇到很多小坑,很多无处可查,慢慢琢磨最后还是克服了。

Vue3 + TypeScript Study

一, 环境配置

1.1 安装最新 Vue 脚手架

npm install -g @vue/cli
yarn global add @vue/cli
复制代码

1.2 创建 Vue3 项目

vue create projectName
复制代码


1.3 现有 Vue 2 项目 升级到 Vue3

vue add typescript
复制代码

二, 进击 Vue3

2. 1 Vue 2 局限性

  1. 随着组件与组件依赖之间不断变大,组件很难读取和维护

  2. 没有完美的方法解决跨组件代码重用

2.2 Vue 3 如何解决 Vue 2 局限

  1. 组件难以维护管理


【在 Vue3 中 编写组合函数,使用 Compositon Api setUp 来解决】


  1. 没有完美的方法解决跨组件代码重用

三,Vue3 Composition Ap i

3.1 关于 Composition Api

在 Vue3 中,也可以不使用 Composition Api 来编写组件,它只是在 Vue3 中编写组件中的另一种方法,内部简化了好多操作。


所以你还可以继续使用 Vue2 的方式来 编写 组件。

3.2 什么时候使用 Composition Api

  1. TypeScript` 的支持

  2. 编写大型组件时,可以使用 Composition Api 组合函数很好的管理状态

  3. 跨组件重用代码时

四,Composition Api 必备基础

4.1 什么是 setup

setup 是用来配置组件状态的另一种实现。


在 setup 中定义的状态,方法要想在模板中使用,必须 return

注意:

  • setup 方法是在 components , props data Methods Computed Lifecycle methods 之前执行

  • 同时在 setup 中是不能访问 this

4.2 ref 创建响应式变量

Vue2 中,我们定义一个响应式变量可以直接在 data 中 定义并且在模板中使用该变量。 如果 使用的 composition api 的话,我们得在 setup 中 使用 ref 来创建 响应式变量,并且得将它返回,才能在页面中使用。

使用

  • 引入 ref import { ref } from 'vue'

  • 初始变量 const name = ref('指定默认值')

  • 返回变量 return { name } 在 return 中还可以返回方法

  • setup 中 访问 定义的变量值,不能直接通过变量名来获取, 必须通过 变量名.value 来获取到该对象 、 值

这样的好处

  • 状态好管理,可以划分好几个 setup 状态管理,最后在一个 文件导入所有,并且使用。


<template>    <div>        <h1>{{title}}</h1>    </div></template>
<script>import {ref,defineComponent} from 'vue'export default defineComponent({ setup () { // 定义响应式变量 const title = ref('前端自学社区') // 访问该变量 console.log(title.value) // 返回变量 return {title} }})</script>
复制代码

4.3 生命周期

Composition Api 生命周期钩子 和 Vue 2 选项式 生命周期钩子名称一样,只是在使用 组合式 API时,前缀为 on, onMounted`


sd


下面代码中有两个 mounted 生命钩子,你猜哪个会先执行?


setup 会先执行


    setup () {        // 定义响应式变量        const title = ref('前端自学社区')        console.log(title)        // 返回变量        function getTitle(){            console.log(title.value)        }        // 页面在加载        onMounted(getTitle)        return {title}    },    mounted() {        console.log('测试 mounted 执行顺序')    },
复制代码

4.4 watch

setup 中使用 watch 响应式更改


  • 引入 watch, import { watch } from 'vue'

  • 直接使用 watch,watch 接受 3 个参数

    1. 要监听更新的 响应式引用或者 getter 函数

    2. 一个回调用来做更新后的操作

    3. 可选配置项


import {wathc} from 'vue'
// 定义响应式变量const num = ref(0)// 更新响应式变量function changeNum(){ num.value++}
// wathc 监听响应式变量watch( num,(newValue, oldValue) => { console.log(`newValue为:${newValue},--------oldValue为:${oldValue}`) } )
复制代码

4.5 computed

它也是 从 vue 导入,computed 函数返回一个作为 computed 的第一个参数传递的 getter 类回调的输出的一个只读响应式引用。为了访问新创建的计算变量的 value,我们需要像使用 ref 一样使用 .value property。


**当 num 值变化时,nums 的值会 *3 **


import {ref,computed} from 'vue';
const num = ref(0)
//更新numfunction changeNum(){ num.value++ }//监听num变化 const nums = computed(() =>{ return num.value * 3 })
复制代码

五,setup

5.1 接受两个参数

props: 父组件传递过来的属性, setup` 函数中 props 是响应式的,它会随着数据更新而更新,并且不能使用 ES6 解构,因为它会不能使 props 为响应式。


context : 它是一个普通的 对象,它暴露 3 个组件的· property


  1. Attribute

  2. 插槽

  3. 触发事件

context 不是 响应式的,所以可以使用 ES6 解构来简便写法。

   props:{        obj:{            type:Object        }    },     setup (props,{attrs,slots,emit}) {            console.log(attrs)            console.log(slots)            console.log(emit)           console.log(props.obj)     }
复制代码

5.2 组件加载 setup 时注意

在组件执行 setup 时, 组件实例没有被创建,因此就无法访问以下属性


  • data

  • computed

  • methods

六,生命周期

setup 中使用 生命周期时,前缀必须加 on.


七, 跨组件之间传值

Vue 2 中,我们可以使用 Provide/Inject 跨组件传值,在 Vue 3 中也可以。


setup 中 使用,必须从 vue 中导入使用。


使用 Provide 时,一般设置为 响应式更新的,这样的话,父组件变更,子组件,子孙组件也跟着更新。

怎么设置为响应式更新呢?

  1. 使用 ref / reactive 创建响应式变量

  2. 使用 provide('name', '要传递的响应式变量')

  3. 最后添加一个更新 响应式变量的事件,这样响应式变量更新, provide 中的变量也跟着更新。

父组件

父组件import { provide, defineComponent, ref, reactive } from "vue";
<template> <Son/> </template>

<script> import { provide, defineComponent, ref, reactive } from "vue"; export default defineComponent({ setup() { const father = ref("我父组件"); const info = reactive({ id: 23, message: "前端自学社区", }); function changeProvide(){ info.message = '测试' } provide('father',father) provide('info',info) return {changeProvide}; } })</script>
复制代码

子组件

<template>    <div>        <h1>{{info.message}}</h1>        <h1>{{fatherData}}</h1>    </div></template>
<script>import {provide, defineComponent,ref,reactive, inject} from 'vue'export default defineComponent({ setup () { const fatherData = inject('father') const info = inject('info') return {fatherData,info} }})</script>
复制代码

八, 在 Vue 中 使用 TypeScirpt 技巧

8.1 接口约束约束属性

采用 TypeScirpt 的特性, 类型断言 + 接口 完美的对 属性进行了 约束

interface
分页查询 字段属性类型验证export default  interface queryType{    page: Number,    size: Number,    name: String,    age:  Number}
复制代码
组件中使用
import queryType from '../interface/Home'

data() { return { query:{ page:0, size:10, name:'测试', age: 2 } as queryType } },
复制代码

8.2 组件使用 来 defineComponent 定义

这样 TypeScript 正确推断 Vue 组件选项中的类型


import { defineComponent } from 'vue'
export default defineComponent({ setup(){ return{ } }})
复制代码

8.3 类型声明 reactive

export default  interface Product {    name:String,    price:Number,    address:String}


import Product from '@/interface/Product' import {reactive} from 'vue'const product = reactive({name:'xiaomi 11',price:5999,address:'北京'}) as Product return {fatherData,info,product}
复制代码


更多精彩文章在微信公众号


最后

文中如有错误,欢迎码友在评论区指正,如果对你有所帮助,欢迎点赞和关注~~~

发布于: 2 小时前阅读数: 5
用户头像

HaiJun

关注

还未添加个人签名 2020.04.02 加入

海军,专注Web前端领域开发,分享开发经验与最新前端技术。 微信公众号: 前端自学社区

评论

发布
暂无评论
Vue3 + TypeScript 开发实践总结