![](/img/trans.png)
[英]Does Vue can import component by dependency inject(DI) like angular?
[英]Does Vue 3 support something like Angular-Services?
Vue 是一個 UI 框架,它沒有專門的服務實體,由開發人員來實現它們。 同樣與 Angular 不同的是,Vue 不提供依賴注入(DI) 功能。
在 Vue 中,可重用的組件代碼應該由可組合或可組合函數提供,它們的反應性是通過組合 API 實現的:
// Usage: service = useLocalService()
const useLocalService = () => {
const someState = reactive({});
const someAction = () => /* change state */;
return { someState, someAction }
};
對於 Angular 中固有的全局單例服務,服務狀態在模塊中定義並評估一次,因此它在應用程序中共享:
// Usage: import * as service from '...';
export const someGlobalState = reactive({});
export const someGlobalAction = () => /* change state */;
將其包裝在可組合函數中以保持一致性是否有益取決於以下情況:
// Usage: service = useGlobalService()
const someGlobalState = reactive({});
const someGlobalAction = () => /* change state */;
const useGlobalService = () => {
return { someGlobalState, someGlobalAction }
};
在 Angular 2 或更高版本中,DI 容器允許為每個組件層次結構提供服務實例。 在 Vue 中,這是通過provide
/ inject
來完成的:
// Usage in a parent: setupRootOrNestedService()
const setupRootOrNestedService = () => {
const someRootOrNestedState = reactive({});
const someRootOrNestedAction = () => /* change state */;
provide('rootOrNestedService', { someRootOrNestedState, someRootOrNestedState });
};
// Usage in a child: service = useRootOrNestedService()
const useRootOrNestedService = () => {
return inject('rootOrNestedService');
};
這允許在任何級別通過令牌識別服務,並從使用 DI 模式中受益。
Pinia
(一個 Vue 商店)庫提供受Flux 模式影響的輕量級狀態管理。 它依賴於組合 API 並允許多個商店。 結果與上面類似,增加了代碼約定、擴展的 Vue 開發工具、正確的 TypeScript 類型和插件層:
// Usage as local service: service = useLocalOrGlobalService()
// Usage as global service: export default useLocalOrGlobalService()
// And: import * as service from '...';
const useLocalOrGlobalService = () => {
return defineStore('localOrGlobalService' + random(), {
state: () => ({}),
actions: {
someAction() { /* change state */ }
}
})
};
Pinia 不限制將 store 實例化並提供給組件的方式,因此它可以在必要時與provide
/ inject
結合使用。
僅供記錄:這是我想出的,作為簡單的示例代碼。 首先我寫了一個小服務:
import { reactive } from "vue";
export const objectService = {
objects: reactive([]), // reactive is important, otherwise it doesn't work
start: function(){
for (var i = 0; i < 10; i++)
((j)=>{
setTimeout(()=> // I use setTimeout as example for an async operation
objectService.objects.push({value: j}), 1000);
})(i);
}
};
這里的重點是,服務在異步操作中操縱狀態(在真實的實時系統中,休息調用或對 indexedDb 的訪問等)。
現在有兩個組件在兩個獨立的 Vue 應用程序中運行。 它們在單獨的應用程序中運行的原因超出了這里的問題范圍。 應用程序1:
<template>
<!--App1.vue-->
<p>Here is App1</p>
<div v-for="obj,ix in objectService.objects" :key="ix">{{obj.value}}
<input v-model="obj.value" />
</div>
</template>
<script>
import { defineComponent } from 'vue';
import { objectService } from '../services/object-service.js';
const App1 = defineComponent({
setup() {
return { objectService };
},
})
export default App1;
</script>
應用 2:
<template>
<!--App2.vue-->
<p>Here is App2</p>
<div v-for="obj,ix in objectService.objects" :key="ix">{{obj.value}}
<input v-model="obj.value" />
</div>
</template>
<script>
import { defineComponent } from 'vue';
import { objectService } from '../services/object-service.js';
const App2 = defineComponent({
setup() {
// const os = objectService;
objectService.start();
return { objectService };
},
})
export default App2;
</script>
這兩個組件是相同的,但有一個例外:App2 調用服務的啟動方法。 結果顯示在兩個組件中。 並且每個組件都可以改變狀態,這會立即反映在另一個組件中。
整個解決方案的重點是在服務中使用 reactive({})。 我希望,這對某人有用。
再次感謝 Estus Flask 和 hc_dev 為我指明了正確的方向。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.