vue3+ts实际开发中该如何优雅书写vue3语法

目录
  • vue3语法的发展
  • 优势
  • Composition Api类型约束
  • 编译器宏
    • defineProps
    • defineEmits
    • defineExpose
  • 总结

vue3语法的发展

  1. Vue3 在早期版本( 3.0.0-beta.21 之前)中对 composition api 的支持,只能在组件选项 setup 函数中使用。
  2. 在 3.0.0-beta.21 版本中增加了 <script setup> 的实验特性。如果你使用了,会提示你 <script setup> 还处在实验特性阶段。
  3. 在 3.2.0 版本中移除<script setup> 的实验状态,从此,宣告 <script setup> 正式转正使用,成为框架稳定的特性之一。

所以我们现在直接就开始使用3.2.0之后的写法

优势

与组件选项 setup 函数对比, <script setup> 的优点:

  1. 更少、更简洁的代码,不需要使用 return {} 暴露变量和方法了,使用组件时不需要主动注册了;
  2. 更好的 Typescript 支持,使用纯 Typescript 声明 props 和抛出事件,不会再像 option api 里那么蹩脚了;
  3. 更好的运行时性能;
  4. 当然, <script setup> 也是有自己的缺点的,比如需要学习额外的 API。

Composition Api类型约束

<script setup lang="ts">
import { ref, reactive, computed } from 'vue'

type User = {
  name: string
  age: number
}

// ref
const msg1 = ref('')  //  会默认约束成 string 类型,因为ts类型推导
const msg2 = ref<string>('')  //  可以通过范型约束类型
const user1 = ref<User>({ name: 'tang', age: 18 })  //  范型约束
const user2 = ref({} as User)  // 类型断言

// reactive
const obj = reactive({})
const user3 = reactive<User>({ name: 'tang', age: 18 })
const user4 = reactive({} as User)

// computed
const msg3 = computed(() => msg1.value)
const user5 = computed<User>(() => {
  return { name: 'tang', age: 18 }
})
</script>

编译器宏

编译器宏(compiler macros) 有:defineProps、defineEmits、withDefaults、defineExpose 等。

编译器宏只能在 <script setup> 块中使用,不需要被导入,并且会在处理 <script setup> 块时被一同编译掉。

编译器宏必须在 <script setup> 的顶层使用,不可以在 <script setup> 的局部变量中引用

defineProps

<script setup> 块中是没有组件配置项的,也就是说是没有 props 选项,需要使用 defineProps 来声明 props 相关信息。defineProps 接收的对象和组件选项 props 的值一样。

我这边引用了pug 如果需要安装一下就可以直接使用 <template lang="pug">

好处可以减少代码量 层次也清楚

npm install pug
// componentA.vue 组件
<template lang="pug">
div
    div {{`我的名字是${name},今年${age}`}}
    div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}}
</template>
<script setup lang="ts">
interface item {
    name: string,
    age: string
}
const props = defineProps<{
    name: string,
    age: string,
    list?: item[] // ?非必传参数
}>()
</script>
// home.vue 页面
<template lang="pug">
.mainBg
    componentA(:name="name",:age="age", :list="list")
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import componentA from '@/components/componentA.vue';
let name = ref('')
const age = ref('')
const list = ref(
    [
        {
            name: '张三',
            age: '20'
        },
        {
            name: '李四',
            age: 18
        },
        {
            name: '王五',
            age: 25
        },
    ]
)
<style lang="scss">
.mainBg {
    padding: 10px;
}
</style>

这时候是可以看到TS写法里面 name和age是没有定义默认值

页面效果

Vue3 为我们提供了 withDefaults 这个编译器宏,给 props 提供默认值

// componentA.vue 组件
<template lang="pug">
div
    div {{`我的名字是${name},今年${age}`}}
    div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}}
</template>
<script setup lang="ts">
interface item {
    name: string,
    age: string
}
interface Props {
    name: string,
    age: string,
    list?: item[]
}
const props = withDefaults(defineProps<Props>(),{
    name: "小cc",
    age: "18",
    list: ()=> []
})
</script>

这边给它定义默认值之后保存 看页面发现还是没有把默认值展示出来

这是因为我们在home页面给name和age用ref赋值的时候给了 ‘ ’ 所以他把空当成了默认值就没有展示withDefaults里面给的默认值 这时候我们把name和age写成
let name = ref() const age = ref()

还有一种情况 当不给props定义默认值的时候 传参也是为空时

defineEmits

一样的,在 <script setup> 块中也是没有组件配置项 emits 的,需要使用 defineEmits 编译器宏声明 emits 相关信息。

// componentA.vue 组件
<template lang="pug">
div
    div {{`我的名字是${name},今年${age}`}}
    //- div(v-for="item in list",:key="item.name") {{`我的名字是${item.name},今年${item.age}`}}
    el-button(type="primary",@click="setName") 向父组件发送 name
    el-button(type="primary",@click="setAge") 向父组件发送 age
</template>
<script setup lang="ts">
interface item {
    name: string,
    age: string
}
interface Props {
    name: string,
    age: string,
    list?: item[]
}
const props = withDefaults(defineProps<Props>(),{
    name: "小cc",
    age: "18",
    list: ()=> []
})
const emits = defineEmits<{
    (e: 'changeName', value: string) : void,
    (e: 'changeAge', value: string) : void,
}>()
const setName = () => {
    emits('changeName', '小橙子')
}
const setAge = () => {
    emits("changeAge", "28")
}
</script>
// home.vue
<template lang="pug">
.mainBg
    componentA(:name="name",:age="age", :list="list", @changeName="changeName",@changeAge="changeAge")
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import componentA from '@/components/componentA.vue';
let name = ref('')
const age = ref('')
const list = ref(
    [
        {
            name: '张三',
            age: '20'
        },
        {
            name: '李四',
            age: 18
        },
        {
            name: '王五',
            age: 25
        },
    ]
)
const changeName = (val: string) => {
    name.value = val
}
const changeAge = (val: string) => {
    age.value = val
}
<style lang="scss">
.mainBg {
    padding: 10px;
}
</style>

点击后

defineExpose

在 Vue3 中,默认不会暴露任何在 <script setup> 中声明的绑定,即不能通过模板 ref 获取到组件实例声明的绑定。

Vue3 提供了 defineExpose 编译器宏,可以显式地暴露需要暴露的组件中声明的变量和方法。

这个情况的场景父组件需要直接调用子组件内部的方法或者修改子组件里的值时,需要将方法或值通过defineExpose暴露才能操作

// componentB.vue
<template lang="pug">
div
    h1 组件B
    h1 {{msg}}
</template>
<script setup lang="ts">
import {ref} from 'vue'

const msg = ref('今天天气不怎么好')

const changeMsg = (v: string) => {
    msg.value = v
}

// 对外暴露的属性 需要用ref 调用子组件方法是需要把方法暴露出去
defineExpose({
  msg,
  changeMsg,
})
</script>
<template lang="pug">
.mainBg
    el-button(type="primary",@click="handleChangeMsg") 组件B
    componentB(ref="root")
</template>

<script lang="ts" setup>
import { ref } from 'vue';
import componentB from '@/components/componentB.vue';
const root = ref<any>(null)
const handleChangeMsg = () => {
    root.value.changeMsg("果然 下雨了")
}
</script>

<style lang="scss">
.mainBg {
    padding: 10px;
}
</style>

如果把defineExpose注释掉

由于没有把这个方法暴露出来 导致找不到这个方法 changeMsg is not a function

总结

到此这篇关于vue3+ts实际开发中该如何优雅书写vue3语法的文章就介绍到这了,更多相关vue3+ts 书写vue3语法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Vue3项目中引用TS语法的实例讲解

    目录 基础语法 vue-router vuex##### elementPlus axios setup script 基础语法 定义data  //script标签上 **lang="ts"** <script lang="ts"> import { defineComponent, reactive, ref, toRefs } from 'vue'; //定义一个类型type或者接口interface来约束data type Todo = {  

  • 详解如何在Vue3使用<script lang=“ts“ setup>语法糖

    目录 迁移组件 隐式返回 defineProps defineEmits 默认关闭和defineExpose Vue 3.2 引入了语法,这是一种稍微不那么冗长的声明组件的方式.您可以通过向 SFC 的元素添加属性来启用它,然后可以删除组件中的一些样板.script setupsetupscript 让我们举一个实际的例子,并将其迁移到这个语法! 迁移组件 以下组件有两个道具(要显示的和一个标志).基于这两个道具,计算模板中显示的小马图像的URL(通过另一个组件).该组件还会在用户单击它时发出一

  • vue3+ts实际开发中该如何优雅书写vue3语法

    目录 vue3语法的发展 优势 Composition Api类型约束 编译器宏 defineProps defineEmits defineExpose 总结 vue3语法的发展 Vue3 在早期版本( 3.0.0-beta.21 之前)中对 composition api 的支持,只能在组件选项 setup 函数中使用. 在 3.0.0-beta.21 版本中增加了 <script setup> 的实验特性.如果你使用了,会提示你 <script setup> 还处在实验特性阶

  • 详解如何在Vue3+TS的项目中使用NProgress进度条

    目录 写在前面 在项目中安装 简单的封装 在Vue切换路由时展示进度条 写在前面 NProgress是一个轻量级的进度条组件,在Github上已经2.4万star数了,虽然这个组件已经好久没有更新了,最近一次更新是20年4月份,改了jQuery的版本,但是该组件的使用频率还是高的. 在项目中安装 这里的包管理工具使用的npm,如果你使用的是yarn或者pnpm,请自行更改安装命令,安装命令如下: npm i nprogress -S 因为我们是TS的项目,还需要安装其类型声明文件,命令如下: n

  • Vue3+TS+Vite+NaiveUI搭建一个项目骨架实现

    目录 写在前面 创建Vue3项目 开发规范 Vite配置 别名配置 环境变量 .env文件 定义环境变量 在vite.config.ts中获取环境变量 自动导入 NaiveUI的安装 写在最后 写在前面 现在已经有很多项目团队使用Vue3+TS进行开发,同时也就意味着Vue3的生态越来越完善,如果还是停留在Vue2的阶段已经out了,这篇文章将会使用Vue3+TS+NaivaUI搭建一个简单的项目骨架. 创建Vue3项目 首先我们通过Vite来创建一个Vue3+TS的一个项目,打开终端,找到我们

  • 使用Vue3+ts 开发ProTable源码教程示例

    目录 前台实现 实现效果 技术栈 使用方法 ProTable 设计思路 编码风格 css 小知识 表格操作 小结 后期功能扩展 后台实现 数据库 mysql 新建项目 RESTful 风格的 URL 定义 Sequelize controller model router.js API 文档 Apifox ts用到的一些 前台实现 实现效果 技术栈 vue3 + typescript + element-plus 使用方法 <template> <el-tabs type="b

  • 在Vue3中如何更优雅的使用echart图表详解

    目录 前言 封装思路 引入模块 封装功能 使用例子 总结 前言 在大屏可视化项目中,我们常常需要用到很多的图表组件,通常你会编写很多的option对图表进行渲染,以及引入它们所需的一些组件并使用echart.use. 在Vue2中我们常常把可复用的组件单独抽离出来,再通过props.emit等方法向复用组件中传入组件所需数据,而在Vue3中我们可以将一些逻辑功能写成hook进行抽离和复用再传入到视图中,这会不仅让你的组件中的代码更加优雅而且阅读性更强. 封装思路 引入模块 我们先创建lib.ts

  • web开发中如何优雅的解决"重复请求"问题

    目录 前言 提出问题 解决思路 axios 如何取消请求 封装axios 准备工作 开始封装 总结 前言 在我们web开发过程中,很多地方需要我们取消重复的请求.但是哪种场合需要我们取消呢?我们如何取消呢?带着这些问题我们阅读本文. 阅读完本文,你将了解以下内容: 需要取消重复请求的场景 我们如何取消重复请求 axios如何取消重复的请求 封装axios 如何给开源的项目提供源码 如何在本地调试npm包 提出问题 最近做的项目中,用的用户经常遇到这样的问题: 用户频繁切换筛选条件去请求数据,初次

  • vue3+ts中ref与reactive指定类型实现示例

    目录 ref 的基础特性 如何在ref中指定类型 reactive isRef.isReactive toRef.toRefs.toRaw ref 的基础特性 ref 约等于 reactive({ value: x }) ref() 可以定义时无参数,第一次赋值任意类型,然后就不能增加属性 const refa = ref(6) const rcta = reactive({ value: 12 }) console.log('refa:', refa) //RefImpl{...} conso

  • vue3+ts+Vuex中使用websocket协议方式

    目录 vue3+ts+Vuex使用websocket协议 在stroe中 vue3中 vue封装websocket 封装的socket.js文件内容 使用方法 vue3+ts+Vuex使用websocket协议 本文作者使用的是ts+vue3的setup语法糖,大家注意使用的vue版本! 在stroe中 import { createStore } from 'vuex' import { stateInt } from '../interface/storeInterface' const s

  • iOS开发中如何优雅的调试数据库详解

    背景 写代码难免出现bug. 储备些调试技能绝对能够提高你的工作效率,让bug无所遁形.相信大家应该都有所体会,我们在开发的时候,数据库的操作一直是一个很棘手的问题,后来发现Android下面有一个第三方的库还挺好用的,就模仿它搞了个iOS的,可以方便的通过浏览器查看.添加.删除.修改数据库.下面话不多说了,来一看看详细的介绍吧. 历史状况 我们来回想一下调试的过程: 如果在模拟器中调试: 找到模拟器应用中数据库的文件位置 拷回到一个比较方便打开的地方 安装一个数据库操作软件 打开数据库文件 s

  • vue3 element plus按需引入最优雅的用法实例

    全局导入 下载安装element plus后,在入口文件配置一下并挂载,就能畅通无阻的使用了.但问题是这样有很多用不上的组件都被打包进来了,导致包的体积非常大. 按需导入 采用按需导入的方法,其实是用解构的方式,从element的包中解构出来,再挂载到app上面.这样开发中用到什么组件就打包什么确实很好,减少了包的体积.但是又有一个新的问题,就是每次想要使用新的组件的时候,都要去解构一下,并且挂载.操作起来非常繁琐. 有什么办法能够像使用全局引入那样只配置一次,后面要用到什么组件,都会自己按需加

随机推荐