十一、组合API(1)

本章概要

  • 为什么要引入组合API
  • setup() 函数

组合(Composition)API 是在 Vue 3.0 中引入的,它是一组附加的、基于函数的 API ,允许灵活地组合组件逻辑。
组合 API 并没有引入新的概念,更多地是将 Vue 的核心功能(如创建和观察响应状态)公开为独立函数,以此来代替 Vue 2.x 中的表达组件逻辑的选项。

11.1 为什么要引入组合API

使用 Vue 构建中小型应用程序是很容易,但随着 Vue 逐渐被开发人员所认可,许多用户开始使用 Vue 构建大型项目,这些项目由一个多名开发人员组成的团队在很长一段时间内迭代和维护,在一些项目中遇到了 Vue 2.x 所要求的编程模型的限制,遇到的问题可以归纳为以下两类:

  • 随着时间的推移,复杂组件的代码越来越难以理解,尤其是当开发人员在阅读不是自己编写的代码时。根本原因是 Vue 2.x 的现有 API 强制按选项组织代码,在某些情况下,按逻辑关注点组织代码更有意义。
  • 缺乏在多个组件之间提取和重用逻辑的干净且无成本的机制。

Vue 3.0 新增的组合 API 为用户组织组件代码提供了更大的灵活性。现在,可以将代码编写为函数,每个函数处理一个特定的功能,而不再需要按选项组织代码了。组合 API 还使用在组件之间甚至外部组件之间提取和重用逻辑变得更加简单。

此外,由于组合 API 是一套基于函数的 API ,因此能够更好地与 TypeScript 集成,使用组合 API 编写的代码可以享受完整的类型推断。组合 API 也可以与现有的基于选项的 API 一起使用,不过组合 API 是在选项(data、computed和methods)之前解析,因此在组合 API 中是无法访问这些选项所定义的属性的。

11.2 setup() 函数

setup() 函数是一个新的组件选项,它作为在组件内部使用组合 API 的入点口。setup() 函数在初始的 prop 解析之后,组件实例创建之前被调用。对于组件的生命周期钩子,setup() 函数在 beforeCreate 钩子之前调用。
如果 setup() 函数返回一个对象,该对象上的属性将被合并到组件模板的渲染上下文中。

const App = {
    setup(){
        // 为目标对象创建一个响应式对象
        const state = Vue.reactive({count: 0});
        function increment(){
            state.count++;
        }
              // 返回一个对象,该对象上的属性可以在模板中使用
        return {
            state,
            increment
        }   
    }
};

setup() 函数返回的对象有两个属性,一个是响应式对象(即为原始对象创建的代理对象),另一个是函数。在 DOM 模板中,可以直接使用这两个属性。如下:

<button @click="increment">count 值:{{ state.count }}</button>

需要注意的是,当和现有的基于选项的 API 一起使用时,从 setup() 函数返回的属性在选项中可以通过 this 访问。
setup() 函数可以接受两个可选参数,第一个参数是已解析的 props ,通过该参数可以访问在 props 选项中定义的 prop。如下:

app.component('PostItem',{
    // 声明 props
    props:['postTitle'],
    setup(props){
        console.log(props.postTitle);
    }
})

setup() 函数接受的 props 对象是响应式的,也就是说,在组件外部传入新的 prop 值时,props 对象也会更新,可以调用 watchEffect() 或 watch() 方法监听对象并对更改做出响应。如下:

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
</head>

<body>
    <div id="app">
        <post-item :post-title="title"></post-item>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const app = Vue.createApp({
            data() {
                return {
                    title: '扁扁'
                }
            }
        });
        app.component('PostItem', {
            //声明props
            props: ['postTitle'],
            setup(props) {
                Vue.watchEffect(() => {
                    console.log(props.postTitle);
                })
            },
            template: '<h3>{{ postTitle }}</h3>'
        });
        const vm = app.mount('#app');
    </script>
</body>

</html>

在谷歌浏览器中打开页面,在 console 窗口中输入 vm.title=“圆圆” ,会看到除了页面内容发生更新外,Console 窗口中也会输出“圆圆”。如下:
在这里插入图片描述

注意:不要去结构 props 对象,否则会失去响应性。如下:

app.component('PostItem', {
    //声明props
    props: ['postTitle'],
    setup({postTitle}) {
        Vue.watchEffect(() => {
            // 不再是响应式的
            console.log(postTitle); 
        })
    }
});

同时也要注意,不要试图去修改 props 对象,否则,将得到一个警告。

setup() 函数接受的第二个可选参数是一个 context 对象,该对象是一个普通的 JavaScript 对象,它公开了 3 组件属性。代码如下:

const MyComponent = {
    setup(props,context){
        // 属性(非响应式)
        console.log(context.attrs)
        // 插槽(非响应式)
        console.log(context.slots)
        // 发出的事件(方法)
        console.log(context.emit)
    }
}

context 对象是一个普通的 JavaScript 对象,也就是说,他不是响应式的,这意味着可以安全地使用 ES6 的对象解构语法对 context 进行结构。

attrs 和 slots 是有状态的对象,当组件本身被更新时,他们也总是被更新。但 attrs 和 slots 对象本身并不是响应式的,所以不应该对它们进行解构,并始终将属性引用为 attrs.x 或 slots.x。如下:

  const MyComponent = {
      setup(props,{attrs}){
          // 在稍后阶段可能被调用的函数
          function onClick(){
              // 保证是最新的引用
              console.log(attrs.foo) 
          }
      }
  }

最后要强调的是,当 setup() 函数和选项 API 一起使用时,在 setup() 函数内部不要使用 this。因为 setup() 函数是在选项被解析之前调用的。也就是,在 setup() 函数内不能访问 data 、 computed、methods 组件选项。例如,下面的代码是错误的:

setup(){
	function onClick(){
    this // 并不是预期的 this
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小熊猫呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值