위젯
프론트엔드 위젯은 페이지에 추가되어 일부 기능을 처리할 수 있는 독립적인 Vue 애플리케이션 또는 Vue 컴포넌트 트리입니다.
위젯의 좋은 예로는 사이드바 담당자와 사이드바 비밀 유지가 있습니다.
위젯을 설계할 때는 아래에 설명된 몇 가지 원칙을 따라야 합니다.
Vue Apollo가 필요함
모든 위젯은 동일한 스택(Vue + Apollo Client)을 사용해야 합니다.
이를 위해 애플리케이션 루트에 Vue Apollo를 추가하거나(위젯을 컴포넌트로 사용할 경우) 위젯에 직접 제공해야 합니다. 사이드바 위젯의 경우 issuable Apollo Client 및 Apollo Provider를 사용하세요:
import SidebarConfidentialityWidget from '~/sidebar/components/confidential/sidebar_confidentiality_widget.vue';
import { apolloProvider } from '~/graphql_shared/issuable_client';
function mountConfidentialComponent() {
new Vue({
apolloProvider,
components: {
SidebarConfidentialityWidget,
},
/* ... */
});
}
필수 주입
모든 편집 가능한 사이드바 위젯은 SidebarEditableItem
를 사용하여 축소/확장 상태를 처리해야 합니다. 이 컴포넌트는 애플리케이션 루트에 제공된 canUpdate
속성이 필요합니다.
전역 상태 매핑 없음
위젯을 가능한 한 재사용 가능하게 만드는 것이 목표입니다. 그렇기 때문에 위젯이나 그 자식 컴포넌트에 외부 상태 바인딩을 추가하는 것은 피해야 합니다. 여기에는 Vuex 매핑 및 중재 저장소가 포함됩니다.
위젯의 책임
위젯은 설계된 엔터티(담당자, 반복주기 등)를 가져오고 업데이트하는 책임이 있습니다.
이는 위젯이 항상 데이터를 가져와야 함을 의미합니다(이미 Apollo 캐시에 없는 경우).
위젯에 초기 값을 제공하더라도, 백그라운드에서 GraphQL 쿼리를 수행하여 Apollo 캐시에 저장해야 합니다.
결국, Apollo Client 캐시가 전역 애플리케이션 상태가 되면, 사이드바 위젯에 초기 데이터를 전달할 필요가 없게 됩니다. 그러면 위젯은 캐시에서 데이터를 검색할 수 있습니다.
GraphQL 쿼리 및 변형 사용
위젯이 다양한 엔터티(에픽, 이슈, 병합 요청 등)와 작업할 수 있도록 유연해야 합니다.
서로 다른 사이드바에 대해 서로 다른 GraphQL 쿼리 및 변형이 필요하기 때문에 매핑을 생성합니다:
export const assigneesQueries = {
[TYPE_ISSUE]: {
query: getIssueParticipants,
mutation: updateAssigneesMutation,
},
[TYPE_MERGE_REQUEST]: {
query: getMergeRequestParticipants,
mutation: updateMergeRequestParticipantsMutation,
},
};
쿼리 업데이트에 대해 동일한 논리를 처리하기 위해 쿼리 필드를 별칭으로 설정합니다. 예를 들어:
-
group
또는project
는workspace
가 됨 -
issue
,epic
, 또는mergeRequest
는issuable
이 됨
불행하게도, Apollo는 별칭이 지정된 필드에 typename
이 undefined
인 값을 할당하므로, __typename
을 명시적으로 가져와야 합니다:
query issueConfidential($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
__typename
issuable: issue(iid: $iid) {
__typename
id
confidential
}
}
}
다른 Vue 애플리케이션과의 통신
위젯 상태의 변경 사항을 (예: 성공적인 변형 후) 부모 애플리케이션에 통신해야 하는 경우, 이벤트를 발생시켜야 합니다:
updateAssignees(assigneeUsernames) {
return this.$apollo
.mutate({
mutation: this.$options.assigneesQueries[this.issuableType].mutation,
variables: {...},
})
.then(({ data }) => {
const assignees = data.issueSetAssignees?.issue?.assignees?.nodes || [];
this.$emit('assignees-updated', assignees);
})
}
때때로 우리는 NotesApp
와 같은 다른 Vue 애플리케이션에서 변경 사항을 듣고 싶어 합니다.
이 경우, 클라이언트를 가져오고 특정 쿼리를 수신하는 렌더링이 없는 구성 요소를 사용할 수 있습니다:
import { fetchPolicies } from '~/lib/graphql';
import { confidentialityQueries } from '~/sidebar/constants';
import { defaultClient as gqlClient } from '~/graphql_shared/issuable_client';
created() {
if (this.issuableType !== IssuableType.Issue) {
return;
}
gqlClient
.watchQuery({
query: confidentialityQueries[this.issuableType].query,
variables: {...},
fetchPolicy: fetchPolicies.CACHE_ONLY,
})
.subscribe((res) => {
this.setConfidentiality(issuable.confidential);
});
},
methods: {
...mapActions(['setConfidentiality']),
},
Merge Request 위젯
Merge Request 위젯 프레임워크에 대한 문서를 참조하세요.