Vue 3组合式API自定义Hook设计模式谈

前言

之前我写了一篇《为什么说组合式API解决了mixins的痛点?》,介绍了一下如何用函数封装代码,这种封装没什么深奥的道理,它既不属于构造函数,也不属于面向对象,顶多就是个闭包。它类似于React里的自定义Hook。

为什么Vue 2没人提到这种简单的设计模式?

原因也很简单,Vue 2的数据响应式基于Vue实例,任何数据都是实例上的数据,所以只能引入另一个.vue文件,做一次选项合并,而不能把数据和方法独立成.js文件。现在Vue 3的数据响应式基于Proxy,不依赖Vue实例,当然就可以写独立.js文件然后引入了。

那么,函数封装的模式,是不是可以用在组合式API里呢?当然能,而且也是推荐做法。

题目

比如现在一个组件,引入了3个Dialog子组件,我要为它们提供title、opened状态、submitDisabled(用来控制按钮是否可点击)……等等,还要提供几个方法。这三个Dialog组件的样子和代码各异,不适合合并。

代码怎么写?

按照基础教程,你要写let aDialogTitle = ...let bDialogTitle = ...let cDialogTitle = ...,是不是想死?

于是你打算试试设计模式,写成let aDialog = {title: ..., opened: ...}let bDialog = {title: ..., opened: ...}let cDialog = {title: ..., opened: ...},这特么跟选项式API也没什么区别,干嘛还要用组合式API呢?

于是你甚至打算用构造函数……打住,没那么复杂,用闭包就可以了。

方案

基础代码是这样:

let aDialogTitle = ...;
let aDialogOpened = ...;

function openADialog() {
  //...
}

闭包写法是这样:

function useADialog() {
  let title = ...;
  let opened = ...;

  function openDialog() {
    //...
  }

  return reactive(ADialog: {title, opened, openDialog});
}

在<template>里的用法举例:

<template>
  <ADialog v-if="ADialog.opened" />
</template>

在ref语法糖中的写法差别

常规写法举例

<template>
  <div class="hello" @click="x.c = x.c + 1">
    {{ x.c }}
  </div>
</template>

<script>
import { ref } from "vue";
export default {
  setup() {
    function x() {
      let c = ref(3);
      return {
        c,
      };
    }
    return reactive({x: x()});
  },
};
</script>

ref语法糖写法举例

<template>
  <div class="hello" @click="x.c = x.c + 1">
    {{ x.c }}
  </div>
</template>

<script setup>
import { reactive, ref } from "vue";

const x = (function () {
  let c = ref(3);
  return reactive({
    c,
  });
})();
</script>

差别

由于语法糖写法没有return,所以必须声明变量(x),而且必须使用自执行函数,才能将数据返给模板。常规写法没什么可说的。

返给模板的都得是Proxy对象。

如果模板不用x.c格式,也就是不用模块前缀,只写c,怎么做?

常规写法

太简单了,把return reactive({x: x()});改成return x();就行了,清爽!

语法糖写法

太复杂了,呵呵。你必须给返回的对象解构,也就是const {c} =,但是解构一定会丢失响应,所以还要用上toRefs包住自执行函数。

总之

常规写法 语法糖写法
模板加模块前缀 return reactive({x: x()})即可 return reactive({c})即可
模板不加模块前缀 无任何心智负担,无需reactive 需用:解构、toRefs、reactive

所以,采用Hook模式的话,是不是采用语法糖写法,你自己慎重考虑吧。

跨Hook调用数据和方法怎么做?

这时候,就不可在末行return执行Hook了,必须提前赋值给变量。以常规写法为例,比如:

<template>
  <div class="hello" @click="y.changeC">{{ x.c }}</div>
</template>

<script>
import { reactive, ref, shallowRef } from "vue";
export default {
  setup() {
    function useX() {
      let c = shallowRef(3);
      return {
        c,
      };
    }
    function useY() {
      function changeC() {
        x.c.value = 33;
      }
      return {
        changeC,
      };
    }
    const x = useX();
    const y = useY();
    return reactive({ x, y });
  },
};
</script>

总结

这个模式真的没什么深奥,setup(){}本身就是这种设计模式!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,200评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,526评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,321评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,601评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,446评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,345评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,753评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,405评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,712评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,743评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,529评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,369评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,770评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,026评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,301评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,732评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,927评论 2 336

推荐阅读更多精彩内容