Skip to content

FAQ

Question List

Q1: How to use $global in non-component files?

javascript
// utils/helper.js
let globalService = null;

export const setGlobalService = (service) => {
  globalService = service;
};

export const useGlobal = () => {
  if (!globalService) {
    throw new Error('Global service not initialized');
  }
  return globalService;
};

// main.js or App.vue
import { setGlobalService } from './utils/helper';

const $global = inject('$global');
setGlobalService($global);

Q2: When is it necessary to pass true for computed properties?

When you need to use theme colors reactively in computed or watch, you should pass true:

javascript
// ✅ Reactive
const color = $tc('primary.main', true);
watch(color, (newColor) => {
  // Triggers when the theme switches
});

// ❌ Non-reactive
const color = $tc('primary.main');
// Will not update when the theme switches

Q3: How to clear all attention components?

Availability:
Scifi
Base
Admin
Prime
javascript
const { 
  $tMessageCloseAll,
  $tNotifyCloseAll,
  $tToastClose,
  $tFlashClose
} = inject('$global');

const clearAllAttentions = () => {
  $tMessageCloseAll();
  $tNotifyCloseAll();
  $tToastClose();
  $tFlashClose();
};

Q4: What are the differences between adaptive modes?

  • fixed: Fixed layout, does not respond to window changes.
  • flexible: Elastic layout, scales proportionally.
  • stretch: Stretch layout, fills available space.
  • extension: Extension layout, intelligently adapts to multiple scenarios.
  • disabled: Disables adaptation.

Q5: How to judge device type?

vue
<script setup>
import { inject, computed } from 'vue';

const { $deviceInfo } = inject('$global');

const isMobile = computed(() => 
  $deviceInfo.value.type === 'mobile' || 
  $deviceInfo.value.touchable
);

const isTablet = computed(() => 
  $deviceInfo.value.type === 'tablet'
);
</script>

<template>
  <div v-if="isMobile">Mobile Interface</div>
  <div v-else-if="isTablet">Tablet Interface</div>
  <div v-else>Desktop Interface</div>
</template>

Q6: How does Admin's keepAlive work?

Availability:
Scifi
Base
Admin
Prime
vue
<script setup>
import { inject } from 'vue';
import { useRoute } from 'vue-router';

const route = useRoute();
const { tabAdd, keepAliveAdd, $AKeepAlive } = inject('$global');

// Open new tab and enable cache
const openCachedPage = (routeConfig) => {
  // Add tab
  tabAdd({
    meta: {
      label: 'UserList',
      keepAlive: true
    },
    path: '/user/list'
  });
  
  // Add to cache list
  keepAliveAdd({ label: 'UserList' });
};
</script>

<template>
  <router-view v-slot="{ Component }">
    <keep-alive :include="$AKeepAlive">
      <component :is="Component" />
    </keep-alive>
  </router-view>
</template>

Notes

  1. Reactive Usage: State values automatically unwrap .value in templates, but must be accessed manually in <script>.
  2. Computed Properties: Remember to pass the true parameter when using methods like $tc to retrieve computed properties.
  3. Attention Sorting: Use $tAttentionDispatcher to uniformly manage the display order of multiple reminder components.
  4. Theme Switching: Ensure the theme is registered in the system before switching.
  5. Admin Features: Related functions can only be used when isActAdminFeatures is true.
  6. Encrypted Storage: It is recommended to use tStoreCrypto for storing sensitive data.
  7. Reload Selection: Use softReload() when state needs to be preserved, and hardReload() when a complete refresh is required.
  8. Route Query: Using updateRouteQuery will not trigger a page refresh, making it suitable for dynamically updating URL parameters.
  9. Floater Mounting: It is recommended to use $optFloaterTo instead of directly using $gFloaterTo, as the former intelligently selects based on the adaptive state.
  10. I18n Initialization: Call initI18n() at application startup to ensure language data is loaded.

Best Practices

Performance Optimization

vue
<script setup>
import { inject, computed } from 'vue';

const { $gTheme, $tc } = inject('$global');

// ✅ Good Practice: Use computed property
const primaryColor = $tc('primary.main', true);

// ❌ Avoid: Repeated calls in template
// <div :style="{ color: $tc('primary.main') }"></div>
</script>

Conditional Rendering

vue
<script setup>
import { inject } from 'vue';

const { 
  isActAdminFeatures,
  isActEchartsFeatures,
  $ADMIN 
} = inject('$global');
</script>

<template>
  <AdminPanel v-if="isActAdminFeatures" />
  <ChartComponent v-if="isActEchartsFeatures" />
</template>

Error Handling

vue
<script setup>
import { inject } from 'vue';

const { $tLoading, $tLoadingClose, $tMessage } = inject('$global');

const handleAction = async () => {
  $tLoading({
    appendTo:"#app",
    visible: true,
    desc:'Processing...',
    spinner: 'ringA'
  });
  
  try {
    await performAction();
    $tMessage({ type: 'success', content: 'Operation successful' });
  } catch (error) {
    $tMessage({ 
      type: 'error', 
      content: error.message || 'Operation failed'
    });
  } finally {
    $tLoadingClose();
  }
};
</script>

Theme Adaptation

vue
<script setup>
import { inject, computed } from 'vue';

const { $gThemeScheme, $tc } = inject('$global');

// In extremely rare cases, dynamically adjust styles based on the theme's light/dark scheme.
// Usually, this is not needed.
const echartsStyle = computed(() => ({
  backgroundColor: $gThemeScheme.value === 'dark' 
    ? $tc('common.bg') 
    : $tc('primary.base'),
  color: $gThemeScheme.value === 'dark'
    ? '#fff'
    : '#333'
}));
</script>

Reactive Listening

vue
<script setup>
import { inject, watch } from 'vue';

const { $gResizeCounter, $gTheme } = inject('$global');

// Listen for window size changes
watch($gResizeCounter, (newVal) => {
  console.log('Window resized', newVal);
  // Execute responsive layout adjustment
});

// Listen for theme changes
watch($gTheme, (newTheme) => {
  console.log('Theme switched to', newTheme);
  // Execute theme-related processing
});
</script>

Component Communication

Using provide/inject for component communication is more recommended. The data bus method of communication is used in TechUI's Tui3DPanel for communication between all peer Panel components of the same type.

vue
<script setup>
import { inject, onMounted, onUnmounted } from 'vue';

const { $tBus } = inject('$global');

onMounted(() => {
  // Listen for global events
  $tBus.on('dataUpdate', handleDataUpdate);
});

onUnmounted(() => {
  // Clean up listeners
  $tBus.off('dataUpdate', handleDataUpdate);
});

const handleDataUpdate = (data) => {
  console.log('Received data update', data);
};

const notifyOthers = () => {
  // Emit global event
  $tBus.emit('dataUpdate', { id: 1, name: 'test' });
};
</script>

Secure Storage

vue
<script setup>
import { inject } from 'vue';

const { tStoreCrypto, openEnc, openDec } = inject('$global');

// Store sensitive data
const saveUserCredentials = (credentials) => {
  // Method 1: Use tStoreCrypto
  tStoreCrypto.s('local','userCred', credentials);
  
  // Method 2: Use openEnc/openDec
  const encrypted = openEnc(credentials);
  localStorage.setItem('userCred', encrypted);
};

// Read sensitive data
const loadUserCredentials = () => {
  // Method 1
  return tStoreCrypto.g('local','userCred');
  
  // Method 2
  const encrypted = localStorage.getItem('userCred');
  return openDec(encrypted);
};
</script>

Released under the MIT License.