前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >初探 Vue 3.0 的组装式 API(二)

初探 Vue 3.0 的组装式 API(二)

作者头像
贤羽
发布2022-06-09 15:01:43
2750
发布2022-06-09 15:01:43
举报
文章被收录于专栏:贤羽的前端小栈

在 RC13 之后,Vue 推出了 3.0 正式版。之前我们尝试了使用新的组装式 API 实现响应式数据,并且和 Vue2 进行了简单对比。

今天继续看看其它日常使用方式的变化与对比吧。

(二)事件处理与 mixin 复用

1. 简单例子

Vue2 中,模板使用到的事件处理函数,通常都被放在 vm 构造参数的 methods 属性中,然后才能通过 v-on:<event>/@<event> 标记到对应 DOM 上:

代码语言:javascript
复制
<template>
    <div>
        <p>Count: {{count}}</p>
        <button @click="increase">Increase</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            count: 0,
        };
    },
    methods: {
        increase() {
            this.count += 1;
        },
    },
}
</script>

上面的 increase() 方法中,this 看似指向 methods 属性的对象,实际上和之前 data 返回对象一样,指向的其实是最终创建的 vm 对象,日常指代混乱。

  • data 中返回了数据模板,告知 vm 会有一个名为 count 的响应式数据;
  • methods 对象作为方法模板,告知 vm 需要创建一个名为 increase 的方法,供模板事件处理;
  • 两者看似属于不同的对象,甚至在 export default 对象中不处在同一层级,实际上 this 都指向了 vm 对象。

2. 使用组装式 API 实现

代码语言:javascript
复制
// Vue 3.0
import { ref } from 'vue';

export default {
    setup() {
        const count = ref(0);
        const increase = () => {
            count.value += 1;
        };
        return {
            count,
            increase,
        };
    },
};

在 Vue3 的 setup 中,对数据的改动,直接使用普通函数或箭头表达式对数据进行操作就行了,非常直观。

  • 事件处理函数和数据一起通过 return 返回给模板使用;
  • 数据与事件处理逻辑处于同一层级,可以编译前发现命名冲突等问题;
  • 而且便于收拢事件处理函数和相关数据的位置,提高代码可读性和可重构性。

3. 不再需要 mixin

(1) Vue2 的 mixin 实现

对于不同组件可复用的数据和事件处理函数关系,在 Vue2 中我们通常都是用 mixin 来完成的。

比如,不同页面都经常使用到一个 ajax 的网络请求方法,和一个请求状态数据 isRequestSending(可用于在模板内判断和调整界面展示和按键交互),过去的 Vue2 中通常这样实现:

代码语言:javascript
复制
// mixin-net.js
export default {
    data() {
        return {
            isRequestSending: false,
        };
    },
    methods: {
        async ajax(/* some params... */) {
            if (this.isRequestSending) {
                return { status: -1, msg: 'network busy' };
            }
            try {
                this.isRequestSending = true;
                return await fetch(/* some params... */);
            } catch (ex) {
                throw ex;
            } finally {
                this.isRequestSending = false;
            }
        }
    },
};
代码语言:javascript
复制
<!-- page-a.vue -->
<template>
    <div>
        <button @click="callAjax">call ajax</button>
        <p>is request sending: {{isRequestSending}}</p>
        <p>resonse: {{response}}</p>
    </div>
</template>

<script>
import mixinNet from './mixin-net.js';

export default {
    mixins: [ mixinNet ],
    data() {
        return {
            response: '',
        };
    },
    methods: {
        async callAjax() {
            this.response = await this.ajax(/* some params... */);
        },
    },
};
</script>

可以看出,因为之前 vm 构造参数导致 this 指代混乱的问题,Vue2 中组件的可复用逻辑只好使用 mixin 的方式,将一个与构造参数结构一致的对象混合到一起来实现。

以至于这个 mixin 的结构,同样继承了组件构造参数的毛病。

而且引入 mixin 之前,无法通过标准 es 模块结构分析可用的数据、方法和钩子函数。必须解读参数中字段,甚至函数返回值,才能得知复用逻辑的大致结构。

(2) Vue3 的方案

Vue3 中,你可以使用类似构造函数的结构,在组件中取到返回值后,直接解构使用:

代码语言:javascript
复制
// net.js
import { ref } from 'vue';

export default {
    setup() {
        const isRequestSending = ref(false);
        const ajax = async () => {
            if (isRequestSending.value) {
                return { status: -1, msg: 'network busy' };
            }
            try {
                isRequestSending.value = true;
                return await fetch(/* some params... */);
            } catch (ex) {
                throw ex;
            } finally {
                isRequestSending.value = false;
            }
        };
        return {
            isRequestSending,
            ajax,
        };
    },
};
代码语言:javascript
复制
<!-- page-a.vue -->
<template>
    <div>
        <button @click="callAjax">call ajax</button>
        <p>is request sending: {{isRequestSending}}</p>
        <p>resonse: {{response}}</p>
    </div>
</template>
<script>
import net from './net.js';

export default {
    setup() {
        const netMixin = net.setup();
        const { ajax } = netMixin;

        const response = ref('');
        const callAjax = async () => {
            response.value = await ajax(/* some params... */);
        };
        return {
            ...netMixin,

            response,
            callAjax,
        };
    },
};
</script>

也可以根据个人喜好和业务实际情况,考虑做进一步拆分,以便简化代码结构或者实现某些属性的单例控制等效果:

代码语言:javascript
复制
// net.js
import { ref } from 'vue';

export const isRequestSending = ref(false);

export const ajax = async () => {
    if (isRequestSending.value) {
        return { status: -1, msg: 'network busy' };
    }
    try {
        isRequestSending.value = true;
        return await fetch(/* some params... */);
    } catch (ex) {
        throw ex;
    } finally {
        isRequestSending.value = false;
    }
};

相比 Vue2 的 mixin,更加自由可控、清晰明了。


下一篇:《初探 Vue 3.0 的组装式 API(三)》

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-10-182,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • (二)事件处理与 mixin 复用
    • 1. 简单例子
      • 2. 使用组装式 API 实现
        • 3. 不再需要 mixin
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档