• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

alovajs / alova / #218

23 Oct 2024 03:16PM UTC coverage: 93.83% (-0.1%) from 93.949%
#218

push

github

web-flow
Merge pull request #570 from alovajs/changeset-release/main

ci: release

1605 of 1759 branches covered (91.25%)

Branch coverage included in aggregate %.

9618 of 10202 relevant lines covered (94.28%)

67.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.12
/packages/vue-options/src/mapAlovaHook.ts
1
import { isPlainObject } from '@alova/shared/function';
1✔
2
import { ObjectCls, trueValue } from '@alova/shared/vars';
1✔
3
import { computed, reactive, version } from 'vue';
1✔
4
import { UseHookCallers, UseHookMapGetter, VueHookMapperMixin } from '~/typings';
1✔
5
import { classifyHookExposure, extractWatches } from './helper';
1✔
6
import myAssert from './myAssert';
1✔
7

1✔
8
/**
1✔
9
 * 将useHook的返回值和操作函数动态映射到vueComponent上
1✔
10
 *
1✔
11
 * **本模块经历了一定的探索过程,如下:**
1✔
12
 * 1. 在beforeCreate中动态添加use hook数据和函数到$options中,发现在mapGetter中无法访问到完整的vueComponent数据;
1✔
13
 * 2. 在data函数中调用mapGetter并返回use hook数据,这样就避免了动态添加,但获取的数据还是不够完整,例如computed、injecting无法获取到;
1✔
14
 * 3. 为了让mapGetter中的this可以访问到完整的数据,如data、props、computed、injecting、setup、methods等,就必须在created及以后的生命周期触发函数,但发现dataKey无法动态通过$set挂载到vueComponent对象上,$set只能动态挂载data中的某个子对象中;
1✔
15
 * 4. 在data中先定义一个用于存放全部use hook数据的命名空间(例如叫alova_namespace),那在用户访问use hook数据时需要通过alova_namespace.xxx.loading,太麻烦了,希望可以减少一层;
1✔
16
 * 5. 希望使用computed来减少一层访问路径,但在created中无法自行动态挂载computed到vueComponent上;
1✔
17
 * 6. (1.x中的方案)想到通过Object.defineProperty自定义挂载use hook数据到vueComponent上,并作为代理访问,这样就实现了访问xxx.loading时实际访问的是alova_namespace.xxx.loading
1✔
18
 * 7. (2.x中的方案)为了适配alova@3.x,现在需要动态挂载计算属性到当前实例上,同时也希望消除watch属性需要辅助函数`mapWatcher`,先方案时使用`reactive`和`computed`来动态创建状态和计算属性并挂载到当前实例上,目前要求版本为vue@2.7.x和vue@3.x,将不再支持vue@2.7之前的版本
1✔
19
 *
1✔
20
 * @param mapGetter usehook映射函数,它将返回映射的集合
1✔
21
 * @returns vue mixins数组
1✔
22
 */
1✔
23
export default <UHC extends UseHookCallers>(mapGetter: UseHookMapGetter<UHC>) => {
1✔
24
  const mixinItem = {
6✔
25
    created(this: any) {
6✔
26
      const vm = this;
11✔
27
      const hookMapper = mapGetter.call(vm, vm);
11✔
28
      myAssert(isPlainObject(hookMapper), 'expect receive an object which contains use hook exposures');
11✔
29

11✔
30
      // 在created阶段遍历发送请求
11✔
31
      for (const dataKey in hookMapper) {
11✔
32
        // 可以在useHookReturns中通过_$c获取useHook的config对象引用,将vue对象和dataKey传入alova内部
10✔
33
        const useHookExposure = hookMapper[dataKey];
10✔
34
        const { __referingObj: referingObject } = useHookExposure;
10✔
35
        myAssert(
10✔
36
          !!referingObject,
10✔
37
          `the use hook exposure of key \`${dataKey}\` is not supported in vue options style.`
10✔
38
        );
10✔
39

10✔
40
        referingObject.component = vm;
10✔
41
        referingObject.dataKey = dataKey;
10✔
42
        const originalTrackedKeys = { ...referingObject.trackedKeys };
10✔
43
        const [states, computeds, fns] = classifyHookExposure(useHookExposure);
10✔
44
        referingObject.trackedKeys = originalTrackedKeys; // recovery trackedKeys
10✔
45

10✔
46
        // require the version of vue must be 3.x or 2.7.x
10✔
47
        myAssert(/^3|2\.7/.test(version), 'please upgrade vue to `2.7.x` or `3.x`');
10✔
48

10✔
49
        // 挂载响应式状态和计算属性
10✔
50
        const proxy = {};
10✔
51
        vm[dataKey] = proxy;
10✔
52
        const rectiveStates = reactive(states);
10✔
53
        for (const key in states) {
10✔
54
          ObjectCls.defineProperty(proxy, key, {
50✔
55
            get: () => {
50✔
56
              referingObject.trackedKeys[key] = trueValue;
152✔
57
              return rectiveStates[key];
152✔
58
            },
50✔
59
            set: value => {
50✔
60
              rectiveStates[key] = value;
23✔
61
              return value;
23✔
62
            }
23✔
63
          });
50✔
64
        }
50✔
65
        for (const key in computeds) {
10!
66
          const computedState = computed(computeds[key]);
×
67
          ObjectCls.defineProperty(proxy, key, {
×
68
            get: () => {
✔
69
              referingObject.trackedKeys[key] = trueValue;
50✔
70
              return computedState.value;
50✔
71
            }
50✔
72
          });
×
73
        }
×
74

10✔
75
        // 设置watchers
10✔
76
        const watchers = extractWatches(dataKey, vm, states, computeds);
10✔
77
        for (const watchingKey in watchers) {
10✔
78
          vm.$watch(watchingKey, watchers[watchingKey]);
7✔
79
        }
7✔
80

10✔
81
        // 将函数动态挂载到vue实例上
10✔
82
        for (const key in fns) {
10✔
83
          (vm as any)[`${dataKey}$${key}`] = function (...args: any) {
70✔
84
            return fns[key](...args);
26✔
85
          };
70✔
86
        }
70✔
87
      }
10✔
88
    }
10✔
89
  };
6✔
90
  return [mixinItem as VueHookMapperMixin<UHC>];
6✔
91
};
6✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc