Vue3.0最新动态:script-setup定稿,部分实验性API将弃用

 [[413042]]

最近一段时间挺忙,对 Vue 3.0 的更新记录看的比较少,今天看了一下 release 记录,发现最新的 2 个小版本对 script-setup 这个新特性改动还算蛮大的,之前的用法都调整了不少。今天距离上一次发文讨论 script-setup 新特性已经有 4 个多月了(回顾上一篇[1]),虽然截止至 7 月 2 日的 3.1.4 版本,script-setup 还是处于实验性阶段,但在同一天,尤大在 twitter[2] 上发布了一条推文,预告了它将会在 3.2.0 版本脱离实验状态,正式进入 Vue 3.0 的队伍。

先简单梳理一下本次定稿下来的一些调整:

useContext API 被弃用

在原先,可以通过该 API 来获取组件的上下文信息,包含了 attrs 、slots 、emit、expose 等父子组件通信数据和方法。 

 
 
 
 
  1. // 导入 useContext 组件  
  2. import { useContext } from "vue";  
  3. // 获取 context  
  4. const ctx = useContext(); 

该 API 将在 3.2 版本之后删除,context 里面的数据,会用新的 useSlots 和 useAttrs API 来代替。

新增 useSlots API 和 useAttrs API

在 useContext API 被删除后,原先的上下文数据,将由这两个新 API 获取到。

useAttrs

顾名思义, useAttrs 可以是用来获取 attrs 数据的(也就是非 props 的属性值)。 

 
 
 
 
  1. // 导入 useAttrs 组件  
  2. import { useAttrs } from "vue"; 
  3. // 获取 attrs  
  4. const attrs = useAttrs();  
  5. // attrs是个对象,和 props 一样,需要通过 key 来得到对应的单个 attr  
  6. console.log(attrs.msg); 

如果当前组件里没有将某个属性指定为 props,那么父组件绑定下来的属性值,都会进入到 attrs 里,通过这个新 API 来拿到。

useSlots

同样,通过 API 的命名也能了解它是用来获取插槽数据的。但这个 API 对大部分同学来说应该用的比较少,因为大部分 Vue 开发者应该都是用的 SFC 模式(单组件),插槽可以直接在 template 里使用 标签渲染。所以,我个人觉得这个 API 的目标用户是面向 JSX / TSX 的开发者,简单的用法参考如下:父组件,可以传入默认插槽和命名插槽: 

 
 
 
 
  1.   
  2.       
  3.     
  4.     
  5.   
  6.   
  7.   import ChildTSX from "@cp/context/Child.tsx";  
  8.  

那么在 JSX / TSX 的子组件,通过 useSlots 来获取父组件传进来的 slots 数据进行渲染: 

 
 
 
 
  1. import { defineComponent, useSlots } from "vue";  
  2. const ChildTSX = defineComponent({  
  3.   setup() {  
  4.     // 获取插槽数据  
  5.     const slots = useSlots();  
  6.     // 渲染组件  
  7.     return () => (  
  8.       
      
  9.         // 渲染默认插槽  
  10.         

    {slots.default ? slots.default() : ""}

      
  11.         // 渲染命名插槽  
  12.         

    {slots.msg ? slots.msg() : ""}

      
  13.       
  
  •     );  
  •   },  
  • });  
  • export default ChildTSX; 
  • 新增 defineExpose API

    在标准组件写法里,子组件的数据都是默认隐式暴露给父组件的,但在 script-setup 模式下,所有数据只是默认 return 给 template 使用,不会暴露到组件外,所以父组件是无法直接通过挂载 ref 变量获取子组件的数据。如果要调用子组件的数据,需要先在子组件显示的暴露出来,才能够正确的拿到,这个操作,就是由 expose 来完成。expose 也是 context 的一个组件成员,原来的用法,是从 useContext 里导出: 

     
     
     
     
    1. // 导入 useContext 组件  
    2. import { useContext } from "vue";  
    3. // 启用expose组件  
    4. const { expose } = useContext();  
    5. // 定义一个想提供给父组件拿到的数据  
    6. const msg: string = "Hello World!";  
    7. // 显示暴露的数据,才可以在父组件拿到  
    8. expose({  
    9.   msg,  
    10. }); 

    由于 useContext 会在未来版本里移除,所以新增了 defineExpose API 来实现 expose 的功能。新的 API 用法: 

     
     
     
     
    1. // 导入 defineExpose 组件  
    2. import { defineExpose } from "vue";  
    3. // 定义数据  
    4. const msg: string = "Hello World!";  
    5. // 暴露给父组件  
    6. defineExpose({  
    7.   msg,  
    8. }); 

    父组件就可以通过 ref API 去拿到子组件暴露出来的 msg 数据了。

    改名 defineEmits API

    使用 defineEmits 取待原来的 defineEmit API ,也就是改名了。好吧,我之前的文章还特地强调了 defineProps 是复数结尾,带有 s,而 defineEmit 没有,如今,都统一了,都是复数形式。从尤大的更新说明里看,大约只是一个 typo 更新,对比原来的 defineEmit ,目的是使用新的 defineEmits 与标准组件的 emits 命名上更为接近,和 defineProps 也更统一。╮(╯▽╰)╭ 所以用法方面和原来是没什么区别的: 

     
     
     
     
    1. // 导入 defineEmits 组件  
    2. import { defineEmits } from "vue";  
    3. // 获取 emit  
    4. const emit = defineEmits(["say-hi", "chang-name"]);  
    5. // 调用 emit 打招呼  
    6. emit("say-hi", "Hello!");  
    7. // 调用 emit 改名  
    8. emit("chang-name", "Tom"); 

    新增 withDefaults API

    说完 emits,经常与之同时出现的 props 也有一些变化,本次是带来了一个全新的 withDefaults API,用于辅助 defineProps 来指定 prop 的默认值。在以前的文章我有提及到,当你用 TypeScript 编程时,defineProps 有两种类型指定方式:

        1.  通过构造函数进行检查(传统方法)

    第一种方式是使用 JavaScript 原生构造函数进行类型规定,使用这种方法时,如果你要限制 props 的类型和默认值,需要通过一个 “对象” 入参来传递给 defineProps,比如: 

     
     
     
     
    1. // 导入 defineProps 组件  
    2. import { defineProps } from "vue"; 
    3.  // 定义 props  
    4. defineProps({  
    5.   name: {  
    6.     type: String,  
    7.     required: false,  
    8.     default: "Petter",  
    9.   },  
    10.   userInfo: Object,  
    11.   tags: Array,  
    12. }); 

        1.  使用类型注解进行检查(TS 专属)

    第二种方式是按照 TS 的书写习惯来定义数据类型,这种情况下需要遵循 TypeScript 的类型规范,比如字符串是 string,而不是 String。 

     
     
     
     
    1. // 导入 defineProps 组件  
    2. import { defineProps } from "vue";  
    3. // 对象类型接口  
    4. interface UserInfo {  
    5.   id: number;  
    6.   age: number;  
    7. }  
    8. // 定义 props  
    9. defineProps<{  
    10.   name: string;  
    11.   phoneNumber: number;  
    12.   userInfo: UserInfo;  
    13.   tags: string[];  
    14. }>();import { defineProps, withDefaults } from "vue";  
    15. withDefaults(  
    16.   defineProps<{  
    17.     size?: number;  
    18.     labels?: string[];  
    19.   }>(),  
    20.   {  
    21.     size: 3,  
    22.     labels: () => ["default label"],  
    23.   }  
    24. );  
    25. import { defineProps, withDefaults } from "vue";  
    26. withDefaults( 
    27.    defineProps<{  
    28.     size?: number;  
    29.     labels?: string[];  
    30.   }>(),  
    31.   {  
    32.     size: 3,  
    33.     labels: () => ["default label"],  
    34.   }  
    35. ); 

    在此之前,使用第二种方法,是无法指定默认值的(在当时的 RFC 的文档里也有说明无法指定)。如今,这个新的 withDefaults API 可以让你在使用 TS 类型系统时,也可以指定 props 的默认值。它接收两个入参:

    可能缺乏一些官方描述,还是看参考用法可能更直观: 

     
     
     
     
    1. import { defineProps, withDefaults } from "vue";  
    2. withDefaults(  
    3.   defineProps<{  
    4.     size?: number;  
    5.     labels?: string[];  
    6.   }>(),  
    7.   {  
    8.     size: 3,  
    9.     labels: () => ["default label"],  
    10.   }  
    11. ); 

    顶级 await 的支持

    不必再配合 async 就可以直接使用 await 了,这种情况下,组件的 setup 会自动变成 async setup 。 

     
     
     
     
    1.   
    2.   const post = await fetch(`/api/post/1`).then((r) => r.json());  
    3.  

    它转换成标准组件的写法就是: 

     
     
     
     
    1.   
    2.   import { defineComponent, withAsyncContext } from "vue"; 
    3.    export default defineComponent({  
    4.     async setup() {  
    5.       const post = await withAsyncContext(  
    6.         fetch(`/api/post/1`).then((r) => r.json())  
    7.       );  
    8.       return {  
    9.         post,  
    10.       };  
    11.     },  
    12.   });  
    13.  

    参考资料

    以上所有的资料都来自于尤大在 PR 227 的评论通告……传送门:script setup by yyx990803 · Pull Request #227 · vuejs/rfcsgithub.com[3]好隐蔽的说,而且原来的 RFC 仓库的文档也删除了,换了新的文档也是找了好久才翻到新的,本文先根据尤大的通告做一波简单的说明,文章首发在博客,只同步在知乎。Vue3.0 最新动态:script-setup 定稿 部分实验性 API 将弃用 - 程沛权 - 养了三只猫 chengpeiquan.com[4]后续将会详细更新到 Vue3.0 学习教程与实战案例[5] 里。 

     

    当前名称:Vue3.0最新动态:script-setup定稿,部分实验性API将弃用
    网页URL:http://www.mswzjz.cn/qtweb/news22/458222.html

    攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能

    贝锐智能技术为您推荐以下文章

    网站排名知识

    同城分类信息